Skip to content
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

feat(esm): expose User-Agent header #43852

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open

Conversation

Fyko
Copy link

@Fyko Fyko commented Jul 15, 2022

Closes #43851

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/modules

@nodejs-github-bot nodejs-github-bot added esm Issues and PRs related to the ECMAScript Modules implementation. needs-ci PRs that need a full CI run. labels Jul 15, 2022
@bmeck
Copy link
Member

bmeck commented Jul 15, 2022 via email

@guybedford
Copy link
Contributor

Perhaps this default with an environment variable to customize makes sense. Definitely seems a useful feature.

@aduh95 aduh95 added the semver-minor PRs that contain new features and should be released in the next minor version. label Jul 17, 2022
@ErickWendel
Copy link
Member

hey, @Fyko would you mind adding tests for this feature?

@Fyko
Copy link
Author

Fyko commented Aug 8, 2022

hey, @Fyko would you mind adding tests for this feature?

I would love to! Except... I'm not quite sure how. Could you point me in the right direction? @ErickWendel

Edit: did some searching, this looks relevant c0f4289c65

@ErickWendel
Copy link
Member

hey, @Fyko would you mind adding tests for this feature?

I would love to! Except... I'm not quite sure how. Could you point me in the right direction? @ErickWendel

Edit: did some searching, this looks relevant c0f4289c65

Sure. I think it'd be easier if you go to this file

assert.strictEqual(response.statusText, 'OK');
and add an assertion for the User-Agent

assert.strictEqual(response.headers["User-Agent"], `Node.js/${process.version}`);

WDYT?

@Fyko
Copy link
Author

Fyko commented Aug 8, 2022

Not quite sure if that would work considering the UA logic was added to fetch_module.js.

I found the file https://github.com/nodejs/node/blob/main/test/es-module/test-http-imports.mjs and considered adding:

if (_req.getHeaders()['user-agent'] !== `Node.js/${process.version}`) {
	res.writeHead(400);
	res.end('bad user-agent');
	return;
}

right after the createServer call

const server = createServer(function(_req, res) {

@ErickWendel
Copy link
Member

ErickWendel commented Aug 8, 2022

I suggested going to the tests-fetch file as it ensures what are the default values returned from the fetch response.

As your change will affect fetch.get adding by default the User Agent flag I think this might be the best place to check it out.

The file you mentioned has another goal. There you'd test the behavior when importing a module from an URL such as import module from "HTTP://domain/mymodule"

Not quite sure if that would work considering the UA logic was added to fetch_module.js.

Even though the logic was added to fetch_module, the test-fetch actually uses it (but notice that fetch is a global object that's why it's not being imported there)

WDYT?

@ErickWendel
Copy link
Member

ErickWendel commented Aug 9, 2022

It seems the test you made is returning undefined. Was it working on your local environment? Lmk if you need something 🤩

@ErickWendel
Copy link
Member

Hey @Fyko do you need any help on this?

@Fyko
Copy link
Author

Fyko commented Aug 25, 2022

I'll get around to this tomorrow. Sorry for the delay!

@@ -52,6 +52,9 @@ function HTTPSGet(url, opts) {
});
return https.get(url, {
agent: HTTPSAgent,
headers: {
'User-Agent': `Node.js/${process.version}`,
},
Copy link
Member

Choose a reason for hiding this comment

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

I'm -1 on always setting this. It should be optional and default turned off.

Copy link
Member

Choose a reason for hiding this comment

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

How do other server-side runtimes behave?

Copy link
Author

@Fyko Fyko Sep 7, 2022

Choose a reason for hiding this comment

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

My inspiration for this was how Deno sets the User-Agent header when getting packages. I don't quite understand why so many people are against this -- many very popular packages and utilities do this. Curl sets a header. So does node-fetch. List goes on. And it's completely nonsensical to use some type of env var to set the header.

Copy link
Member

Choose a reason for hiding this comment

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

“many people do x” isn’t ever a justification; many people do many ill-advised things.

The advantages i can see of setting it by default is easier debugging on the other end - the disadvantages i see is that a server could identify, track, and treat differently a request coming from node vs from other sources.

Copy link
Member

Choose a reason for hiding this comment

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

Deno sets the User-Agent header when getting packages. I don’t quite understand why so many people are against this – many very popular packages and utilities do this. Curl sets a header. So does node-fetch.

If most non-browser clients set a User-Agent header, then it’s a de facto standard and we should do the same. It doesn’t matter if some of us disagree with the wisdom of the practice; the point of adding APIs like fetch is to be more standards-compliant and similar to other clients. If users want network requests without User-Agent, they can just override the default or use some other API.

Copy link

Choose a reason for hiding this comment

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

Understanding the concerns about default behavior is essential. While many popular utilities set the User-Agent header by default, there are legitimate concerns regarding potential server-side differentiation based on this header. However, aligning with common practices across other clients could indeed enhance standards compliance.

Perhaps we can consider an optional flag for users to toggle the inclusion of the User-Agent header, offering both flexibility and adherence to commonly accepted practices. This could cater to different user preferences without compromising on standards.

Copy link
Member

Choose a reason for hiding this comment

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

Please god not yet another flag. But yes some way to customize this behavior would be good.

@Fyko
Copy link
Author

Fyko commented Sep 15, 2022

@jasnell @guybedford @bmeck

this pr has my attention again, and im adamant about getting this done. if not a default User-Agent, what would you suggest? env var? what would you name it? NODE_MODULE_FETCH_UA=node/16.x.x? i feel it would be better to be a toggle.

@GeoffreyBooth
Copy link
Member

if not a default User-Agent

I think we should set it by default, and users could override it on a per-fetch basis:

fetch(url, { headers: { 'User-Agent': 'whatever' } })

If we need a global override, that could happen later.

@Fyko
Copy link
Author

Fyko commented Sep 15, 2022

i think you're misunderstanding.
the purpose of my PR is to implement the User-Agent header only when fetching remote modules -- URL imports

@GeoffreyBooth
Copy link
Member

i think you’re misunderstanding. the purpose of my PR is to implement the User-Agent header only when fetching remote modules – URL imports

You mean --experimental-network-imports? I think it should apply to all fetch calls, both as a result of network imports and user code. I don’t think Node’s calls need a way to be customized.

@Fyko
Copy link
Author

Fyko commented Sep 15, 2022

Got it, just making sure we're on the same page. I'm not exactly sure what to do here -- I've got conflicting opinions from different members. I'm going to fix my tests so CI passes and we'll see what happens! 🤗

@GeoffreyBooth
Copy link
Member

GeoffreyBooth commented Sep 15, 2022

Got it, just making sure we’re on the same page. I’m not exactly sure what to do here – I’ve got conflicting opinions from different members. I’m going to fix my tests so CI passes and we’ll see what happens! 🤗

#43851 doesn’t mention this applying to only --experimental-network-imports, so I think maybe that issue could be used to debate what we want the intended behavior should be, and this PR discussion could be restricted to technical discussion of the implementation of whatever design we settle on. We shouldn’t land something until we have a decision regarding what we want. If we don’t reach consensus in discussion on that thread it can go to the TSC for a vote.

Also, please always rebase on main rather than merging main into your branch.

The issue was that on L133, the headers object being passed through was overwriting the user-agent header.
I've reformatted the `opts` spread so the only way to over-write the header is to explicitily define it
@renhiyama
Copy link

Any updates on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. needs-ci PRs that need a full CI run. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

esm(network imports): expose User-Agent header