mirror of https://github.com/aria2/aria2
Accept HTTP 304 reply as success when If-None-Match request-header
field is specified using --header option. When --conditional-get is used, --allow-overwrite is now required to overwrite existing file.pull/1/head
parent
7a6ec762ef
commit
1b9329c67c
|
@ -322,6 +322,11 @@ void HttpRequest::addHeader(const std::string& headersString)
|
||||||
headers_.insert(headers_.end(), headers.begin(), headers.end());
|
headers_.insert(headers_.end(), headers.begin(), headers.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpRequest::clearHeader()
|
||||||
|
{
|
||||||
|
headers_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void HttpRequest::addAcceptType(const std::string& type)
|
void HttpRequest::addAcceptType(const std::string& type)
|
||||||
{
|
{
|
||||||
acceptTypes_.push_back(type);
|
acceptTypes_.push_back(type);
|
||||||
|
@ -431,4 +436,20 @@ void HttpRequest::setIfModifiedSinceHeader(const std::string& hd)
|
||||||
ifModSinceHeader_ = hd;
|
ifModSinceHeader_ = hd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HttpRequest::conditionalRequest() const
|
||||||
|
{
|
||||||
|
if(!ifModSinceHeader_.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for(std::vector<std::string>::const_iterator i = headers_.begin(),
|
||||||
|
eoi = headers_.end(); i != eoi; ++i) {
|
||||||
|
std::string hd = util::toLower(*i);
|
||||||
|
if(util::startsWith(hd, "if-modified-since") ||
|
||||||
|
util::startsWith(hd, "if-none-match")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -168,6 +168,8 @@ public:
|
||||||
// accepts multiline headers, delimited by LF
|
// accepts multiline headers, delimited by LF
|
||||||
void addHeader(const std::string& headers);
|
void addHeader(const std::string& headers);
|
||||||
|
|
||||||
|
void clearHeader();
|
||||||
|
|
||||||
void addAcceptType(const std::string& type);
|
void addAcceptType(const std::string& type);
|
||||||
|
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
|
@ -249,6 +251,11 @@ public:
|
||||||
{
|
{
|
||||||
return ifModSinceHeader_;
|
return ifModSinceHeader_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if request is conditional:more specifically, the
|
||||||
|
// request is considered to be conditional if the client sent
|
||||||
|
// "If-Modified-Since" or "If-None-Match" request-header field.
|
||||||
|
bool conditionalRequest() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -70,8 +70,8 @@ void HttpResponse::validateResponse() const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(statusCode == 304) {
|
if(statusCode == 304) {
|
||||||
if(httpRequest_->getIfModifiedSinceHeader().empty()) {
|
if(!httpRequest_->conditionalRequest()) {
|
||||||
throw DL_ABORT_EX2("Got 304 without If-Modified-Since",
|
throw DL_ABORT_EX2("Got 304 without If-Modified-Since or If-None-Match",
|
||||||
error_code::HTTP_PROTOCOL_ERROR);
|
error_code::HTTP_PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
} else if(statusCode == 301 ||
|
} else if(statusCode == 301 ||
|
||||||
|
|
|
@ -174,26 +174,22 @@ bool HttpResponseCommand::executeInternal()
|
||||||
}
|
}
|
||||||
|
|
||||||
int statusCode = httpResponse->getStatusCode();
|
int statusCode = httpResponse->getStatusCode();
|
||||||
if(!httpResponse->getHttpRequest()->getIfModifiedSinceHeader().empty()) {
|
|
||||||
if(statusCode == 304) {
|
if(statusCode == 304) {
|
||||||
uint64_t totalLength = httpResponse->getEntityLength();
|
uint64_t totalLength = httpResponse->getEntityLength();
|
||||||
getFileEntry()->setLength(totalLength);
|
getFileEntry()->setLength(totalLength);
|
||||||
getRequestGroup()->initPieceStorage();
|
getRequestGroup()->initPieceStorage();
|
||||||
getPieceStorage()->markAllPiecesDone();
|
getPieceStorage()->markAllPiecesDone();
|
||||||
// Just set checksum verification done.
|
// Just set checksum verification done.
|
||||||
getDownloadContext()->setChecksumVerified(true);
|
getDownloadContext()->setChecksumVerified(true);
|
||||||
A2_LOG_NOTICE(fmt(MSG_DOWNLOAD_ALREADY_COMPLETED,
|
A2_LOG_NOTICE(fmt(MSG_DOWNLOAD_ALREADY_COMPLETED,
|
||||||
util::itos(getRequestGroup()->getGID()).c_str(),
|
util::itos(getRequestGroup()->getGID()).c_str(),
|
||||||
getRequestGroup()->getFirstFilePath().c_str()));
|
getRequestGroup()->getFirstFilePath().c_str()));
|
||||||
poolConnection();
|
poolConnection();
|
||||||
getFileEntry()->poolRequest(getRequest());
|
getFileEntry()->poolRequest(getRequest());
|
||||||
return true;
|
return true;
|
||||||
} else if(statusCode == 200 || statusCode == 206) {
|
|
||||||
// Remote file is newer than local file. We allow overwrite.
|
|
||||||
getOption()->put(PREF_ALLOW_OVERWRITE, A2_V_TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(statusCode != 304 && statusCode >= 300) {
|
if(statusCode >= 300) {
|
||||||
if(statusCode == 404) {
|
if(statusCode == 404) {
|
||||||
getRequestGroup()->increaseAndValidateFileNotFoundCount();
|
getRequestGroup()->increaseAndValidateFileNotFoundCount();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ class HttpRequestTest : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testAddHeader);
|
CPPUNIT_TEST(testAddHeader);
|
||||||
CPPUNIT_TEST(testAddAcceptType);
|
CPPUNIT_TEST(testAddAcceptType);
|
||||||
CPPUNIT_TEST(testEnableAcceptEncoding);
|
CPPUNIT_TEST(testEnableAcceptEncoding);
|
||||||
|
CPPUNIT_TEST(testConditionalRequest);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
private:
|
private:
|
||||||
SharedHandle<Option> option_;
|
SharedHandle<Option> option_;
|
||||||
|
@ -64,6 +65,7 @@ public:
|
||||||
void testAddHeader();
|
void testAddHeader();
|
||||||
void testAddAcceptType();
|
void testAddAcceptType();
|
||||||
void testEnableAcceptEncoding();
|
void testEnableAcceptEncoding();
|
||||||
|
void testConditionalRequest();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -843,4 +845,19 @@ void HttpRequestTest::testCreateRequest_ipv6LiteralAddr()
|
||||||
CPPUNIT_ASSERT(proxyRequest.find("CONNECT [::1]:80 ") != std::string::npos);
|
CPPUNIT_ASSERT(proxyRequest.find("CONNECT [::1]:80 ") != std::string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::testConditionalRequest()
|
||||||
|
{
|
||||||
|
HttpRequest httpRequest;
|
||||||
|
CPPUNIT_ASSERT(!httpRequest.conditionalRequest());
|
||||||
|
httpRequest.setIfModifiedSinceHeader("dummy");
|
||||||
|
CPPUNIT_ASSERT(httpRequest.conditionalRequest());
|
||||||
|
httpRequest.setIfModifiedSinceHeader("");
|
||||||
|
CPPUNIT_ASSERT(!httpRequest.conditionalRequest());
|
||||||
|
httpRequest.addHeader("If-None-Match: *");
|
||||||
|
CPPUNIT_ASSERT(httpRequest.conditionalRequest());
|
||||||
|
httpRequest.clearHeader();
|
||||||
|
httpRequest.addHeader("If-Modified-Since: dummy");
|
||||||
|
CPPUNIT_ASSERT(httpRequest.conditionalRequest());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
Loading…
Reference in New Issue