Closed
Description
I did this
There is a backend that returns several multi-value headers in overlapping order:
< HTTP/2 200
< server: nginx
< date: Tue, 07 Mar 2023 15:14:41 GMT
< content-type: application/json
< content-length: 12265
< vary: Accept-Encoding
< access-control-allow-origin: *
< vary: Accept-Encoding
< referrer-policy: strict-origin-when-cross-origin
< access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
< access-control-max-age: 1728000
< access-control-allow-headers: Authorization, Content-Type, AuthorizationOauth, X-EARLY-ACCESS
< access-control-expose-headers:
< vary: Accept
< etag: W/"2678f9ab2ba550d164e7cc014aefd31e"
< cache-control: max-age=0, private, must-revalidate
< x-request-id: 375b343b3d2ecf9b442c0daf00fc4a9a
< strict-transport-security: max-age=31536000; includeSubDomains
< x-content-type-options: nosniff
< x-xss-protection: 1; mode=block
< referrer-policy: strict-origin-when-cross-origin
< feature-policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'
You can see the vary
and referrer-policy
occurring multiple times. With -w %{header_json}
option the JSON produced becomes incorrect:
{
"server": ["nginx"],
"date": ["Tue, 07 Mar 2023 11:31:47 GMT"],
"content-type": ["application/json"],
"content-length": ["12265"],
"vary": ["Accept-Encoding", "Accept-Encoding", "Accept"],
"etag": ["W/\"2678f9ab2ba550d164e7cc014aefd31e\""],
"cache-control": ["max-age=0, private, must-revalidate"],
"x-request-id": ["ad2176d584f1c5b1a56b564af1969efa"],
"strict-transport-security": ["max-age=31536000; includeSubDomains"],
"x-content-type-options": ["nosniff"],
"x-xss-protection": ["1; mode=block"],
"referrer-policy": ],
"feature-policy": ["accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"]
}
Notice the "referrer-policy": ],
. Also notice that headers between the first occurrence of the first multi-value header (vary) are also missing.
Here's the cURL command to reproduce the issue (note: the token is taken from the official docs, so feel free to use it).
curl https://api.pagerduty.com/oncalls -H "Accept: application/vnd.pagerduty+json;version=2" -H "Content-Type: application/json" -H "Authorization: Token token=y_NbAkKc66ryYTWUXYEu" -w %{header_json}
I managed to track it down to headerJSON
right here:
Lines 131 to 132 in a26418c
prev
pointer gets overwritten by that last call to curl_easy_header
before breaking from the loop; therefore the next iteration of the while
starts from etag
(which is the next header after the last occurrence of vary
) and therefore misses the first occurrence of another multi-value header referrer-policy
(along with all other headers in between the first and the last occurrence of vary
). By the time the outer loop reaches referrer-policy
it actually sees the second occurrence (with index 1
) and that causes the method to only emit a closing bracket because the branch before it is never entered.
I expected the following
JSON should be valid. All headers should be present.
curl/libcurl version
7.88.1
operating system
macOS 12.5.1
/cc @christellevs