Skip to content

fix: ensure that Origin header is rewritten as necessary #4812

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 24, 2024

Conversation

petebacondarwin
Copy link
Contributor

@petebacondarwin petebacondarwin commented Jan 22, 2024

The wrangler dev command puts the Worker under test behind a proxy server. This proxy server should be transparent to the client and the Worker, which means that the Request arriving at the Worker with the correct url property, and Host and Origin headers.

Previously we fixed the Host header but missed the Origin header which is only added to a request under certain circumstances, such as cross-origin requests.

What this PR solves / how to test:

This change fixes the Origin header as well, so that it is rewritten, when it exists, to use the origin of the url property.

A nice way to test this is to simply clone the reproduction from #4761 - https://github.com/Le0Developer/wrangler-host-header-repro, then replace the local Miniflare with the pre-release one from this PR.

Fixes #4761

Author has addressed the following:

  • Tests
    • Included (updated worker-app fixture tests)
    • Not necessary because:
  • Changeset (Changeset guidelines)
    • Included
    • Not necessary because:
  • Associated docs
    • Issue(s)/PR(s):
    • Not necessary because: no user facing change

Sorry, something went wrong.

@petebacondarwin petebacondarwin requested a review from a team as a code owner January 22, 2024 21:17
Copy link

changeset-bot bot commented Jan 22, 2024

🦋 Changeset detected

Latest commit: 0337596

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
miniflare Patch
@cloudflare/pages-shared Patch
wrangler Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

github-actions bot commented Jan 22, 2024

A wrangler prerelease is available for testing. You can install this latest build in your project with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7631624262/npm-package-wrangler-4812

You can reference the automatically updated head of this PR with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/prs/4812/npm-package-wrangler-4812

Or you can use npx with this latest build directly:

npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7631624262/npm-package-wrangler-4812 dev path/to/script.js
Additional artifacts:
npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7631624262/npm-package-create-cloudflare-4812 --no-auto-update
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7631624262/npm-package-miniflare-4812
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7631624262/npm-package-cloudflare-pages-shared-4812

Note that these links will no longer work once the GitHub Actions artifact expires.


wrangler@3.24.0 includes the following runtime dependencies:

Package Constraint Resolved
miniflare workspace:* 3.20231218.3
workerd 1.20231218.0 1.20231218.0
workerd --version 1.20231218.0 2023-12-18

Please ensure constraints are pinned, and miniflare/workerd minor versions match.

Copy link

codecov bot commented Jan 22, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (77b0bce) 70.56% compared to head (0337596) 70.63%.
Report is 2 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4812      +/-   ##
==========================================
+ Coverage   70.56%   70.63%   +0.06%     
==========================================
  Files         290      290              
  Lines       15089    15089              
  Branches     3828     3828              
==========================================
+ Hits        10648    10658      +10     
+ Misses       4441     4431      -10     

see 7 files with indirect coverage changes

request.headers.set("Host", url.host);
// Only rewrite Origin header if there is already one
if (request.headers.has("Origin")) {
request.headers.set('Origin', url.origin);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooo this should be " instead of '. I guess we're not running miniflare's linting checks in CI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😱

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is purposefully ignored -

# Miniflare shouldn't be formatted with the root `prettier` version

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix up that formatting. But we should probably bring miniflare into the fold with the same prettier settings as the rest of the mono-repo. As far as I can tell the only difference is trailing commas.

Copy link
Contributor

@mrbbot mrbbot Jan 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the other difference is that Miniflare uses Prettier 3, whereas the rest use Prettier 2.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was basing it off of removing the prettier ignore and running the formatting fix up command at the root.

@petebacondarwin petebacondarwin force-pushed the pbacondarwin/fix-origin-header branch from 0de1e16 to 5f907e2 Compare January 23, 2024 15:51
The `wrangler dev` command puts the Worker under test behind a proxy server.
This proxy server should be transparent to the client and the Worker, which
means that the `Request` arriving at the Worker with the correct `url` property,
and `Host` and `Origin` headers.
Previously we fixed the `Host` header but missed the `Origin` header which is
only added to a request under certain circumstances, such as cross-origin requests.

This change fixes the `Origin` header as well, so that it is rewritten, when it exists,
to use the `origin` of the `url` property.

Fixes #4761

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@petebacondarwin petebacondarwin force-pushed the pbacondarwin/fix-origin-header branch from 7f2f623 to 0337596 Compare January 23, 2024 20:43
@petebacondarwin petebacondarwin added the e2e Run wrangler + vite-plugin e2e tests on a PR label Jan 24, 2024
@petebacondarwin petebacondarwin merged commit 8166eef into main Jan 24, 2024
@petebacondarwin petebacondarwin deleted the pbacondarwin/fix-origin-header branch January 24, 2024 09:55
@afonsocrg
Copy link

Hey @petebacondarwin and @mrbbot, I have a question regarding this PR and would be very grateful if you could clarify it for me 🙂

I am building an application that has a React frontend making requests to Cloudflare workers. Whenever any request is sent, the Origin header is correctly set in the browser (in my case to localhost:5173). However, when the worker starts processing it, that header has the same value of the request url (in my case localhost:8787). I checked with wireshark that the request is actually being sent with the correct Origin header, so I believe this change took place between the request being received and the worker starts processing it. The issue with this behavior is that without the original Origin header value, I cannot set the correct Access-Control-Allow-Origin header, making the frontend reject every response.

After looking at this PR, I noticed that the Origin header is being set in the following lines:

if (rewriteHeadersFromOriginalUrl) {
    request.headers.set("Host", url.host);
    // Only rewrite Origin header if there is already one
    if (request.headers.has("Origin")) {
        request.headers.set("Origin", url.origin);
    }
}

I'm having trouble figuring out why the Origin header needs to be set to the request url, and not to its original value (request.headers.get("Origin"), or no change at all, since the original request was used to build the new one). I would be very grateful if you could clarify that for me!

@petebacondarwin
Copy link
Contributor Author

@afonsocrg - happy to try to help. Can you confirm what version of Wrangler you are using, and exactly what your setup is here? It seems from what you are saying that you are running wrangler pages dev and testing this locally?
Also when you say that the request in the browser has the Origin set to localhost:5172, what is the actual request you are making? Are you setting the url to localhost:8787 but the Origin to localhost:5172?

@afonsocrg
Copy link

@petebacondarwin thanks for the fast reply!! This behavior happens only in versions 3.25 and 3.26. The worker was running using wrangler dev. If I ran with the --remote flag, I did not have this issue, but I'd rather not have to use that flag.

The React app is running on localhost:5173, and when it sends any request (OPTIONS, POST, etc.), the same happens: The browser sends the correct Origin header (localhost:5173, which is the endpoint the frontend is running), but the worker receives Origin: http://localhost:8787, which is incorrect. I changed the worker code to only print the headers and return an empty response, so the headers must have been modified before the worker code has been called.

I expected the headers to be the same as the ones sent by the browser, so that the wrangler layer is transparent to the worker

@petebacondarwin
Copy link
Contributor Author

How does the request get to the Worker if it is running at localhost:8787 and the browser is making a request to locahost:5173?

@afonsocrg
Copy link

Sorry, the frontend is running at localhost:5173, and is sending the requests to localhost:8787.
According to MDN, I believe the origin header should be set to localhsot:5173, and the Host header should be the one set to localhost:8787

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host

@petebacondarwin
Copy link
Contributor Author

This stuff is so confusing but here is my take on how this should work.

  • Host is where the request is going to, it is very likely going to match the request.url property since this is also what is used to route the request to the correct end point.
  • Origin (as noted in MDN) is effectively the server where the response being processed by a client originated from.

So as I understand it, if you have a web page hosted at localhost:5173 and you make a client side fetch() request to a server at localhost:8787, then the Request should have localhost:5173 as its Origin and localhost:8787 as its Host headers.

With that in mind, you might be right that something in our implementation is a bit off in our implementation of this fix, since we are reconstructing the Origin header from the request url origin, rather than the referring URL...

petebacondarwin added a commit that referenced this pull request Feb 7, 2024
In #4812 we tried to fix the Origin headers to match the Host header but were overzealous and rewrote Origin headers for external origins (outside of the proxy server's origin).

This is now fixed, and moreover we rewrite any headers that refer to the proxy server on the request with the configured host and vice versa on the response.

This should ensure that CORS is not broken in browsers when a different host is being simulated based on routes in the Wrangler configuration.
petebacondarwin added a commit that referenced this pull request Feb 8, 2024
In #4812 we tried to fix the Origin headers to match the Host header but were overzealous and rewrote Origin headers for external origins (outside of the proxy server's origin).

This is now fixed, and moreover we rewrite any headers that refer to the proxy server on the request with the configured host and vice versa on the response.

This should ensure that CORS is not broken in browsers when a different host is being simulated based on routes in the Wrangler configuration.
petebacondarwin added a commit that referenced this pull request Feb 9, 2024
In #4812 we tried to fix the Origin headers to match the Host header but were overzealous and rewrote Origin headers for external origins (outside of the proxy server's origin).

This is now fixed, and moreover we rewrite any headers that refer to the proxy server on the request with the configured host and vice versa on the response.

This should ensure that CORS is not broken in browsers when a different host is being simulated based on routes in the Wrangler configuration.
petebacondarwin added a commit that referenced this pull request Feb 9, 2024
…#4950)

fix: ensure we do not rewrite external Origin headers in wrangler dev

In #4812 we tried to fix the Origin headers to match the Host header but were overzealous and rewrote Origin headers for external origins (outside of the proxy server's origin).

This is now fixed, and moreover we rewrite any headers that refer to the proxy server on the request with the configured host and vice versa on the response.

This should ensure that CORS is not broken in browsers when a different host is being simulated based on routes in the Wrangler configuration.
@workers-devprod workers-devprod mentioned this pull request Feb 9, 2024
renovate bot referenced this pull request in Johannes-Andersen/Johannes Feb 13, 2024
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [wrangler](https://togithub.com/cloudflare/workers-sdk)
([source](https://togithub.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler))
| [`3.28.1` ->
`3.28.2`](https://renovatebot.com/diffs/npm/wrangler/3.28.1/3.28.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.28.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.28.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.28.1/3.28.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.28.1/3.28.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>cloudflare/workers-sdk (wrangler)</summary>

###
[`v3.28.2`](https://togithub.com/cloudflare/workers-sdk/blob/HEAD/packages/wrangler/CHANGELOG.md#3282)

[Compare
Source](https://togithub.com/cloudflare/workers-sdk/compare/wrangler@3.28.1...wrangler@3.28.2)

##### Patch Changes

- [#&#8203;4950](https://togithub.com/cloudflare/workers-sdk/pull/4950)
[`05360e43`](https://togithub.com/cloudflare/workers-sdk/commit/05360e432bff922def960e86690232c762fad284)
Thanks [@&#8203;petebacondarwin](https://togithub.com/petebacondarwin)!
- fix: ensure we do not rewrite external Origin headers in wrangler dev

In
[https://github.com/cloudflare/workers-sdk/pull/4812](https://togithub.com/cloudflare/workers-sdk/pull/4812)
we tried to fix the Origin headers to match the Host header but were
overzealous and rewrote Origin headers for external origins (outside of
the proxy server's origin).

This is now fixed, and moreover we rewrite any headers that refer to the
proxy server on the request with the configured host and vice versa on
the response.

This should ensure that CORS is not broken in browsers when a different
host is being simulated based on routes in the Wrangler configuration.

<!---->

- [#&#8203;4997](https://togithub.com/cloudflare/workers-sdk/pull/4997)
[`bfeefe27`](https://togithub.com/cloudflare/workers-sdk/commit/bfeefe275390491a7bb71f01550b3cb368d13320)
Thanks
[@&#8203;dario-piotrowicz](https://togithub.com/dario-piotrowicz)! -
chore: add missing `defineNavigatorUserAgent` dependency to useEsbuild
hook

<!---->

- [#&#8203;4966](https://togithub.com/cloudflare/workers-sdk/pull/4966)
[`36692326`](https://togithub.com/cloudflare/workers-sdk/commit/366923264fe2643acee0761c849ad0dc3922ad6c)
Thanks [@&#8203;penalosa](https://togithub.com/penalosa)! - fix: Report
Custom Build failures as `UserError`s

<!---->

- [#&#8203;5002](https://togithub.com/cloudflare/workers-sdk/pull/5002)
[`315a651b`](https://togithub.com/cloudflare/workers-sdk/commit/315a651b5742a614fd950c29b5dac5fdd2d1f270)
Thanks
[@&#8203;dario-piotrowicz](https://togithub.com/dario-piotrowicz)! -
chore: rename `getBindingsProxy` to `getPlatformProxy`

initially `getBindingsProxy` was supposed to only provide proxies for
bindings,
the utility has however grown, including now `cf`, `ctx` and `caches`,
to
clarify the increased scope the utility is getting renamed to
`getPlatformProxy`
    and its `bindings` field is getting renamed `env`

*note*: `getBindingProxy` with its signature is still kept available,
making this
    a non breaking change

- Updated dependencies
\[[`05360e43`](https://togithub.com/cloudflare/workers-sdk/commit/05360e432bff922def960e86690232c762fad284)]:
    -   miniflare@3.20240129.2

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/Johannes-Andersen/Johannes).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xNzMuMCIsInVwZGF0ZWRJblZlciI6IjM3LjE3My4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
e2e Run wrangler + vite-plugin e2e tests on a PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

🐛 BUG MF: host & origin header out of sync
3 participants