From: Stefan Eissing Date: Mon, 20 Oct 2025 10:17:31 +0000 (+0200) Subject: http: accept duplicate location with same value X-Git-Tag: curl-8_17_0~160 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4be9db7bc8c7b604e9288f7deaec48f61bbc61e0;p=thirdparty%2Fcurl.git http: accept duplicate location with same value When a server sends a Location: header repeat with the same location, ignore the repeats silently. Follow-up to 9596c4a2587a9e512ea46f Closes #19159 --- diff --git a/lib/http.c b/lib/http.c index 2d5da2e0e1..172a091668 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3270,37 +3270,37 @@ static CURLcode http_header_l(struct Curl_easy *data, char *location = Curl_copy_header_value(hd); if(!location) return CURLE_OUT_OF_MEMORY; - if(!*location) - /* ignore empty data */ + if(!*location || + (data->req.location && !strcmp(data->req.location, location))) { + /* ignore empty header, or exact repeat of a previous one */ free(location); + return CURLE_OK; + } else { - if(data->req.location && - strcmp(data->req.location, location)) { + /* has value and is not an exact repeat */ + if(data->req.location) { failf(data, "Multiple Location headers"); free(location); return CURLE_WEIRD_SERVER_REPLY; } - else { - free(data->req.location); - data->req.location = location; - - if((k->httpcode >= 300 && k->httpcode < 400) && - data->set.http_follow_mode) { - CURLcode result; - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->req.location); /* clone */ - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - - /* some cases of POST and PUT etc needs to rewind the data - stream at this point */ - result = http_perhapsrewind(data, conn); - if(result) - return result; - - /* mark the next request as a followed location: */ - data->state.this_is_a_follow = TRUE; - } + data->req.location = location; + + if((k->httpcode >= 300 && k->httpcode < 400) && + data->set.http_follow_mode) { + CURLcode result; + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->req.location); /* clone */ + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + + /* some cases of POST and PUT etc needs to rewind the data + stream at this point */ + result = http_perhapsrewind(data, conn); + if(result) + return result; + + /* mark the next request as a followed location: */ + data->state.this_is_a_follow = TRUE; } } }