-
Notifications
You must be signed in to change notification settings - Fork 117
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
Set User-Agent header to window.navigator.userAgent #1237
Conversation
…adme Remove dead --experimental-worker references from README.md
Auto-enter tutorial.html
Unlock macos swap hacks
Added onbeforeload flag
…ead of the document
Add CanvasRenderingContext2D::setLineDash
HTMLLinkElement load emit timing
Emulate HTMLIFrameElement contentWindow/contentDocument better
Capture Buffer global in local closures in src
[Web Workers] Navigator
I think this is fine, but is there a plan to cover the rest of the cases here? It seems that currently this PR adds disparity by fixing the one call point only. |
Done. |
5b27f89
to
58ff970
Compare
I updated this PR with the latest changes from master. It seems to cover all the cases you outlined. If you feel it's sufficient, then it's ready to merge. |
src/Window.js
Outdated
@@ -102,6 +102,7 @@ const { | |||
GlobalContext.id = id; | |||
GlobalContext.args = args; | |||
GlobalContext.version = version; | |||
GlobalContext.userAgent = `Mozilla/5.0 (OS) AppleWebKit/999.0 (KHTML, like Gecko) Chrome/999.0.0.0 Safari/999.0 Exokit/${GlobalContext.version}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't add anything new to GlobalContext
unless there is no other way, Ideally, GlobalContext
is deleted entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can fetch
pull from the global navigator
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any suggestions? The only alternative I can think of is to move this line into src/fetch.js
. But then it will still depend on GlobalContext.version
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be a method on window-fetch
that sets the interception user agent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I've updated the code. src/fetch.js
now pulls from Navigator.userAgent
, which is a static get userAgent() { .... }
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, the navigator
should be a global in all cases, where the userAgent
can be accessed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense, but I don't think it needs to be a static. We could just access the navigator
instance without adding any new data shapes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The navigator
instance is per-window, and there can be multiple windows. As far as I know, there isn't a concept of "the global window
value", so src/fetch.js
can't really call window.navigator.userAgent
unless the user passes in window
, which would complicate the interface.
I think exokit wanted a constant, un-configurable User-Agent string, if I remember our conversation correctly from a few months ago when I proposed a configurable User-Agent string. If so, then it seems to make sense for it to be either attached to GlobalContext
or a static getter on Navigator
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know, there isn't a concept of "the global window value"
There is, in the specs. For our purposes that is simply global
, as set up by node
. I think this should work for all of the worker cases, as well as window
.
const GlobalContext = require('./GlobalContext'); | ||
const fetch = require('window-fetch'); | ||
|
||
Object.assign(module.exports, fetch); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't the usual way we export in the rest of the codebase. It's usually
module.exports.fetch = fetch;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/fetch.js
needs to export everything that window-fetch
exports, including Header
, Request
, Response
, and Blob
. This accomplishes that.
The idea is that src/fetch.js
is a drop-in replacement for window-fetch
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's the case, maybe it's best this is put upstream into window-fetch
as an interception API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mm, I would say that overriding the User-Agent
header and forcing it to be a specific value is a browser-specific concern. It might be nice if window-fetch
provided a way to do that, but the tradeoff is that the API becomes more complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's cleaner than requiring a hack to collect and re-export properties from the module.
window-fetch
is designed to implement the needs of a "browser", and setting a User-Agent is one of the spec requirements of that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Malicious modules are a valid concern, but a malicious module could do much worse than setting a User-Agent -- and it's not clear that that itself would be a problem regardless.
The API wouldn't necessarily need to be forceTheUserAgentStringToBe
-- it could be options on a constructor on the import. This would be roughly equivalent to fetch.js
, except owned by window-fetch
instead of Exokit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine -- Exokit allows user code to spoof.
Chrome does not: https://developer.chrome.com/multidevice/user-agent
You can reconfigure the user-agent string via extensions (https://chrome.google.com/webstore/detail/user-agent-switcher-for-c/djflhoibgkdhkhhcedjiklpkjnoahfmg?hl=en-US) but it's switched globally; there's no such thing as overriding it on a per-request basis.
This is important to prevent userland JS from spoofing other devices. Google Analytics also relies on standard User-Agent values, so allowing users to override it can break GA.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those concerns are outside the scope of Exokit. Exokit is not a browser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. In that case, feel free to close this PR. I'll merge it into sweetiekit-dom which is what we bundle with SweetieKit.
That will fix our GA issue #1230
I was hoping to maintain parity with exokit's DOM implementation, but it sounds like it might take some time before the necessary functionality / fixes can be integrated into window-fetch
and published. The window-fetch
extensions also introduce risks due to the dependency on mutable global state.
It might be a better idea for us to switch over to the standard https://github.com/bitinn/node-fetch module. There are significant upstream differences, like support for stream.pipe
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds like it might take some time before the necessary functionality / fixes can be integrated into window-fetch and published.
Which timing does this refer to? It looks like most of that work is done in this PR.
The window-fetch extensions also introduce risks due to the dependency on mutable global state.
What are the risks?
There are significant upstream differences, like support for stream.pipe.
Indeed, window-fetch
should pull from upstream.
Closes #1230
See JakeChampion/fetch#614 (comment)
This PR forces the User-Agent header of any
window.fetch
call to bewindow.navigator.userAgent
.(This behavior seems identical to what Chrome enforces.)