mirror of https://github.com/aria2/aria2
Better handling of 30X HTTP status codes
Reference: http://greenbytes.de/tech/tc/httpredirects/pull/195/head
parent
bdc9c8a991
commit
ec4b729704
|
@ -75,27 +75,9 @@ HttpResponse::HttpResponse()
|
||||||
void HttpResponse::validateResponse() const
|
void HttpResponse::validateResponse() const
|
||||||
{
|
{
|
||||||
int statusCode = getStatusCode();
|
int statusCode = getStatusCode();
|
||||||
if (statusCode >= 400) {
|
switch(statusCode) {
|
||||||
return;
|
case 200: // OK
|
||||||
}
|
case 206: // Partial Content
|
||||||
|
|
||||||
if (statusCode == 304) {
|
|
||||||
if (!httpRequest_->conditionalRequest()) {
|
|
||||||
throw DL_ABORT_EX2("Got 304 without If-Modified-Since or If-None-Match",
|
|
||||||
error_code::HTTP_PROTOCOL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (statusCode == 301 ||
|
|
||||||
statusCode == 302 ||
|
|
||||||
statusCode == 303 ||
|
|
||||||
statusCode == 307) {
|
|
||||||
if (!httpHeader_->defined(HttpHeader::LOCATION)) {
|
|
||||||
throw DL_ABORT_EX2(fmt(EX_LOCATION_HEADER_REQUIRED, statusCode),
|
|
||||||
error_code::HTTP_PROTOCOL_ERROR);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (statusCode == 200 || statusCode == 206) {
|
|
||||||
if (!httpHeader_->defined(HttpHeader::TRANSFER_ENCODING)) {
|
if (!httpHeader_->defined(HttpHeader::TRANSFER_ENCODING)) {
|
||||||
// compare the received range against the requested range
|
// compare the received range against the requested range
|
||||||
auto responseRange = httpHeader_->getRange();
|
auto responseRange = httpHeader_->getRange();
|
||||||
|
@ -110,11 +92,26 @@ void HttpResponse::validateResponse() const
|
||||||
error_code::CANNOT_RESUME);
|
error_code::CANNOT_RESUME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
case 304: // Not Modified
|
||||||
|
if (!httpRequest_->conditionalRequest()) {
|
||||||
|
throw DL_ABORT_EX2("Got 304 without If-Modified-Since or If-None-Match",
|
||||||
|
error_code::HTTP_PROTOCOL_ERROR);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 300: // Multiple Choices
|
||||||
|
case 301: // Moved Permanently
|
||||||
|
case 302: // Found
|
||||||
|
case 303: // See Other
|
||||||
|
case 307: // Temporary Redirect
|
||||||
|
case 308: // Permanent Redirect
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
if (statusCode >= 400) {
|
||||||
throw DL_ABORT_EX2(fmt("Unexpected status %d", statusCode),
|
return;
|
||||||
error_code::HTTP_PROTOCOL_ERROR);
|
|
||||||
}
|
}
|
||||||
|
throw DL_ABORT_EX2(fmt("Unexpected status %d", statusCode),
|
||||||
|
error_code::HTTP_PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HttpResponse::determineFilename() const
|
std::string HttpResponse::determineFilename() const
|
||||||
|
@ -151,9 +148,16 @@ void HttpResponse::retrieveCookie()
|
||||||
|
|
||||||
bool HttpResponse::isRedirect() const
|
bool HttpResponse::isRedirect() const
|
||||||
{
|
{
|
||||||
auto code = getStatusCode();
|
switch(getStatusCode()) {
|
||||||
return (301 == code || 302 == code || 303 == code || 307 == code) &&
|
case 300: // Multiple Choices
|
||||||
httpHeader_->defined(HttpHeader::LOCATION);
|
case 301: // Moved Permanently
|
||||||
|
case 302: // Found
|
||||||
|
case 303: // See Other
|
||||||
|
case 307: // Temporary Redirect
|
||||||
|
case 308: // Permanent Redirect
|
||||||
|
return httpHeader_->defined(HttpHeader::LOCATION);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpResponse::processRedirect()
|
void HttpResponse::processRedirect()
|
||||||
|
|
|
@ -231,10 +231,11 @@ bool HttpResponseCommand::executeInternal()
|
||||||
#endif // ENABLE_MESSAGE_DIGEST
|
#endif // ENABLE_MESSAGE_DIGEST
|
||||||
}
|
}
|
||||||
|
|
||||||
if (statusCode >= 300) {
|
if (statusCode == 404) {
|
||||||
if (statusCode == 404) {
|
grp->increaseAndValidateFileNotFoundCount();
|
||||||
grp->increaseAndValidateFileNotFoundCount();
|
return skipResponseBody(std::move(httpResponse));
|
||||||
}
|
}
|
||||||
|
if (statusCode >= 400 || statusCode == 304 || httpResponse->isRedirect()) {
|
||||||
return skipResponseBody(std::move(httpResponse));
|
return skipResponseBody(std::move(httpResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,16 +220,49 @@ void HttpResponseTest::testGetRedirectURI_with_Location()
|
||||||
void HttpResponseTest::testIsRedirect()
|
void HttpResponseTest::testIsRedirect()
|
||||||
{
|
{
|
||||||
HttpResponse httpResponse;
|
HttpResponse httpResponse;
|
||||||
auto httpHeader = make_unique<HttpHeader>();
|
httpResponse.setHttpHeader(make_unique<HttpHeader>());
|
||||||
httpHeader->setStatusCode(200);
|
|
||||||
httpHeader->put(HttpHeader::LOCATION,
|
|
||||||
"http://localhost/download/aria2-1.0.0.tar.bz2");
|
|
||||||
|
|
||||||
httpResponse.setHttpHeader(std::move(httpHeader));
|
httpResponse.getHttpHeader()->setStatusCode(301);
|
||||||
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(200);
|
||||||
|
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->put
|
||||||
|
(HttpHeader::LOCATION,
|
||||||
|
"http://localhost/download/aria2-1.0.0.tar.bz2");
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(300);
|
||||||
|
CPPUNIT_ASSERT(httpResponse.isRedirect());
|
||||||
|
|
||||||
httpResponse.getHttpHeader()->setStatusCode(301);
|
httpResponse.getHttpHeader()->setStatusCode(301);
|
||||||
CPPUNIT_ASSERT(httpResponse.isRedirect());
|
CPPUNIT_ASSERT(httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(302);
|
||||||
|
CPPUNIT_ASSERT(httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(303);
|
||||||
|
CPPUNIT_ASSERT(httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(304);
|
||||||
|
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(305);
|
||||||
|
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(306);
|
||||||
|
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(307);
|
||||||
|
CPPUNIT_ASSERT(httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(308);
|
||||||
|
CPPUNIT_ASSERT(httpResponse.isRedirect());
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(309);
|
||||||
|
CPPUNIT_ASSERT(!httpResponse.isRedirect());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpResponseTest::testIsTransferEncodingSpecified()
|
void HttpResponseTest::testIsTransferEncodingSpecified()
|
||||||
|
@ -329,19 +362,15 @@ void HttpResponseTest::testValidateResponse()
|
||||||
httpResponse.setHttpHeader(make_unique<HttpHeader>());
|
httpResponse.setHttpHeader(make_unique<HttpHeader>());
|
||||||
httpResponse.getHttpHeader()->setStatusCode(301);
|
httpResponse.getHttpHeader()->setStatusCode(301);
|
||||||
|
|
||||||
try {
|
// It is fine without Location header
|
||||||
|
httpResponse.validateResponse();
|
||||||
|
|
||||||
|
httpResponse.getHttpHeader()->setStatusCode(201);
|
||||||
|
try{
|
||||||
httpResponse.validateResponse();
|
httpResponse.validateResponse();
|
||||||
CPPUNIT_FAIL("exception must be thrown.");
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
}
|
// success
|
||||||
|
|
||||||
httpResponse.getHttpHeader()->put
|
|
||||||
(HttpHeader::LOCATION,
|
|
||||||
"http://localhost/archives/aria2-1.0.0.tar.bz2");
|
|
||||||
try {
|
|
||||||
httpResponse.validateResponse();
|
|
||||||
} catch(Exception& e) {
|
|
||||||
CPPUNIT_FAIL("exception must not be thrown.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue