http: return error for a second Location: header
No binary (build failed)
—
(log yok)
| @@ -3265,9 +3265,7 @@ static CURLcode http_header_l(struct Curl_easy *data, | |
| data->info.filetime = k->timeofdoc; | |
| return CURLE_OK; | |
| } | |
| - | if((k->httpcode >= 300 && k->httpcode < 400) && |
| - | HD_IS(hd, hdlen, "Location:") && |
| - | !data->req.location) { |
| + | if(HD_IS(hd, hdlen, "Location:")) { |
| /* this is the URL that the server advises us to use instead */ | |
| char *location = Curl_copy_header_value(hd); | |
| if(!location) | |
| @@ -3276,23 +3274,33 @@ static CURLcode http_header_l(struct Curl_easy *data, | |
| /* ignore empty data */ | |
| free(location); | |
| else { | |
| - | data->req.location = location; |
| - | |
| - | if(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; |
| + | if(data->req.location && |
| + | strcmp(data->req.location, 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; |
| + | } |
| } | |
| } | |
| } | |
| @@ -110,7 +110,7 @@ test736 test737 test738 test739 test740 test741 test742 test743 test744 \ | |
| test745 test746 test747 test748 test749 test750 test751 test752 test753 \ | |
| test754 test755 test756 test757 test758 test759 test760 test761 test762 \ | |
| test763 test764 test765 test766 test767 test768 test769 test770 test771 \ | |
| - | \ |
| + | test772 test773 \ |
| test780 test781 test782 test783 test784 test785 test786 test787 test788 \ | |
| test789 test790 test791 test792 test793 test794 test796 test797 \ | |
| \ | |
| @@ -20,6 +20,14 @@ Connection: close | |
| Location: and there's a second one too! / moo.html | |
| </data> | |
| + | <datacheck> |
| + | HTTP/1.1 302 eat this! |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Location: this-is-the-first.html |
| + | Content-Length: 0 |
| + | Connection: close |
| + | </datacheck> |
| </reply> | |
| # Client-side | |
| @@ -51,5 +59,8 @@ Host: %HOSTIP:%HTTPPORT | |
| Accept: */* | |
| </protocol> | |
| + | <errorcode> |
| + | 8 |
| + | </errorcode> |
| </verify> | |
| </testcase> | |
| @@ -0,0 +1,52 @@ | |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | Location |
| + | </keywords> |
| + | </info> |
| + | |
| + | # |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="yes" nocheck="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Content-Length: 0 |
| + | Connection: close |
| + | Location: this |
| + | Location: that |
| + | |
| + | </data> |
| + | </reply> |
| + | |
| + | # |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP with two Location: headers triggers error |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="yes"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | <errorcode> |
| + | 8 |
| + | </errorcode> |
| + | </verify> |
| + | </testcase> |
| @@ -0,0 +1,49 @@ | |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | Location |
| + | </keywords> |
| + | </info> |
| + | |
| + | # |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="yes" nocheck="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Content-Length: 0 |
| + | Connection: close |
| + | Location: this |
| + | Location: this |
| + | |
| + | </data> |
| + | </reply> |
| + | |
| + | # |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP with two identical Location: headers triggers no error |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="yes"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | </verify> |
| + | </testcase> |