mirror of https://github.com/aria2/aria2
2008-05-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Reimplemented transparent metalink using Accept request header. * src/HttpRequest.cc * src/HttpRequest.h * src/HttpRequestCommand.cc * src/Metalink2RequestGroup.cc * src/RequestGroup.cc * src/RequestGroup.h * test/HttpRequestTest.ccpull/1/head
parent
b892b54e4b
commit
f596de9eec
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2008-05-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
Reimplemented transparent metalink using Accept request header.
|
||||||
|
* src/HttpRequest.cc
|
||||||
|
* src/HttpRequest.h
|
||||||
|
* src/HttpRequestCommand.cc
|
||||||
|
* src/Metalink2RequestGroup.cc
|
||||||
|
* src/RequestGroup.cc
|
||||||
|
* src/RequestGroup.h
|
||||||
|
* test/HttpRequestTest.cc
|
||||||
|
|
||||||
2008-04-27 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2008-04-27 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Bump up version number to 0.13.2a
|
Bump up version number to 0.13.2a
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
#include "AuthConfigFactory.h"
|
#include "AuthConfigFactory.h"
|
||||||
#include "AuthConfig.h"
|
#include "AuthConfig.h"
|
||||||
|
#include "a2functional.h"
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
@ -145,11 +146,17 @@ std::string HttpRequest::createRequest() const
|
||||||
}
|
}
|
||||||
requestLine +=
|
requestLine +=
|
||||||
std::string(" HTTP/1.1\r\n")+
|
std::string(" HTTP/1.1\r\n")+
|
||||||
"User-Agent: "+userAgent+"\r\n"+
|
"User-Agent: "+userAgent+"\r\n";
|
||||||
"Accept: */*\r\n"+ /* */
|
|
||||||
|
requestLine +=
|
||||||
|
std::accumulate(_acceptTypes.begin(), _acceptTypes.end(),
|
||||||
|
std::string("Accept: */*"), Concat(","))+"\r\n"; /* */
|
||||||
|
|
||||||
|
requestLine +=
|
||||||
"Host: "+getHostText(getHost(), getPort())+"\r\n"+
|
"Host: "+getHostText(getHost(), getPort())+"\r\n"+
|
||||||
"Pragma: no-cache\r\n"+
|
"Pragma: no-cache\r\n"+
|
||||||
"Cache-Control: no-cache\r\n";
|
"Cache-Control: no-cache\r\n";
|
||||||
|
|
||||||
if(!request->isKeepAliveEnabled() && !request->isPipeliningEnabled()) {
|
if(!request->isKeepAliveEnabled() && !request->isPipeliningEnabled()) {
|
||||||
requestLine += "Connection: close\r\n";
|
requestLine += "Connection: close\r\n";
|
||||||
}
|
}
|
||||||
|
@ -232,6 +239,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::addAcceptType(const std::string& type)
|
||||||
|
{
|
||||||
|
_acceptTypes.push_back(type);
|
||||||
|
}
|
||||||
|
|
||||||
void HttpRequest::configure(const Option* option)
|
void HttpRequest::configure(const Option* option)
|
||||||
{
|
{
|
||||||
authEnabled = option->get(PREF_HTTP_AUTH_ENABLED) == V_TRUE;
|
authEnabled = option->get(PREF_HTTP_AUTH_ENABLED) == V_TRUE;
|
||||||
|
|
|
@ -68,6 +68,8 @@ private:
|
||||||
|
|
||||||
std::deque<std::string> _headers;
|
std::deque<std::string> _headers;
|
||||||
|
|
||||||
|
std::deque<std::string> _acceptTypes;
|
||||||
|
|
||||||
std::string getHostText(const std::string& host, uint16_t port) const;
|
std::string getHostText(const std::string& host, uint16_t port) const;
|
||||||
|
|
||||||
std::string getProxyAuthString() const;
|
std::string getProxyAuthString() const;
|
||||||
|
@ -171,6 +173,14 @@ public:
|
||||||
|
|
||||||
// accepts multiline headers, deliminated by LF
|
// accepts multiline headers, deliminated by LF
|
||||||
void addHeader(const std::string& headers);
|
void addHeader(const std::string& headers);
|
||||||
|
|
||||||
|
void addAcceptType(const std::string& type);
|
||||||
|
|
||||||
|
template<typename InputIterator>
|
||||||
|
void addAcceptType(InputIterator first, InputIterator last)
|
||||||
|
{
|
||||||
|
_acceptTypes.insert(_acceptTypes.end(), first, last);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<HttpRequest> HttpRequestHandle;
|
typedef SharedHandle<HttpRequest> HttpRequestHandle;
|
||||||
|
|
|
@ -71,7 +71,7 @@ createHttpRequest(const SharedHandle<Request>& req,
|
||||||
const SharedHandle<Segment>& segment,
|
const SharedHandle<Segment>& segment,
|
||||||
uint64_t totalLength,
|
uint64_t totalLength,
|
||||||
const Option* option,
|
const Option* option,
|
||||||
const std::deque<std::string>& acceptFeatures)
|
const RequestGroup* rg)
|
||||||
{
|
{
|
||||||
HttpRequestHandle httpRequest(new HttpRequest());
|
HttpRequestHandle httpRequest(new HttpRequest());
|
||||||
httpRequest->setUserAgent(option->get(PREF_USER_AGENT));
|
httpRequest->setUserAgent(option->get(PREF_USER_AGENT));
|
||||||
|
@ -79,7 +79,8 @@ createHttpRequest(const SharedHandle<Request>& req,
|
||||||
httpRequest->setSegment(segment);
|
httpRequest->setSegment(segment);
|
||||||
httpRequest->setEntityLength(totalLength);
|
httpRequest->setEntityLength(totalLength);
|
||||||
httpRequest->addHeader(option->get(PREF_HEADER));
|
httpRequest->addHeader(option->get(PREF_HEADER));
|
||||||
if(acceptFeatures.size()) {
|
if(rg->getAcceptFeatures().size()) {
|
||||||
|
const std::deque<std::string>& acceptFeatures = rg->getAcceptFeatures();
|
||||||
std::string acceptFeaturesHeader = "Accept-Features: "+
|
std::string acceptFeaturesHeader = "Accept-Features: "+
|
||||||
Util::trim
|
Util::trim
|
||||||
(std::accumulate(acceptFeatures.begin()+1, acceptFeatures.end(),
|
(std::accumulate(acceptFeatures.begin()+1, acceptFeatures.end(),
|
||||||
|
@ -88,6 +89,8 @@ createHttpRequest(const SharedHandle<Request>& req,
|
||||||
",");
|
",");
|
||||||
httpRequest->addHeader(acceptFeaturesHeader);
|
httpRequest->addHeader(acceptFeaturesHeader);
|
||||||
}
|
}
|
||||||
|
httpRequest->addAcceptType(rg->getAcceptTypes().begin(),
|
||||||
|
rg->getAcceptTypes().end());
|
||||||
httpRequest->configure(option);
|
httpRequest->configure(option);
|
||||||
|
|
||||||
return httpRequest;
|
return httpRequest;
|
||||||
|
@ -103,7 +106,7 @@ bool HttpRequestCommand::executeInternal() {
|
||||||
HttpRequestHandle httpRequest
|
HttpRequestHandle httpRequest
|
||||||
(createHttpRequest(req, SharedHandle<Segment>(),
|
(createHttpRequest(req, SharedHandle<Segment>(),
|
||||||
_requestGroup->getTotalLength(), e->option,
|
_requestGroup->getTotalLength(), e->option,
|
||||||
_requestGroup->getAcceptFeatures()));
|
_requestGroup));
|
||||||
_httpConnection->sendRequest(httpRequest);
|
_httpConnection->sendRequest(httpRequest);
|
||||||
} else {
|
} else {
|
||||||
for(Segments::iterator itr = _segments.begin(); itr != _segments.end(); ++itr) {
|
for(Segments::iterator itr = _segments.begin(); itr != _segments.end(); ++itr) {
|
||||||
|
@ -112,7 +115,7 @@ bool HttpRequestCommand::executeInternal() {
|
||||||
HttpRequestHandle httpRequest
|
HttpRequestHandle httpRequest
|
||||||
(createHttpRequest(req, segment,
|
(createHttpRequest(req, segment,
|
||||||
_requestGroup->getTotalLength(), e->option,
|
_requestGroup->getTotalLength(), e->option,
|
||||||
_requestGroup->getAcceptFeatures()));
|
_requestGroup));
|
||||||
_httpConnection->sendRequest(httpRequest);
|
_httpConnection->sendRequest(httpRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,9 +169,9 @@ Metalink2RequestGroup::createRequestGroup(std::deque<SharedHandle<MetalinkEntry>
|
||||||
torrentRg->setDownloadContext(dctx);
|
torrentRg->setDownloadContext(dctx);
|
||||||
torrentRg->clearPreDowloadHandler();
|
torrentRg->clearPreDowloadHandler();
|
||||||
torrentRg->clearPostDowloadHandler();
|
torrentRg->clearPostDowloadHandler();
|
||||||
// remove "metalink" from Accept-Feature list to avoid loop in tranparent
|
// remove "metalink" from Accept Type list to avoid loop in tranparent
|
||||||
// metalink
|
// metalink
|
||||||
torrentRg->removeAcceptFeatureHeader(RequestGroup::FEATURE_METALINK);
|
torrentRg->removeAcceptType(RequestGroup::ACCEPT_METALINK);
|
||||||
// make it in-memory download
|
// make it in-memory download
|
||||||
SharedHandle<PreDownloadHandler> preh(new MemoryBufferPreDownloadHandler());
|
SharedHandle<PreDownloadHandler> preh(new MemoryBufferPreDownloadHandler());
|
||||||
{
|
{
|
||||||
|
@ -222,9 +222,9 @@ Metalink2RequestGroup::createRequestGroup(std::deque<SharedHandle<MetalinkEntry>
|
||||||
std::min(_option->getAsInt(PREF_METALINK_SERVERS), entry->maxConnections));
|
std::min(_option->getAsInt(PREF_METALINK_SERVERS), entry->maxConnections));
|
||||||
// In metalink, multi connection to a single host is not allowed by default.
|
// In metalink, multi connection to a single host is not allowed by default.
|
||||||
rg->setSingleHostMultiConnectionEnabled(!_option->getAsBool(PREF_METALINK_ENABLE_UNIQUE_PROTOCOL));
|
rg->setSingleHostMultiConnectionEnabled(!_option->getAsBool(PREF_METALINK_ENABLE_UNIQUE_PROTOCOL));
|
||||||
// remove "metalink" from Accept-Feature list to avoid loop in tranparent
|
// remove "metalink" from Accept Type list to avoid loop in tranparent
|
||||||
// metalink
|
// metalink
|
||||||
rg->removeAcceptFeatureHeader(RequestGroup::FEATURE_METALINK);
|
rg->removeAcceptType(RequestGroup::ACCEPT_METALINK);
|
||||||
|
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
// Inject depenency between rg and torrentRg here if torrentRg.isNull() == false
|
// Inject depenency between rg and torrentRg here if torrentRg.isNull() == false
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace aria2 {
|
||||||
|
|
||||||
int32_t RequestGroup::_gidCounter = 0;
|
int32_t RequestGroup::_gidCounter = 0;
|
||||||
|
|
||||||
const std::string RequestGroup::FEATURE_METALINK = "metalink";
|
const std::string RequestGroup::ACCEPT_METALINK = "application/metalink+xml";
|
||||||
|
|
||||||
RequestGroup::RequestGroup(const Option* option,
|
RequestGroup::RequestGroup(const Option* option,
|
||||||
const std::deque<std::string>& uris):
|
const std::deque<std::string>& uris):
|
||||||
|
@ -127,11 +127,11 @@ RequestGroup::RequestGroup(const Option* option,
|
||||||
} else {
|
} else {
|
||||||
_fileAllocationEnabled = false;
|
_fileAllocationEnabled = false;
|
||||||
}
|
}
|
||||||
// For now, only supported 'Accept-Features' is "metalink" used for
|
// Add types to be sent as a Accept header value here.
|
||||||
// transparent metalink.
|
|
||||||
// It would be good to put this value in Option so that user can tweak
|
// It would be good to put this value in Option so that user can tweak
|
||||||
// and add this list.
|
// and add this list.
|
||||||
_acceptFeatures.push_back(FEATURE_METALINK);
|
// ACCEPT_METALINK is used for `transparent metalink'.
|
||||||
|
addAcceptType(ACCEPT_METALINK);
|
||||||
|
|
||||||
initializePreDownloadHandler();
|
initializePreDownloadHandler();
|
||||||
initializePostDownloadHandler();
|
initializePostDownloadHandler();
|
||||||
|
@ -969,4 +969,22 @@ void RequestGroup::removeAcceptFeatureHeader(const std::string& feature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::deque<std::string>& RequestGroup::getAcceptTypes() const
|
||||||
|
{
|
||||||
|
return _acceptTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestGroup::addAcceptType(const std::string& type)
|
||||||
|
{
|
||||||
|
if(std::find(_acceptTypes.begin(), _acceptTypes.end(), type) == _acceptTypes.end()) {
|
||||||
|
_acceptTypes.push_back(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestGroup::removeAcceptType(const std::string& type)
|
||||||
|
{
|
||||||
|
_acceptTypes.erase(std::remove(_acceptTypes.begin(), _acceptTypes.end(), type),
|
||||||
|
_acceptTypes.end());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -110,6 +110,8 @@ private:
|
||||||
|
|
||||||
std::deque<std::string> _acceptFeatures;
|
std::deque<std::string> _acceptFeatures;
|
||||||
|
|
||||||
|
std::deque<std::string> _acceptTypes;
|
||||||
|
|
||||||
const Option* _option;
|
const Option* _option;
|
||||||
|
|
||||||
Logger* _logger;
|
Logger* _logger;
|
||||||
|
@ -343,7 +345,13 @@ public:
|
||||||
|
|
||||||
void removeAcceptFeatureHeader(const std::string& feature);
|
void removeAcceptFeatureHeader(const std::string& feature);
|
||||||
|
|
||||||
static const std::string FEATURE_METALINK;
|
const std::deque<std::string>& getAcceptTypes() const;
|
||||||
|
|
||||||
|
void addAcceptType(const std::string& type);
|
||||||
|
|
||||||
|
void removeAcceptType(const std::string& type);
|
||||||
|
|
||||||
|
static const std::string ACCEPT_METALINK;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<RequestGroup> RequestGroupHandle;
|
typedef SharedHandle<RequestGroup> RequestGroupHandle;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
#include "CookieBox.h"
|
#include "CookieBox.h"
|
||||||
#include "Option.h"
|
#include "Option.h"
|
||||||
|
#include "array_fun.h"
|
||||||
#include <cppunit/extensions/HelperMacros.h>
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
@ -24,6 +25,7 @@ class HttpRequestTest : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testIsRangeSatisfied);
|
CPPUNIT_TEST(testIsRangeSatisfied);
|
||||||
CPPUNIT_TEST(testUserAgent);
|
CPPUNIT_TEST(testUserAgent);
|
||||||
CPPUNIT_TEST(testAddHeader);
|
CPPUNIT_TEST(testAddHeader);
|
||||||
|
CPPUNIT_TEST(testAddAcceptType);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ public:
|
||||||
void testIsRangeSatisfied();
|
void testIsRangeSatisfied();
|
||||||
void testUserAgent();
|
void testUserAgent();
|
||||||
void testAddHeader();
|
void testAddHeader();
|
||||||
|
void testAddAcceptType();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -641,5 +644,29 @@ void HttpRequestTest::testAddHeader()
|
||||||
CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
|
CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::testAddAcceptType()
|
||||||
|
{
|
||||||
|
std::string acceptTypes[] = { "cream/custard",
|
||||||
|
"muffin/chocolate" };
|
||||||
|
|
||||||
|
SharedHandle<Request> request(new Request());
|
||||||
|
request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
|
||||||
|
|
||||||
|
HttpRequest httpRequest;
|
||||||
|
httpRequest.setRequest(request);
|
||||||
|
httpRequest.addAcceptType(&acceptTypes[0], &acceptTypes[arrayLength(acceptTypes)]);
|
||||||
|
|
||||||
|
std::string expectedText =
|
||||||
|
"GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n"
|
||||||
|
"User-Agent: aria2\r\n"
|
||||||
|
"Accept: */*,cream/custard,muffin/chocolate\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"Pragma: no-cache\r\n"
|
||||||
|
"Cache-Control: no-cache\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
Loading…
Reference in New Issue