Skip to content
Snippets Groups Projects
Commit b9699708 authored by Vladimir Davydov's avatar Vladimir Davydov
Browse files

httpc: reset headers on redirect

When a request is redirected, old headers are of no use anymore and
should be dropped. We can detect a redirect by checking the value of
CURLINFO_REDIRECT_COUNT.

Note about the test: we change the redirect reply to 'redirecting...',
so that its length differs from 'hello world'.

Close #6101

NO_DOC=bug fix

(cherry picked from commit 1cde49d4)
parent 2a122c95
No related branches found
No related tags found
No related merge requests found
## bugfix/http client
* Fixed invalid headers after redirect (gh-6101).
......@@ -75,6 +75,20 @@ curl_easy_header_cb(char *buffer, size_t size, size_t nitems, void *ctx)
{
struct httpc_request *req = (struct httpc_request *) ctx;
const size_t bytes = size * nitems;
/*
* The callback is invoked for the headers of all responses received
* after initiating a request and not just the final response. Since
* we're only interested in the final response headers, we drop all
* accumulated headers on each redirect.
*/
long redirect_count;
curl_easy_getinfo(req->curl_request.easy, CURLINFO_REDIRECT_COUNT,
&redirect_count);
if (redirect_count > req->redirect_count) {
assert(redirect_count == req->redirect_count + 1);
req->redirect_count = redirect_count;
region_reset(&req->resp_headers);
}
char *p = region_alloc(&req->resp_headers, bytes);
if (p == NULL) {
diag_set(OutOfMemory, bytes, "ibuf", "httpc header");
......
......@@ -103,6 +103,8 @@ struct httpc_request {
struct curl_request curl_request;
/** HTTP status code */
int status;
/** Number of redirects that were followed. */
int redirect_count;
/** Error message */
const char *reason;
/** buffer of headers */
......
......@@ -118,20 +118,52 @@ g.test_follow_location = function(cg)
local r = client.request('GET', url .. endpoint, nil, opts)
t.assert_equals(r.status, 200, 'default: status')
t.assert_equals(r.body, 'hello world', 'default: body')
-- gh-6101: headers are reset on redirect
r.headers.date = r.headers.date and 'DATE'
r.headers.host = r.headers.host and 'HOST'
t.assert_equals(r.headers, {
['date'] = 'DATE',
['host'] = 'HOST',
['accept'] = '*/*',
['connection'] = 'close',
['content-length'] = '11',
['content-type'] = 'application/json',
}, 'default: headers')
-- Verify {follow_location = true} behaviour.
local r = client.request('GET', url .. endpoint, nil, merge(opts, {
follow_location = true}))
t.assert_equals(r.status, 200, 'follow location: status')
t.assert_equals(r.body, 'hello world', 'follow location: body')
-- gh-6101: headers are reset on redirect
r.headers.date = r.headers.date and 'DATE'
r.headers.host = r.headers.host and 'HOST'
t.assert_equals(r.headers, {
['date'] = 'DATE',
['host'] = 'HOST',
['accept'] = '*/*',
['connection'] = 'close',
['content-length'] = '11',
['content-type'] = 'application/json',
}, 'follow location: headers')
-- Verify {follow_location = false} behaviour.
local r = client.request('GET', url .. endpoint, nil, merge(opts, {
follow_location = false}))
t.assert_equals(r.status, 302, 'do not follow location: status')
t.assert_equals(r.body, 'redirecting', 'do not follow location: body')
t.assert_equals(r.headers['location'], '/',
'do not follow location: header')
t.assert_equals(r.body, 'redirecting...',
'do not follow location: body')
-- gh-6101: headers are not reset if redirect is disabled
r.headers.date = r.headers.date and 'DATE'
r.headers.host = r.headers.host and 'HOST'
t.assert_equals(r.headers, {
['date'] = 'DATE',
['host'] = 'HOST',
['location'] = '/',
['accept'] = '*/*',
['connection'] = 'close',
['content-length'] = '14',
}, 'do not follow location: headers')
end
--
......
......@@ -47,7 +47,7 @@ def long_query():
def redirect():
code = "302 Found"
body = [b'redirecting']
body = [b'redirecting...']
headers = [("Location", "/")]
return code, body, headers
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment