mirror of https://github.com/aria2/aria2
2009-08-31 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added support for IPv6 literal address in URI. Now aria2 can handle URI such as http://[::1]/ * src/HttpRequest.cc * src/HttpRequest.h * src/Request.cc * src/Request.h * test/HttpRequestTest.cc * test/OptionHandlerTest.cc * test/RequestTest.ccpull/1/head
parent
19ae8f9d07
commit
ce25b54cfe
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2009-08-31 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
|
Added support for IPv6 literal address in URI. Now aria2 can
|
||||||
|
handle URI such as http://[::1]/
|
||||||
|
* src/HttpRequest.cc
|
||||||
|
* src/HttpRequest.h
|
||||||
|
* src/Request.cc
|
||||||
|
* src/Request.h
|
||||||
|
* test/HttpRequestTest.cc
|
||||||
|
* test/OptionHandlerTest.cc
|
||||||
|
* test/RequestTest.cc
|
||||||
|
|
||||||
2009-08-30 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
2009-08-30 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
Fixed the bug that HTTP request header for XML-RPC request is not
|
Fixed the bug that HTTP request header for XML-RPC request is not
|
||||||
|
|
|
@ -117,7 +117,7 @@ bool HttpRequest::isRangeSatisfied(const RangeHandle& range) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HttpRequest::getHostText(const std::string& host, uint16_t port) const
|
static std::string getHostText(const std::string& host, uint16_t port)
|
||||||
{
|
{
|
||||||
std::string hosttext = host;
|
std::string hosttext = host;
|
||||||
if(!(port == 80 || port == 443)) {
|
if(!(port == 80 || port == 443)) {
|
||||||
|
@ -172,7 +172,7 @@ std::string HttpRequest::createRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strappend(requestLine, "Host: ", getHostText(getHost(), getPort()), "\r\n");
|
strappend(requestLine, "Host: ", getHostText(getURIHost(), getPort()), "\r\n");
|
||||||
requestLine += "Pragma: no-cache\r\n";
|
requestLine += "Pragma: no-cache\r\n";
|
||||||
requestLine += "Cache-Control: no-cache\r\n";
|
requestLine += "Cache-Control: no-cache\r\n";
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ std::string HttpRequest::createRequest()
|
||||||
std::string HttpRequest::createProxyRequest() const
|
std::string HttpRequest::createProxyRequest() const
|
||||||
{
|
{
|
||||||
assert(!_proxyRequest.isNull());
|
assert(!_proxyRequest.isNull());
|
||||||
std::string hostport = getHost();
|
std::string hostport = getURIHost();
|
||||||
strappend(hostport, ":", Util::uitos(getPort()));
|
strappend(hostport, ":", Util::uitos(getPort()));
|
||||||
|
|
||||||
std::string requestLine = "CONNECT ";
|
std::string requestLine = "CONNECT ";
|
||||||
|
|
|
@ -83,8 +83,6 @@ private:
|
||||||
|
|
||||||
SharedHandle<Request> _proxyRequest;
|
SharedHandle<Request> _proxyRequest;
|
||||||
|
|
||||||
std::string getHostText(const std::string& host, uint16_t port) const;
|
|
||||||
|
|
||||||
std::string getProxyAuthString() const;
|
std::string getProxyAuthString() const;
|
||||||
public:
|
public:
|
||||||
HttpRequest();
|
HttpRequest();
|
||||||
|
@ -149,6 +147,11 @@ public:
|
||||||
return request->getPreviousUrl();
|
return request->getPreviousUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getURIHost() const
|
||||||
|
{
|
||||||
|
return request->getURIHost();
|
||||||
|
}
|
||||||
|
|
||||||
SharedHandle<Range> getRange() const;
|
SharedHandle<Range> getRange() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -71,7 +71,8 @@ Request::Request():
|
||||||
_keepAliveHint(false),
|
_keepAliveHint(false),
|
||||||
_pipeliningHint(false),
|
_pipeliningHint(false),
|
||||||
_maxPipelinedRequest(1),
|
_maxPipelinedRequest(1),
|
||||||
method(METHOD_GET)
|
method(METHOD_GET),
|
||||||
|
_ipv6LiteralAddress(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static std::string removeFragment(const std::string url)
|
static std::string removeFragment(const std::string url)
|
||||||
|
@ -160,6 +161,7 @@ bool Request::parseUrl(const std::string& url) {
|
||||||
_query = A2STR::NIL;
|
_query = A2STR::NIL;
|
||||||
_username = A2STR::NIL;
|
_username = A2STR::NIL;
|
||||||
_password = A2STR::NIL;
|
_password = A2STR::NIL;
|
||||||
|
_ipv6LiteralAddress = false;
|
||||||
// find query part
|
// find query part
|
||||||
std::string queryTemp;
|
std::string queryTemp;
|
||||||
std::string::size_type startQueryIndex = tempUrl.find("?");
|
std::string::size_type startQueryIndex = tempUrl.find("?");
|
||||||
|
@ -193,22 +195,40 @@ bool Request::parseUrl(const std::string& url) {
|
||||||
_password = Util::urldecode(userPass.second);
|
_password = Util::urldecode(userPass.second);
|
||||||
hostPart.erase(0, atmarkp+1);
|
hostPart.erase(0, atmarkp+1);
|
||||||
}
|
}
|
||||||
std::pair<std::string, std::string> hostAndPort;
|
{
|
||||||
Util::split(hostAndPort, hostPart, ':');
|
std::string::size_type colonpos;
|
||||||
host = hostAndPort.first;
|
// Detect IPv6 literal address in square brackets
|
||||||
if(hostAndPort.second != A2STR::NIL) {
|
if(Util::startsWith(hostPart, "[")) {
|
||||||
try {
|
std::string::size_type rbracketpos = hostPart.find("]");
|
||||||
unsigned int tempPort = Util::parseUInt(hostAndPort.second);
|
if(rbracketpos == std::string::npos) {
|
||||||
if(65535 < tempPort) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
port = tempPort;
|
_ipv6LiteralAddress = true;
|
||||||
} catch(RecoverableException& e) {
|
colonpos = hostPart.find(":", rbracketpos+1);
|
||||||
return false;
|
} else {
|
||||||
|
colonpos = hostPart.find_last_of(":");
|
||||||
|
}
|
||||||
|
if(colonpos == std::string::npos) {
|
||||||
|
colonpos = hostPart.size();
|
||||||
|
// If port is not specified, then we set it to default port of
|
||||||
|
// its protocol..
|
||||||
|
port = defPort;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
unsigned int tempPort = Util::parseUInt(hostPart.substr(colonpos+1));
|
||||||
|
if(65535 < tempPort) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
port = tempPort;
|
||||||
|
} catch(RecoverableException& e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_ipv6LiteralAddress) {
|
||||||
|
host = hostPart.substr(1, colonpos-2);
|
||||||
|
} else {
|
||||||
|
host = hostPart.substr(0, colonpos);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If port is not specified, then we set it to default port of its protocol..
|
|
||||||
port = defPort;
|
|
||||||
}
|
}
|
||||||
// find directory and file part
|
// find directory and file part
|
||||||
std::string::size_type direp = tempUrl.find_last_of("/");
|
std::string::size_type direp = tempUrl.find_last_of("/");
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "SharedHandle.h"
|
#include "SharedHandle.h"
|
||||||
#include "PeerStat.h"
|
#include "PeerStat.h"
|
||||||
|
#include "a2functional.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -82,6 +83,8 @@ private:
|
||||||
|
|
||||||
std::string _password;
|
std::string _password;
|
||||||
|
|
||||||
|
bool _ipv6LiteralAddress;
|
||||||
|
|
||||||
SharedHandle<PeerStat> _peerStat;
|
SharedHandle<PeerStat> _peerStat;
|
||||||
|
|
||||||
bool parseUrl(const std::string& url);
|
bool parseUrl(const std::string& url);
|
||||||
|
@ -116,10 +119,21 @@ public:
|
||||||
void setReferer(const std::string& url);
|
void setReferer(const std::string& url);
|
||||||
const std::string& getProtocol() const { return protocol; }
|
const std::string& getProtocol() const { return protocol; }
|
||||||
const std::string& getHost() const { return host; }
|
const std::string& getHost() const { return host; }
|
||||||
|
// Same as getHost(), but for IPv6 literal addresses, enclose them
|
||||||
|
// with square brackets and return.
|
||||||
|
std::string getURIHost() const
|
||||||
|
{
|
||||||
|
if(isIPv6LiteralAddress()) {
|
||||||
|
return strconcat("[", getHost(), "]");
|
||||||
|
} else {
|
||||||
|
return getHost();
|
||||||
|
}
|
||||||
|
}
|
||||||
uint16_t getPort() const { return port; }
|
uint16_t getPort() const { return port; }
|
||||||
const std::string& getDir() const { return dir; }
|
const std::string& getDir() const { return dir; }
|
||||||
const std::string& getFile() const { return file;}
|
const std::string& getFile() const { return file;}
|
||||||
const std::string& getQuery() const { return _query; }
|
const std::string& getQuery() const { return _query; }
|
||||||
|
bool isIPv6LiteralAddress() const { return _ipv6LiteralAddress; }
|
||||||
|
|
||||||
void supportsPersistentConnection(bool f)
|
void supportsPersistentConnection(bool f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ class HttpRequestTest : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testCreateRequest_with_cookie);
|
CPPUNIT_TEST(testCreateRequest_with_cookie);
|
||||||
CPPUNIT_TEST(testCreateRequest_query);
|
CPPUNIT_TEST(testCreateRequest_query);
|
||||||
CPPUNIT_TEST(testCreateRequest_head);
|
CPPUNIT_TEST(testCreateRequest_head);
|
||||||
|
CPPUNIT_TEST(testCreateRequest_ipv6LiteralAddr);
|
||||||
CPPUNIT_TEST(testCreateProxyRequest);
|
CPPUNIT_TEST(testCreateProxyRequest);
|
||||||
CPPUNIT_TEST(testIsRangeSatisfied);
|
CPPUNIT_TEST(testIsRangeSatisfied);
|
||||||
CPPUNIT_TEST(testUserAgent);
|
CPPUNIT_TEST(testUserAgent);
|
||||||
|
@ -53,6 +54,7 @@ public:
|
||||||
void testCreateRequest_with_cookie();
|
void testCreateRequest_with_cookie();
|
||||||
void testCreateRequest_query();
|
void testCreateRequest_query();
|
||||||
void testCreateRequest_head();
|
void testCreateRequest_head();
|
||||||
|
void testCreateRequest_ipv6LiteralAddr();
|
||||||
void testCreateProxyRequest();
|
void testCreateProxyRequest();
|
||||||
void testIsRangeSatisfied();
|
void testIsRangeSatisfied();
|
||||||
void testUserAgent();
|
void testUserAgent();
|
||||||
|
@ -735,4 +737,23 @@ void HttpRequestTest::testEnableAcceptEncoding()
|
||||||
CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
|
CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::testCreateRequest_ipv6LiteralAddr()
|
||||||
|
{
|
||||||
|
SharedHandle<Request> request(new Request());
|
||||||
|
request->setUrl("http://[::1]/path");
|
||||||
|
HttpRequest httpRequest;
|
||||||
|
httpRequest.disableContentEncoding();
|
||||||
|
httpRequest.setRequest(request);
|
||||||
|
httpRequest.setAuthConfigFactory(_authConfigFactory, _option.get());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(httpRequest.createRequest().find("Host: [::1]") != std::string::npos);
|
||||||
|
|
||||||
|
SharedHandle<Request> proxy(new Request());
|
||||||
|
proxy->setUrl("http://proxy");
|
||||||
|
httpRequest.setProxyRequest(proxy);
|
||||||
|
std::string proxyRequest = httpRequest.createProxyRequest();
|
||||||
|
CPPUNIT_ASSERT(proxyRequest.find("Host: [::1]:80") != std::string::npos);
|
||||||
|
CPPUNIT_ASSERT(proxyRequest.find("CONNECT [::1]:80 ") != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -311,11 +311,7 @@ void OptionHandlerTest::testHttpProxyOptionHandler()
|
||||||
|
|
||||||
handler.parse(option, "http://proxy:8080");
|
handler.parse(option, "http://proxy:8080");
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("http://proxy:8080"),
|
CPPUNIT_ASSERT_EQUAL(std::string("http://proxy:8080"),
|
||||||
option.get(PREF_HTTP_PROXY));
|
option.get(PREF_HTTP_PROXY));
|
||||||
|
|
||||||
handler.parse(option, "ftp://proxy:8080");
|
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("http://ftp://proxy:8080"),
|
|
||||||
option.get(PREF_HTTP_PROXY));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
handler.parse(option, "http://bar:65536");
|
handler.parse(option, "http://bar:65536");
|
||||||
|
|
|
@ -32,6 +32,7 @@ class RequestTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testSetUrl_usernamePassword);
|
CPPUNIT_TEST(testSetUrl_usernamePassword);
|
||||||
CPPUNIT_TEST(testSetUrl_zeroUsername);
|
CPPUNIT_TEST(testSetUrl_zeroUsername);
|
||||||
CPPUNIT_TEST(testSetUrl_supportsPersistentConnection);
|
CPPUNIT_TEST(testSetUrl_supportsPersistentConnection);
|
||||||
|
CPPUNIT_TEST(testSetUrl_ipv6);
|
||||||
CPPUNIT_TEST(testRedirectUrl);
|
CPPUNIT_TEST(testRedirectUrl);
|
||||||
CPPUNIT_TEST(testRedirectUrl2);
|
CPPUNIT_TEST(testRedirectUrl2);
|
||||||
CPPUNIT_TEST(testRedirectUrl_supportsPersistentConnection);
|
CPPUNIT_TEST(testRedirectUrl_supportsPersistentConnection);
|
||||||
|
@ -39,6 +40,7 @@ class RequestTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testResetUrl_supportsPersistentConnection);
|
CPPUNIT_TEST(testResetUrl_supportsPersistentConnection);
|
||||||
CPPUNIT_TEST(testInnerLink);
|
CPPUNIT_TEST(testInnerLink);
|
||||||
CPPUNIT_TEST(testInnerLinkInReferer);
|
CPPUNIT_TEST(testInnerLinkInReferer);
|
||||||
|
CPPUNIT_TEST(testGetURIHost);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -63,6 +65,7 @@ public:
|
||||||
void testSetUrl_usernamePassword();
|
void testSetUrl_usernamePassword();
|
||||||
void testSetUrl_zeroUsername();
|
void testSetUrl_zeroUsername();
|
||||||
void testSetUrl_supportsPersistentConnection();
|
void testSetUrl_supportsPersistentConnection();
|
||||||
|
void testSetUrl_ipv6();
|
||||||
void testRedirectUrl();
|
void testRedirectUrl();
|
||||||
void testRedirectUrl2();
|
void testRedirectUrl2();
|
||||||
void testRedirectUrl_supportsPersistentConnection();
|
void testRedirectUrl_supportsPersistentConnection();
|
||||||
|
@ -70,6 +73,7 @@ public:
|
||||||
void testResetUrl_supportsPersistentConnection();
|
void testResetUrl_supportsPersistentConnection();
|
||||||
void testInnerLink();
|
void testInnerLink();
|
||||||
void testInnerLinkInReferer();
|
void testInnerLinkInReferer();
|
||||||
|
void testGetURIHost();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,6 +95,7 @@ void RequestTest::testSetUrl1() {
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery());
|
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getUsername());
|
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getUsername());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getPassword());
|
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getPassword());
|
||||||
|
CPPUNIT_ASSERT(!req.isIPv6LiteralAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestTest::testSetUrl2() {
|
void RequestTest::testSetUrl2() {
|
||||||
|
@ -483,4 +488,26 @@ void RequestTest::testRedirectUrl_supportsPersistentConnection()
|
||||||
CPPUNIT_ASSERT(req.supportsPersistentConnection());
|
CPPUNIT_ASSERT(req.supportsPersistentConnection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RequestTest::testSetUrl_ipv6()
|
||||||
|
{
|
||||||
|
Request req;
|
||||||
|
CPPUNIT_ASSERT(!req.setUrl("http://[::1"));
|
||||||
|
CPPUNIT_ASSERT(req.setUrl("http://[::1]"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("::1"), req.getHost());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(req.setUrl("http://[::1]:8000/dir/file"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("::1"), req.getHost());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((uint16_t)8000, req.getPort());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("/dir"), req.getDir());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("file"), req.getFile());
|
||||||
|
CPPUNIT_ASSERT(req.isIPv6LiteralAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestTest::testGetURIHost()
|
||||||
|
{
|
||||||
|
Request req;
|
||||||
|
CPPUNIT_ASSERT(req.setUrl("http://[::1]"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("[::1]"), req.getURIHost());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
Loading…
Reference in New Issue