runtime: SocketsHttpHandler does not preserve request header format
Description
The following HTTP headers are in theory equivalent, but not always in practice:
Multi-Line:
HeaderName: value1
HeaderName: value2
HeaderName: value3
Comma Separated:
HeaderName: value1, value2, value3
Mixed:
HeaderName: value1
HeaderName: value2, value3
Some clients, servers, and/or application logic requires the headers to come through in a specific format, and this is often encountered by a 3rd party that needs to accommodate them by sending that format.
Now add YARP into the mix. YARP should be as transparent as possible about headers and formats so that it doesn’t interfere with how the clients/servers/apps are trying to communicate. The linked PR verifies that YARP is able to preserve the header format for responses, but not for requests. All multi-line requests headers are consolidated to a single comma separated header.
We have specific examples where this has been a problem in responses, such as Set-Cookie and Www-Authenticate. We don’t have specific examples for requests yet. Kestrel is able to preserve the requested header format in both directions, the limitation here is in HttpClient.
If a customer were to encounter this is there any workaround possible?
What kinds of changes would it take to make this possible in SocketsHttpHandler/HttpHeaders?
Reproduction Steps
Unit tests available in https://github.com/microsoft/reverse-proxy/pull/1498/files#diff-4ffa10100339146ae9048f52f94656c0aff1b984dabdbb5200d87284069b1379R474
Expected behavior
The header format can be preserved.
Actual behavior
Multi-line headers are consolidated to a single comma separated header.
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
No response
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 2
- Comments: 17 (14 by maintainers)
It did broke our protocol, but luckily since we own both client and server, we modified the server to accept comma separated metadata.
Yes, that’s what I meant.
I’m not sure we want to do this anyway. Seems like this:
Should be equivalent to this: