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

fix(http): remove outgoing headers normalization #3557

Conversation

marcinjahn
Copy link
Contributor

@marcinjahn marcinjahn commented Jan 21, 2023

Which problem is this PR solving?

The http auto-instrumentation should not modify the request in any other way than context injection. Currently, the library does modify the casing of request headers. Even though in theory that should not matter, there are servers that require incoming headers to have some predefined casing, e.g. all letters uppercase.

Fixes #3556

Short description of the changes

Remove the code that "normalizes" the request headers.

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

To test this, send a request with headers that are not lowercase. The target server should receive them as they were sent.

Checklist:

  • Followed the style guidelines of this project
  • Documentation has been updated

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Jan 21, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: marcinjahn / name: Marcin Jahn (4397853)

@marcinjahn marcinjahn force-pushed the feature/remove-header-normalization-in-http branch from 4397853 to eefce64 Compare January 21, 2023 09:27
@marcinjahn marcinjahn marked this pull request as ready for review January 21, 2023 09:27
@marcinjahn marcinjahn requested a review from a team January 21, 2023 09:27
@codecov
Copy link

codecov bot commented Jan 23, 2023

Codecov Report

Merging #3557 (92c5af9) into main (d1f9594) will decrease coverage by 0.01%.
The diff coverage is n/a.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3557      +/-   ##
==========================================
- Coverage   93.88%   93.88%   -0.01%     
==========================================
  Files         255      255              
  Lines        7757     7752       -5     
  Branches     1612     1611       -1     
==========================================
- Hits         7283     7278       -5     
  Misses        474      474              
Impacted Files Coverage Δ
...es/opentelemetry-instrumentation-http/src/utils.ts 99.17% <ø> (-0.02%) ⬇️
...emetry-core/src/platform/node/RandomIdGenerator.ts 87.50% <0.00%> (-6.25%) ⬇️
...ges/opentelemetry-instrumentation-http/src/http.ts 94.21% <0.00%> (+0.32%) ⬆️

@marcinjahn marcinjahn changed the title Remove headers normalization in outgoing HTTP requests fix(http) Remove outgoing headers normalization Jan 23, 2023
@marcinjahn marcinjahn force-pushed the feature/remove-header-normalization-in-http branch 2 times, most recently from bcdfe82 to 3f203e3 Compare January 23, 2023 13:31
@marcinjahn marcinjahn changed the title fix(http) Remove outgoing headers normalization fix(http): remove outgoing headers normalization Jan 23, 2023
@marcinjahn marcinjahn force-pushed the feature/remove-header-normalization-in-http branch from 3f203e3 to 82a2523 Compare January 24, 2023 07:08
Copy link
Member

@dyladan dyladan left a comment

Choose a reason for hiding this comment

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

Strongly agree. Why was this here to begin with?

@dyladan
Copy link
Member

dyladan commented Jan 24, 2023

Looks like this was added by @legendecas in 21fc8b5#diff-2a4dbbc8d99791ab2180a7b9c036458fa20b0e8175d677b7cd28099ed2ebf100R294-R298

@legendecas is there a reason to keep this code or was it just an oversight?

@Flarna
Copy link
Member

Flarna commented Jan 25, 2023

I assume it's used to ease request suppression in outgoing hook based on request headers. for incoming node http normalizes all headers to lowercase. For outgoing one gets what application uses so any sort of casing.

Another topic is maybe to ensure that we don't end up in having TraceParent form application next to traceparent added by instrumentation.

@marcinjahn
Copy link
Contributor Author

I assume it's used to ease request suppression in outgoing hook based on request headers. for incoming node http normalizes all headers to lowercase. For outgoing one gets what application uses so any sort of casing.

Another topic is maybe to ensure that we don't end up in having TraceParent form application next to traceparent added by instrumentation.

The second point definitely should be addressed, probably in a different PR though. The question is, what do do in such a case? Should the library prioritize the traceparent supplied with the request, or should it prioritize the one that it'd normally inject?

Btw, the build started to fail in an unexpected place, I looked through the commits that came in since I opened this PR, and none of them should be the reason. I'm not sure why builds fail.

@Flarna
Copy link
Member

Flarna commented Jan 25, 2023

Btw, the build started to fail in an unexpected place, I looked through the commits that came in since I opened this PR, and none of them should be the reason. I'm not sure why builds fail.

#3567 should fix this

@dyladan
Copy link
Member

dyladan commented Jan 25, 2023

I assume it's used to ease request suppression in outgoing hook based on request headers. for incoming node http normalizes all headers to lowercase. For outgoing one gets what application uses so any sort of casing.

it's possible to normalize for the hook without modifying the request. @marcinjahn what would you think about updating the PR to do that?

Another topic is maybe to ensure that we don't end up in having TraceParent form application next to traceparent added by instrumentation.

Lots of layers to this. I think questions around this are most likely best solved in the spec or even in the w3c spec before implementations start tackling them inconsistently.

@marcinjahn
Copy link
Contributor Author

marcinjahn commented Jan 25, 2023

it's possible to normalize for the hook without modifying the request. @marcinjahn what would you think about updating the PR to do that?

I could do that, only I am unsure if that's a good idea. If some client sends requests with non-lowercased headers, possibly there's some reason behind it, and the casing matters. Possibly, in the hook, the app would want to use these headers for something else (e.g., just logging). If lower-case headers are needed, it's not difficult for the app to lowercase them.

I say, let's not make such decisions for the users of the library. Doing the lower-casing on the library side is irreversible for the users, while leaving the headers in their original form gives them all the possibilities to do whatever they need to do.

Having said that, since you are the maintainers of the library, I'll add the lowercasing in the hook if you still think it's the right thing to do. Btw, do you mean the HttpInstrumentationConfig's requestHook? The config interfaca has quite a few hooks there :)

@marcinjahn
Copy link
Contributor Author

@dyladan Is there anything more to do or can this PR be merged?

@dyladan
Copy link
Member

dyladan commented Jan 27, 2023

If some client sends requests with non-lowercased headers, possibly there's some reason behind it, and the casing matters. Possibly, in the hook, the app would want to use these headers for something else (e.g., just logging). If lower-case headers are needed, it's not difficult for the app to lowercase them.

I say, let's not make such decisions for the users of the library. Doing the lower-casing on the library side is irreversible for the users, while leaving the headers in their original form gives them all the possibilities to do whatever they need to do.

Having said that, since you are the maintainers of the library, I'll add the lowercasing in the hook if you still think it's the right thing to do. Btw, do you mean the HttpInstrumentationConfig's requestHook? The config interfaca has quite a few hooks there :)

I was thinking about it mostly from a backwards compatibility perspective. There may be users depending on the lowercase behavior that we will break by undoing it. For example, they may be reading the 'authorization' key when their app is adding it as Authorization. Apps should not be differentiating between headers by case and should not be depending on casing in headers as they are specified to be case insensitive.

I guess I can go either way. I'm curious what the other @open-telemetry/javascript-maintainers think about this, particularly @legendecas but he is on vacation until the end of the month.

@marcinjahn
Copy link
Contributor Author

marcinjahn commented Jan 27, 2023

@dyladan Right, I agree with your perspective. Completely removing lower-casing might be breaking for some (although still, it might be undesirable for new users). To keep it working for existing users, I'll add the hook normalization. Again, would it be the requestHook that you were thinking about?

@dyladan
Copy link
Member

dyladan commented Jan 27, 2023

That's the one I was thinking of but I admit there may be others that I don't think of immediately.

@marcinjahn
Copy link
Contributor Author

Alright, let's await for @legendecas's input.

@legendecas
Copy link
Member

legendecas commented Jan 27, 2023

This was added to avoid header case-sensitivity duplications in the hooks. As defined in https://www.rfc-editor.org/rfc/rfc7230#section-3.2, HTTP header keys are case-insensitive. And Node.js already lowe-cased all incoming message's header keys so we don't have to perform anything particular. But this is not the case for the outgoing message since the header object can be an arbitrary object.

However, it is true that we should not prevent users from sending arbitrary case headers. I think the alternative here is using the original headers object to make the actual request and calling the hooks with the parsed one.

@Flarna
Copy link
Member

Flarna commented Jan 27, 2023

Client response and server request hooks have lowercase headers because node normalizes headers on receive.
Client request and server response get the data from user.

@dyladan
Copy link
Member

dyladan commented Jan 27, 2023

I think the alternative here is using the original headers object to make the actual request and calling the hooks with the parsed one.

That was my original recommendation as well

Client response and server request hooks have lowercase headers because node normalizes headers on receive.
Client request and server response get the data from user.

In the case of client response and server request hooks, we don't have to lowercase them because they're already lowercased.

In the case of client request and server response hooks, we should not modify the original request but it may be beneficial to provide normalized headers to the hooks. This satisfies backwards compatibility and also provides a consistent experience across all hooks.


Thinking about this a bit more though I am not so sure we should normalize the headers at all. The main drawback I can think of is that we may normalize in a different way than the runtime. If there is an outgoing request with MyHeader and myheader, one of these will "win" the normalization but the runtime may (probably will) treat them entirely differently. I don't think node does any modification of the outgoing headers, which means we may provide different headers to the hook than are actually included in the request.

Copy link
Member

@dyladan dyladan left a comment

Choose a reason for hiding this comment

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

I actually think we should keep the PR the way it is now. See my above comment for reason

@marcinjahn marcinjahn closed this Jan 27, 2023
@marcinjahn marcinjahn reopened this Jan 27, 2023
@marcinjahn
Copy link
Contributor Author

Do you know why the node-windows unit tests are failing?

@legendecas
Copy link
Member

Do you know why the node-windows unit tests are failing?

The test is not stable. Being tracked at #3572. I've restarted the run.

@legendecas legendecas merged commit 4978743 into open-telemetry:main Jan 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HTTP instrumentation modifies headers casing of outgoing requests
4 participants