Store only interesting HTTP headers in HttpHeader

In this change, we defined HTTP header fields we are interested in.
We only store those headers in HttpHeader object.  Accessing HTTP
headers in HttpHeader object is now done through enum values.
pull/28/head
Tatsuhiro Tsujikawa 2012-09-23 20:59:34 +09:00
parent 0b4dec0250
commit dd7014a612
13 changed files with 294 additions and 219 deletions

View File

@ -37,26 +37,10 @@
#include "util.h" #include "util.h"
#include "A2STR.h" #include "A2STR.h"
#include "DownloadFailureException.h" #include "DownloadFailureException.h"
#include "array_fun.h"
namespace aria2 { namespace aria2 {
const std::string HttpHeader::LOCATION("location");
const std::string HttpHeader::TRANSFER_ENCODING("transfer-encoding");
const std::string HttpHeader::CONTENT_ENCODING("content-encoding");
const std::string HttpHeader::CONTENT_DISPOSITION("content-disposition");
const std::string HttpHeader::SET_COOKIE("set-cookie");
const std::string HttpHeader::CONTENT_TYPE("content-type");
const std::string HttpHeader::RETRY_AFTER("retry-after");
const std::string HttpHeader::CONNECTION("connection");
const std::string HttpHeader::CONTENT_LENGTH("content-length");
const std::string HttpHeader::CONTENT_RANGE("content-range");
const std::string HttpHeader::LAST_MODIFIED("last-modified");
const std::string HttpHeader::ACCEPT_ENCODING("accept-encoding");
const std::string HttpHeader::LINK("link");
const std::string HttpHeader::DIGEST("digest");
const std::string HttpHeader::PROXY_CONNECTION("proxy-connection");
const std::string HttpHeader::AUTHORIZATION("authorization");
const std::string HttpHeader::HTTP_1_1 = "HTTP/1.1"; const std::string HttpHeader::HTTP_1_1 = "HTTP/1.1";
const std::string HttpHeader::CLOSE = "close"; const std::string HttpHeader::CLOSE = "close";
const std::string HttpHeader::KEEP_ALIVE = "keep-alive"; const std::string HttpHeader::KEEP_ALIVE = "keep-alive";
@ -67,21 +51,20 @@ const std::string HttpHeader::DEFLATE = "deflate";
HttpHeader::HttpHeader() {} HttpHeader::HttpHeader() {}
HttpHeader::~HttpHeader() {} HttpHeader::~HttpHeader() {}
void HttpHeader::put(const std::string& name, const std::string& value) void HttpHeader::put(int hdKey, const std::string& value)
{ {
std::multimap<std::string, std::string>::value_type vt(name, value); std::multimap<int, std::string>::value_type vt(hdKey, value);
table_.insert(vt); table_.insert(vt);
} }
bool HttpHeader::defined(const std::string& name) const bool HttpHeader::defined(int hdKey) const
{ {
return table_.count(name); return table_.count(hdKey);
} }
const std::string& HttpHeader::find(const std::string& name) const const std::string& HttpHeader::find(int hdKey) const
{ {
std::multimap<std::string, std::string>::const_iterator itr = std::multimap<int, std::string>::const_iterator itr = table_.find(hdKey);
table_.find(name);
if(itr == table_.end()) { if(itr == table_.end()) {
return A2STR::NIL; return A2STR::NIL;
} else { } else {
@ -89,12 +72,12 @@ const std::string& HttpHeader::find(const std::string& name) const
} }
} }
std::vector<std::string> HttpHeader::findAll(const std::string& name) const std::vector<std::string> HttpHeader::findAll(int hdKey) const
{ {
std::vector<std::string> v; std::vector<std::string> v;
std::pair<std::multimap<std::string, std::string>::const_iterator, std::pair<std::multimap<int, std::string>::const_iterator,
std::multimap<std::string, std::string>::const_iterator> itrpair = std::multimap<int, std::string>::const_iterator> itrpair =
table_.equal_range(name); table_.equal_range(hdKey);
while(itrpair.first != itrpair.second) { while(itrpair.first != itrpair.second) {
v.push_back((*itrpair.first).second); v.push_back((*itrpair.first).second);
++itrpair.first; ++itrpair.first;
@ -102,16 +85,16 @@ std::vector<std::string> HttpHeader::findAll(const std::string& name) const
return v; return v;
} }
std::pair<std::multimap<std::string, std::string>::const_iterator, std::pair<std::multimap<int, std::string>::const_iterator,
std::multimap<std::string, std::string>::const_iterator> std::multimap<int, std::string>::const_iterator>
HttpHeader::equalRange(const std::string& name) const HttpHeader::equalRange(int hdKey) const
{ {
return table_.equal_range(name); return table_.equal_range(hdKey);
} }
int32_t HttpHeader::findAsInt(const std::string& name) const int32_t HttpHeader::findAsInt(int hdKey) const
{ {
const std::string& value = find(name); const std::string& value = find(hdKey);
if(value.empty()) { if(value.empty()) {
return 0; return 0;
} else { } else {
@ -119,9 +102,9 @@ int32_t HttpHeader::findAsInt(const std::string& name) const
} }
} }
int64_t HttpHeader::findAsLLInt(const std::string& name) const int64_t HttpHeader::findAsLLInt(int hdKey) const
{ {
const std::string& value = find(name); const std::string& value = find(hdKey);
if(value.empty()) { if(value.empty()) {
return 0; return 0;
} else { } else {
@ -253,13 +236,12 @@ void HttpHeader::setReasonPhrase(const std::string& reasonPhrase)
reasonPhrase_ = reasonPhrase; reasonPhrase_ = reasonPhrase;
} }
bool HttpHeader::fieldContains(const std::string& name, bool HttpHeader::fieldContains(int hdKey, const char* value)
const std::string& value)
{ {
std::pair<std::multimap<std::string, std::string>::const_iterator, std::pair<std::multimap<int, std::string>::const_iterator,
std::multimap<std::string, std::string>::const_iterator> range = std::multimap<int, std::string>::const_iterator> range =
equalRange(name); equalRange(hdKey);
for(std::multimap<std::string, std::string>::const_iterator i = range.first; for(std::multimap<int, std::string>::const_iterator i = range.first;
i != range.second; ++i) { i != range.second; ++i) {
std::vector<Scip> values; std::vector<Scip> values;
util::splitIter((*i).second.begin(), (*i).second.end(), util::splitIter((*i).second.begin(), (*i).second.end(),
@ -269,7 +251,7 @@ bool HttpHeader::fieldContains(const std::string& name,
); );
for(std::vector<Scip>::const_iterator j = values.begin(), for(std::vector<Scip>::const_iterator j = values.begin(),
eoj = values.end(); j != eoj; ++j) { eoj = values.end(); j != eoj; ++j) {
if(util::strieq((*j).first, (*j).second, value.begin(), value.end())) { if(util::strieq((*j).first, (*j).second, value)) {
return true; return true;
} }
} }
@ -277,4 +259,45 @@ bool HttpHeader::fieldContains(const std::string& name,
return false; return false;
} }
namespace {
const char* INTERESTING_HEADER_NAMES[] = {
"accept-encoding",
"access-control-request-headers",
"access-control-request-method",
"authorization",
"connection",
"content-disposition",
"content-encoding",
"content-length",
"content-range",
"content-type",
"digest",
"infohash",
"last-modified",
"link",
"location",
"origin",
"port",
"proxy-connection",
"retry-after",
"sec-websocket-key",
"sec-websocket-version",
"set-cookie",
"transfer-encoding",
"upgrade",
};
} // namespace
int idInterestingHeader(const char* hdName)
{
const char** i = std::lower_bound(vbegin(INTERESTING_HEADER_NAMES),
vend(INTERESTING_HEADER_NAMES),
hdName, util::strless);
if(i != vend(INTERESTING_HEADER_NAMES) && strcmp(*i, hdName) == 0 ) {
return i - vbegin(INTERESTING_HEADER_NAMES);
} else {
return HttpHeader::MAX_INTERESTING_HEADER;
}
}
} // namespace aria2 } // namespace aria2

View File

@ -49,7 +49,7 @@ class Range;
class HttpHeader { class HttpHeader {
private: private:
std::multimap<std::string, std::string> table_; std::multimap<int, std::string> table_;
// HTTP status code, e.g. 200 // HTTP status code, e.g. 200
int statusCode_; int statusCode_;
@ -69,16 +69,47 @@ public:
HttpHeader(); HttpHeader();
~HttpHeader(); ~HttpHeader();
// The list of headers we are interested in. Only those header
// values are stored in table_. When updating this list, also update
// INTERESTING_HEADER_NAMES in HttpHeader.cc
enum InterestingHeader {
ACCEPT_ENCODING,
ACCESS_CONTROL_REQUEST_HEADERS,
ACCESS_CONTROL_REQUEST_METHOD,
AUTHORIZATION,
CONNECTION,
CONTENT_DISPOSITION,
CONTENT_ENCODING,
CONTENT_LENGTH,
CONTENT_RANGE,
CONTENT_TYPE,
DIGEST,
INFOHASH, // Used for BitTorrent LPD
LAST_MODIFIED,
LINK,
LOCATION,
ORIGIN,
PORT, // Used for BitTorrent LPD
PROXY_CONNECTION,
RETRY_AFTER,
SEC_WEBSOCKET_KEY,
SEC_WEBSOCKET_VERSION,
SET_COOKIE,
TRANSFER_ENCODING,
UPGRADE,
MAX_INTERESTING_HEADER
};
// For all methods, use lowercased header field name. // For all methods, use lowercased header field name.
void put(const std::string& name, const std::string& value); void put(int hdKey, const std::string& value);
bool defined(const std::string& name) const; bool defined(int hdKey) const;
const std::string& find(const std::string& name) const; const std::string& find(int hdKey) const;
std::vector<std::string> findAll(const std::string& name) const; std::vector<std::string> findAll(int hdKey) const;
std::pair<std::multimap<std::string, std::string>::const_iterator, std::pair<std::multimap<int, std::string>::const_iterator,
std::multimap<std::string, std::string>::const_iterator> std::multimap<int, std::string>::const_iterator>
equalRange(const std::string& name) const; equalRange(int hdKey) const;
int32_t findAsInt(const std::string& name) const; int32_t findAsInt(int hdKey) const;
int64_t findAsLLInt(const std::string& name) const; int64_t findAsLLInt(int hdKey) const;
SharedHandle<Range> getRange() const; SharedHandle<Range> getRange() const;
@ -125,24 +156,7 @@ public:
// Returns true if heder field |name| contains |value|. This method // Returns true if heder field |name| contains |value|. This method
// assumes the values of the header field is delimited by ','. // assumes the values of the header field is delimited by ','.
bool fieldContains(const std::string& name, const std::string& value); bool fieldContains(int hdKey, const char* value);
static const std::string LOCATION;
static const std::string TRANSFER_ENCODING;
static const std::string CONTENT_ENCODING;
static const std::string CONTENT_DISPOSITION;
static const std::string SET_COOKIE;
static const std::string CONTENT_TYPE;
static const std::string RETRY_AFTER;
static const std::string CONNECTION;
static const std::string CONTENT_LENGTH;
static const std::string CONTENT_RANGE;
static const std::string LAST_MODIFIED;
static const std::string ACCEPT_ENCODING;
static const std::string LINK;
static const std::string DIGEST;
static const std::string AUTHORIZATION;
static const std::string PROXY_CONNECTION;
static const std::string HTTP_1_1; static const std::string HTTP_1_1;
static const std::string CLOSE; static const std::string CLOSE;
@ -152,8 +166,10 @@ public:
static const std::string DEFLATE; static const std::string DEFLATE;
}; };
int idInterestingHeader(const char* hdName);
typedef SharedHandle<HttpHeader> HttpHeaderHandle; typedef SharedHandle<HttpHeader> HttpHeaderHandle;
} // namespace std; } // namespace
#endif // D_HTTP_HEADER_H #endif // D_HTTP_HEADER_H

View File

@ -78,6 +78,7 @@ HttpHeaderProcessor::HttpHeaderProcessor(ParserMode mode)
: mode_(mode), : mode_(mode),
state_(mode == CLIENT_PARSER ? PREV_RES_VERSION : PREV_METHOD), state_(mode == CLIENT_PARSER ? PREV_RES_VERSION : PREV_METHOD),
lastBytesProcessed_(0), lastBytesProcessed_(0),
lastFieldHdKey_(HttpHeader::MAX_INTERESTING_HEADER),
result_(new HttpHeader()) result_(new HttpHeader())
{} {}
@ -118,6 +119,16 @@ size_t getText(std::string& buf,
} }
} // namespace } // namespace
namespace {
size_t ignoreText(std::string& buf,
const unsigned char* data, size_t length, size_t off)
{
size_t j;
for(j = off; j < length && !util::isCRLF(data[j]); ++j);
return j-1;
}
} // namespace
bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length) bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length)
{ {
size_t i; size_t i;
@ -276,9 +287,11 @@ bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length)
state_ = FIELD_VALUE; state_ = FIELD_VALUE;
} else { } else {
if(!lastFieldName_.empty()) { if(!lastFieldName_.empty()) {
util::lowercase(lastFieldName_); if(lastFieldHdKey_ != HttpHeader::MAX_INTERESTING_HEADER) {
result_->put(lastFieldName_, util::strip(buf_)); result_->put(lastFieldHdKey_, util::strip(buf_));
}
lastFieldName_.clear(); lastFieldName_.clear();
lastFieldHdKey_ = HttpHeader::MAX_INTERESTING_HEADER;
buf_.clear(); buf_.clear();
} }
if(c == '\n') { if(c == '\n') {
@ -297,6 +310,8 @@ bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length)
if(util::isLws(c) || util::isCRLF(c)) { if(util::isLws(c) || util::isCRLF(c)) {
throw DL_ABORT_EX("Bad HTTP header: missing ':'"); throw DL_ABORT_EX("Bad HTTP header: missing ':'");
} else if(c == ':') { } else if(c == ':') {
util::lowercase(lastFieldName_);
lastFieldHdKey_ = idInterestingHeader(lastFieldName_.c_str());
state_ = PREV_FIELD_VALUE; state_ = PREV_FIELD_VALUE;
} else { } else {
i = getFieldNameToken(lastFieldName_, data, length, i); i = getFieldNameToken(lastFieldName_, data, length, i);
@ -309,17 +324,25 @@ bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length)
state_ = PREV_FIELD_NAME; state_ = PREV_FIELD_NAME;
} else if(!util::isLws(c)) { } else if(!util::isLws(c)) {
state_ = FIELD_VALUE; state_ = FIELD_VALUE;
if(lastFieldHdKey_ == HttpHeader::MAX_INTERESTING_HEADER) {
i = ignoreText(buf_, data, length, i);
} else {
i = getText(buf_, data, length, i); i = getText(buf_, data, length, i);
} }
}
break; break;
case FIELD_VALUE: case FIELD_VALUE:
if(c == '\r') { if(c == '\r') {
state_ = PREV_EOL; state_ = PREV_EOL;
} else if(c == '\n') { } else if(c == '\n') {
state_ = PREV_FIELD_NAME; state_ = PREV_FIELD_NAME;
} else {
if(lastFieldHdKey_ == HttpHeader::MAX_INTERESTING_HEADER) {
i = ignoreText(buf_, data, length, i);
} else { } else {
i = getText(buf_, data, length, i); i = getText(buf_, data, length, i);
} }
}
break; break;
case PREV_EOH: case PREV_EOH:
if(c == '\n') { if(c == '\n') {
@ -363,6 +386,7 @@ void HttpHeaderProcessor::clear()
lastBytesProcessed_ = 0; lastBytesProcessed_ = 0;
buf_.clear(); buf_.clear();
lastFieldName_.clear(); lastFieldName_.clear();
lastFieldHdKey_ = HttpHeader::MAX_INTERESTING_HEADER;
result_.reset(new HttpHeader()); result_.reset(new HttpHeader());
headers_.clear(); headers_.clear();
} }

View File

@ -88,6 +88,7 @@ private:
size_t lastBytesProcessed_; size_t lastBytesProcessed_;
std::string buf_; std::string buf_;
std::string lastFieldName_; std::string lastFieldName_;
int lastFieldHdKey_;
SharedHandle<HttpHeader> result_; SharedHandle<HttpHeader> result_;
std::string headers_; std::string headers_;
}; };

View File

@ -140,8 +140,8 @@ std::string HttpResponse::determinFilename() const
void HttpResponse::retrieveCookie() void HttpResponse::retrieveCookie()
{ {
Time now; Time now;
std::pair<std::multimap<std::string, std::string>::const_iterator, std::pair<std::multimap<int, std::string>::const_iterator,
std::multimap<std::string, std::string>::const_iterator> r = std::multimap<int, std::string>::const_iterator> r =
httpHeader_->equalRange(HttpHeader::SET_COOKIE); httpHeader_->equalRange(HttpHeader::SET_COOKIE);
for(; r.first != r.second; ++r.first) { for(; r.first != r.second; ++r.first) {
httpRequest_->getCookieStorage()->parseAndStore httpRequest_->getCookieStorage()->parseAndStore
@ -162,7 +162,6 @@ bool HttpResponse::isRedirect() const
void HttpResponse::processRedirect() void HttpResponse::processRedirect()
{ {
if(httpRequest_->getRequest()->redirectUri if(httpRequest_->getRequest()->redirectUri
(util::percentEncodeMini(getRedirectURI()))) { (util::percentEncodeMini(getRedirectURI()))) {
A2_LOG_INFO(fmt(MSG_REDIRECT, A2_LOG_INFO(fmt(MSG_REDIRECT,
@ -375,8 +374,8 @@ void HttpResponse::getMetalinKHttpEntries
(std::vector<MetalinkHttpEntry>& result, (std::vector<MetalinkHttpEntry>& result,
const SharedHandle<Option>& option) const const SharedHandle<Option>& option) const
{ {
std::pair<std::multimap<std::string, std::string>::const_iterator, std::pair<std::multimap<int, std::string>::const_iterator,
std::multimap<std::string, std::string>::const_iterator> p = std::multimap<int, std::string>::const_iterator> p =
httpHeader_->equalRange(HttpHeader::LINK); httpHeader_->equalRange(HttpHeader::LINK);
for(; p.first != p.second; ++p.first) { for(; p.first != p.second; ++p.first) {
MetalinkHttpEntry e; MetalinkHttpEntry e;
@ -410,8 +409,8 @@ void HttpResponse::getMetalinKHttpEntries
void HttpResponse::getDigest(std::vector<Checksum>& result) const void HttpResponse::getDigest(std::vector<Checksum>& result) const
{ {
using std::swap; using std::swap;
std::pair<std::multimap<std::string, std::string>::const_iterator, std::pair<std::multimap<int, std::string>::const_iterator,
std::multimap<std::string, std::string>::const_iterator> p = std::multimap<int, std::string>::const_iterator> p =
httpHeader_->equalRange(HttpHeader::DIGEST); httpHeader_->equalRange(HttpHeader::DIGEST);
for(; p.first != p.second; ++p.first) { for(; p.first != p.second; ++p.first) {
const std::string& s = (*p.first).second; const std::string& s = (*p.first).second;

View File

@ -169,14 +169,14 @@ bool HttpServerBodyCommand::execute()
const SharedHandle<HttpHeader>& header = const SharedHandle<HttpHeader>& header =
httpServer_->getRequestHeader(); httpServer_->getRequestHeader();
std::string accessControlHeaders; std::string accessControlHeaders;
if(!header->find("origin").empty() && if(!header->find(HttpHeader::ORIGIN).empty() &&
!header->find("access-control-request-method").empty() && !header->find(HttpHeader::ACCESS_CONTROL_REQUEST_METHOD).empty()
!httpServer_->getAllowOrigin().empty()) { && !httpServer_->getAllowOrigin().empty()) {
accessControlHeaders += accessControlHeaders +=
"Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n" "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n"
"Access-Control-Max-Age: 1728000\r\n"; "Access-Control-Max-Age: 1728000\r\n";
const std::string& accReqHeaders = const std::string& accReqHeaders =
header->find("access-control-request-headers"); header->find(HttpHeader::ACCESS_CONTROL_REQUEST_HEADERS);
if(!accReqHeaders.empty()) { if(!accReqHeaders.empty()) {
// We allow all headers requested. // We allow all headers requested.
accessControlHeaders += "Access-Control-Allow-Headers: "; accessControlHeaders += "Access-Control-Allow-Headers: ";

View File

@ -133,9 +133,9 @@ namespace {
int websocketHandshake(const SharedHandle<HttpHeader>& header) int websocketHandshake(const SharedHandle<HttpHeader>& header)
{ {
if(header->getMethod() != "GET" || if(header->getMethod() != "GET" ||
header->find("sec-websocket-key").empty()) { header->find(HttpHeader::SEC_WEBSOCKET_KEY).empty()) {
return 400; return 400;
} else if(header->find("sec-websocket-version") != "13") { } else if(header->find(HttpHeader::SEC_WEBSOCKET_VERSION) != "13") {
return 426; return 426;
} else if(header->getRequestPath() != "/jsonrpc") { } else if(header->getRequestPath() != "/jsonrpc") {
return 404; return 404;
@ -177,14 +177,15 @@ bool HttpServerCommand::execute()
e_->setNoWait(true); e_->setNoWait(true);
return true; return true;
} }
if(header->fieldContains("upgrade", "websocket") && if(header->fieldContains(HttpHeader::UPGRADE, "websocket") &&
header->fieldContains("connection", "upgrade")) { header->fieldContains(HttpHeader::CONNECTION, "upgrade")) {
#ifdef ENABLE_WEBSOCKET #ifdef ENABLE_WEBSOCKET
int status = websocketHandshake(header); int status = websocketHandshake(header);
Command* command; Command* command;
if(status == 101) { if(status == 101) {
std::string serverKey = std::string serverKey =
createWebSocketServerKey(header->find("sec-websocket-key")); createWebSocketServerKey
(header->find(HttpHeader::SEC_WEBSOCKET_KEY));
httpServer_->feedUpgradeResponse("websocket", httpServer_->feedUpgradeResponse("websocket",
fmt("Sec-WebSocket-Accept: %s\r\n", fmt("Sec-WebSocket-Accept: %s\r\n",
serverKey.c_str())); serverKey.c_str()));

View File

@ -93,10 +93,8 @@ SharedHandle<LpdMessage> LpdMessageReceiver::receiveMessage()
return msg; return msg;
} }
const SharedHandle<HttpHeader>& header = proc.getResult(); const SharedHandle<HttpHeader>& header = proc.getResult();
static const std::string A2_INFOHASH = "infohash"; const std::string& infoHashString = header->find(HttpHeader::INFOHASH);
static const std::string A2_PORT = "port"; uint16_t port = header->findAsInt(HttpHeader::PORT);
const std::string& infoHashString = header->find(A2_INFOHASH);
uint16_t port = header->findAsInt(A2_PORT);
A2_LOG_INFO(fmt("LPD message received infohash=%s, port=%u from %s", A2_LOG_INFO(fmt("LPD message received infohash=%s, port=%u from %s",
infoHashString.c_str(), infoHashString.c_str(),
port, port,

View File

@ -1725,6 +1725,11 @@ bool iendsWith(const std::string& a, const std::string& b)
return iendsWith(a.begin(), a.end(), b.begin(), b.end()); return iendsWith(a.begin(), a.end(), b.begin(), b.end());
} }
bool strless(const char* a, const char* b)
{
return strcmp(a, b) < 0;
}
} // namespace util } // namespace util
} // namespace aria2 } // namespace aria2

View File

@ -714,6 +714,9 @@ bool iendsWith
bool iendsWith(const std::string& a, const char* b); bool iendsWith(const std::string& a, const char* b);
bool iendsWith(const std::string& a, const std::string& b); bool iendsWith(const std::string& a, const std::string& b);
// Returns true if strcmp(a, b) < 0
bool strless(const char* a, const char *b);
void generateRandomData(unsigned char* data, size_t length); void generateRandomData(unsigned char* data, size_t length);
// Saves data to file whose name is filename. If overwrite is true, // Saves data to file whose name is filename. If overwrite is true,

View File

@ -68,27 +68,24 @@ void HttpHeaderProcessorTest::testParse3()
"GET / HTTP/1.1\r\n" "GET / HTTP/1.1\r\n"
"Host: aria2.sourceforge.net\r\n" "Host: aria2.sourceforge.net\r\n"
"Connection: close \r\n" // trailing white space (BWS) "Connection: close \r\n" // trailing white space (BWS)
"Multi-Line: text1\r\n" // Multi-line header "Accept-Encoding: text1\r\n" // Multi-line header
" text2\r\n" " text2\r\n"
" text3\r\n" " text3\r\n"
"Duplicate: foo\r\n" "Authorization: foo\r\n"
"Duplicate: bar\r\n" "Authorization: bar\r\n"
"No-value:\r\n" "Content-Type:\r\n"
"\r\n"; "\r\n";
CPPUNIT_ASSERT(proc.parse(s)); CPPUNIT_ASSERT(proc.parse(s));
SharedHandle<HttpHeader> h = proc.getResult(); SharedHandle<HttpHeader> h = proc.getResult();
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sourceforge.net"), CPPUNIT_ASSERT_EQUAL(std::string("close"), h->find(HttpHeader::CONNECTION));
h->find("host"));
CPPUNIT_ASSERT_EQUAL(std::string("close"),
h->find("connection"));
CPPUNIT_ASSERT_EQUAL(std::string("text1 text2 text3"), CPPUNIT_ASSERT_EQUAL(std::string("text1 text2 text3"),
h->find("multi-line")); h->find(HttpHeader::ACCEPT_ENCODING));
CPPUNIT_ASSERT_EQUAL(std::string("foo"), CPPUNIT_ASSERT_EQUAL(std::string("foo"),
h->findAll("duplicate")[0]); h->findAll(HttpHeader::AUTHORIZATION)[0]);
CPPUNIT_ASSERT_EQUAL(std::string("bar"), CPPUNIT_ASSERT_EQUAL(std::string("bar"),
h->findAll("duplicate")[1]); h->findAll(HttpHeader::AUTHORIZATION)[1]);
CPPUNIT_ASSERT_EQUAL(std::string(""), h->find("no-value")); CPPUNIT_ASSERT_EQUAL(std::string(""), h->find(HttpHeader::CONTENT_TYPE));
CPPUNIT_ASSERT(h->defined("no-value")); CPPUNIT_ASSERT(h->defined(HttpHeader::CONTENT_TYPE));
} }
void HttpHeaderProcessorTest::testGetLastBytesProcessed() void HttpHeaderProcessorTest::testGetLastBytesProcessed()
@ -135,7 +132,7 @@ void HttpHeaderProcessorTest::testGetHttpResponseHeader()
"Connection: close\r\n" "Connection: close\r\n"
"Content-Type: text/html; charset=UTF-8\r\n" "Content-Type: text/html; charset=UTF-8\r\n"
"\r\n" "\r\n"
"Entity: body"; "Content-Encoding: body";
CPPUNIT_ASSERT(proc.parse(hd)); CPPUNIT_ASSERT(proc.parse(hd));
@ -143,15 +140,11 @@ void HttpHeaderProcessorTest::testGetHttpResponseHeader()
CPPUNIT_ASSERT_EQUAL(404, header->getStatusCode()); CPPUNIT_ASSERT_EQUAL(404, header->getStatusCode());
CPPUNIT_ASSERT_EQUAL(std::string("Not Found"), header->getReasonPhrase()); CPPUNIT_ASSERT_EQUAL(std::string("Not Found"), header->getReasonPhrase());
CPPUNIT_ASSERT_EQUAL(std::string("HTTP/1.1"), header->getVersion()); CPPUNIT_ASSERT_EQUAL(std::string("HTTP/1.1"), header->getVersion());
CPPUNIT_ASSERT_EQUAL(std::string("Mon, 25 Jun 2007 16:04:59 GMT"),
header->find("date"));
CPPUNIT_ASSERT_EQUAL(std::string("Apache/2.2.3 (Debian)"),
header->find("server"));
CPPUNIT_ASSERT_EQUAL((int64_t)9187LL, CPPUNIT_ASSERT_EQUAL((int64_t)9187LL,
header->findAsLLInt("content-length")); header->findAsLLInt(HttpHeader::CONTENT_LENGTH));
CPPUNIT_ASSERT_EQUAL(std::string("text/html; charset=UTF-8"), CPPUNIT_ASSERT_EQUAL(std::string("text/html; charset=UTF-8"),
header->find("content-type")); header->find(HttpHeader::CONTENT_TYPE));
CPPUNIT_ASSERT(!header->defined("entity")); CPPUNIT_ASSERT(!header->defined(HttpHeader::CONTENT_ENCODING));
} }
void HttpHeaderProcessorTest::testGetHttpResponseHeader_statusOnly() void HttpHeaderProcessorTest::testGetHttpResponseHeader_statusOnly()
@ -272,7 +265,7 @@ void HttpHeaderProcessorTest::testGetHttpRequestHeader()
"Host: host\r\n" "Host: host\r\n"
"Connection: close\r\n" "Connection: close\r\n"
"\r\n" "\r\n"
"Entity: body"; "Content-Encoding: body";
CPPUNIT_ASSERT(proc.parse(request)); CPPUNIT_ASSERT(proc.parse(request));
@ -280,8 +273,9 @@ void HttpHeaderProcessorTest::testGetHttpRequestHeader()
CPPUNIT_ASSERT_EQUAL(std::string("GET"), httpHeader->getMethod()); CPPUNIT_ASSERT_EQUAL(std::string("GET"), httpHeader->getMethod());
CPPUNIT_ASSERT_EQUAL(std::string("/index.html"),httpHeader->getRequestPath()); CPPUNIT_ASSERT_EQUAL(std::string("/index.html"),httpHeader->getRequestPath());
CPPUNIT_ASSERT_EQUAL(std::string("HTTP/1.1"), httpHeader->getVersion()); CPPUNIT_ASSERT_EQUAL(std::string("HTTP/1.1"), httpHeader->getVersion());
CPPUNIT_ASSERT_EQUAL(std::string("close"),httpHeader->find("connection")); CPPUNIT_ASSERT_EQUAL(std::string("close"),
CPPUNIT_ASSERT(!httpHeader->defined("entity")); httpHeader->find(HttpHeader::CONNECTION));
CPPUNIT_ASSERT(!httpHeader->defined(HttpHeader::CONTENT_ENCODING));
} }
} // namespace aria2 } // namespace aria2

View File

@ -29,7 +29,7 @@ void HttpHeaderTest::testGetRange()
{ {
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", httpHeader.put(HttpHeader::CONTENT_RANGE,
"9223372036854775800-9223372036854775801/9223372036854775807"); "9223372036854775800-9223372036854775801/9223372036854775807");
SharedHandle<Range> range = httpHeader.getRange(); SharedHandle<Range> range = httpHeader.getRange();
@ -40,7 +40,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", httpHeader.put(HttpHeader::CONTENT_RANGE,
"9223372036854775800-9223372036854775801/9223372036854775807"); "9223372036854775800-9223372036854775801/9223372036854775807");
SharedHandle<Range> range = httpHeader.getRange(); SharedHandle<Range> range = httpHeader.getRange();
@ -51,7 +51,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", "bytes */1024"); httpHeader.put(HttpHeader::CONTENT_RANGE, "bytes */1024");
SharedHandle<Range> range = httpHeader.getRange(); SharedHandle<Range> range = httpHeader.getRange();
@ -61,7 +61,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", "bytes 0-9/*"); httpHeader.put(HttpHeader::CONTENT_RANGE, "bytes 0-9/*");
SharedHandle<Range> range = httpHeader.getRange(); SharedHandle<Range> range = httpHeader.getRange();
@ -71,7 +71,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", "bytes */*"); httpHeader.put(HttpHeader::CONTENT_RANGE, "bytes */*");
SharedHandle<Range> range = httpHeader.getRange(); SharedHandle<Range> range = httpHeader.getRange();
@ -81,7 +81,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", "bytes 0"); httpHeader.put(HttpHeader::CONTENT_RANGE, "bytes 0");
SharedHandle<Range> range = httpHeader.getRange(); SharedHandle<Range> range = httpHeader.getRange();
@ -91,7 +91,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", "bytes 0/"); httpHeader.put(HttpHeader::CONTENT_RANGE, "bytes 0/");
SharedHandle<Range> range = httpHeader.getRange(); SharedHandle<Range> range = httpHeader.getRange();
@ -101,7 +101,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", "bytes 0-/3"); httpHeader.put(HttpHeader::CONTENT_RANGE, "bytes 0-/3");
try { try {
httpHeader.getRange(); httpHeader.getRange();
CPPUNIT_FAIL("Exception must be thrown"); CPPUNIT_FAIL("Exception must be thrown");
@ -111,7 +111,7 @@ void HttpHeaderTest::testGetRange()
} }
{ {
HttpHeader httpHeader; HttpHeader httpHeader;
httpHeader.put("content-range", "bytes -0/3"); httpHeader.put(HttpHeader::CONTENT_RANGE, "bytes -0/3");
try { try {
httpHeader.getRange(); httpHeader.getRange();
CPPUNIT_FAIL("Exception must be thrown"); CPPUNIT_FAIL("Exception must be thrown");
@ -124,11 +124,11 @@ void HttpHeaderTest::testGetRange()
void HttpHeaderTest::testFindAll() void HttpHeaderTest::testFindAll()
{ {
HttpHeader h; HttpHeader h;
h.put("A", "100"); h.put(HttpHeader::LINK, "100");
h.put("A", "101"); h.put(HttpHeader::LINK, "101");
h.put("B", "200"); h.put(HttpHeader::CONNECTION, "200");
std::vector<std::string> r(h.findAll("A")); std::vector<std::string> r(h.findAll(HttpHeader::LINK));
CPPUNIT_ASSERT_EQUAL((size_t)2, r.size()); CPPUNIT_ASSERT_EQUAL((size_t)2, r.size());
CPPUNIT_ASSERT_EQUAL(std::string("100"), r[0]); CPPUNIT_ASSERT_EQUAL(std::string("100"), r[0]);
CPPUNIT_ASSERT_EQUAL(std::string("101"), r[1]); CPPUNIT_ASSERT_EQUAL(std::string("101"), r[1]);
@ -139,13 +139,13 @@ void HttpHeaderTest::testClearField()
HttpHeader h; HttpHeader h;
h.setStatusCode(200); h.setStatusCode(200);
h.setVersion(HttpHeader::HTTP_1_1); h.setVersion(HttpHeader::HTTP_1_1);
h.put("Foo", "Bar"); h.put(HttpHeader::LINK, "Bar");
CPPUNIT_ASSERT_EQUAL(std::string("Bar"), h.find("Foo")); CPPUNIT_ASSERT_EQUAL(std::string("Bar"), h.find(HttpHeader::LINK));
h.clearField(); h.clearField();
CPPUNIT_ASSERT_EQUAL(std::string(""), h.find("Foo")); CPPUNIT_ASSERT_EQUAL(std::string(""), h.find(HttpHeader::LINK));
CPPUNIT_ASSERT_EQUAL(200, h.getStatusCode()); CPPUNIT_ASSERT_EQUAL(200, h.getStatusCode());
CPPUNIT_ASSERT_EQUAL(std::string(HttpHeader::HTTP_1_1), h.getVersion()); CPPUNIT_ASSERT_EQUAL(std::string(HttpHeader::HTTP_1_1), h.getVersion());
} }
@ -153,18 +153,18 @@ void HttpHeaderTest::testClearField()
void HttpHeaderTest::testFieldContains() void HttpHeaderTest::testFieldContains()
{ {
HttpHeader h; HttpHeader h;
h.put("connection", "Keep-Alive, Upgrade"); h.put(HttpHeader::CONNECTION, "Keep-Alive, Upgrade");
h.put("upgrade", "WebSocket"); h.put(HttpHeader::UPGRADE, "WebSocket");
h.put("sec-websocket-version", "13"); h.put(HttpHeader::SEC_WEBSOCKET_VERSION, "13");
h.put("sec-websocket-version", "8, 7"); h.put(HttpHeader::SEC_WEBSOCKET_VERSION, "8, 7");
CPPUNIT_ASSERT(h.fieldContains("connection", "upgrade")); CPPUNIT_ASSERT(h.fieldContains(HttpHeader::CONNECTION, "upgrade"));
CPPUNIT_ASSERT(h.fieldContains("connection", "keep-alive")); CPPUNIT_ASSERT(h.fieldContains(HttpHeader::CONNECTION, "keep-alive"));
CPPUNIT_ASSERT(!h.fieldContains("connection", "close")); CPPUNIT_ASSERT(!h.fieldContains(HttpHeader::CONNECTION, "close"));
CPPUNIT_ASSERT(h.fieldContains("upgrade", "websocket")); CPPUNIT_ASSERT(h.fieldContains(HttpHeader::UPGRADE, "websocket"));
CPPUNIT_ASSERT(!h.fieldContains("upgrade", "spdy")); CPPUNIT_ASSERT(!h.fieldContains(HttpHeader::UPGRADE, "spdy"));
CPPUNIT_ASSERT(h.fieldContains("sec-websocket-version", "13")); CPPUNIT_ASSERT(h.fieldContains(HttpHeader::SEC_WEBSOCKET_VERSION, "13"));
CPPUNIT_ASSERT(h.fieldContains("sec-websocket-version", "8")); CPPUNIT_ASSERT(h.fieldContains(HttpHeader::SEC_WEBSOCKET_VERSION, "8"));
CPPUNIT_ASSERT(!h.fieldContains("sec-websocket-version", "6")); CPPUNIT_ASSERT(!h.fieldContains(HttpHeader::SEC_WEBSOCKET_VERSION, "6"));
} }
} // namespace aria2 } // namespace aria2

View File

@ -109,7 +109,7 @@ void HttpResponseTest::testGetContentLength_contentLength()
HttpResponse httpResponse; HttpResponse httpResponse;
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpHeader->put("content-length", "4294967296"); httpHeader->put(HttpHeader::CONTENT_LENGTH, "4294967296");
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
@ -121,13 +121,13 @@ void HttpResponseTest::testGetEntityLength()
HttpResponse httpResponse; HttpResponse httpResponse;
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpHeader->put("content-length", "4294967296"); httpHeader->put(HttpHeader::CONTENT_LENGTH, "4294967296");
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
CPPUNIT_ASSERT_EQUAL((int64_t)4294967296LL, httpResponse.getEntityLength()); CPPUNIT_ASSERT_EQUAL((int64_t)4294967296LL, httpResponse.getEntityLength());
httpHeader->put("content-range", "bytes 1-4294967296/4294967297"); httpHeader->put(HttpHeader::CONTENT_RANGE, "bytes 1-4294967296/4294967297");
CPPUNIT_ASSERT_EQUAL((int64_t)4294967297LL, httpResponse.getEntityLength()); CPPUNIT_ASSERT_EQUAL((int64_t)4294967297LL, httpResponse.getEntityLength());
@ -137,7 +137,8 @@ void HttpResponseTest::testGetContentType()
{ {
HttpResponse httpResponse; HttpResponse httpResponse;
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpHeader->put("content-type", "application/metalink+xml; charset=UTF-8"); httpHeader->put(HttpHeader::CONTENT_TYPE,
"application/metalink+xml; charset=UTF-8");
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
// See paramter is ignored. // See paramter is ignored.
CPPUNIT_ASSERT_EQUAL(std::string("application/metalink+xml"), CPPUNIT_ASSERT_EQUAL(std::string("application/metalink+xml"),
@ -165,7 +166,7 @@ void HttpResponseTest::testDeterminFilename_with_ContentDisposition_zero_length
{ {
HttpResponse httpResponse; HttpResponse httpResponse;
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpHeader->put("content-disposition", "attachment; filename=\"\""); httpHeader->put(HttpHeader::CONTENT_DISPOSITION, "attachment; filename=\"\"");
SharedHandle<HttpRequest> httpRequest(new HttpRequest()); SharedHandle<HttpRequest> httpRequest(new HttpRequest());
SharedHandle<Request> request(new Request()); SharedHandle<Request> request(new Request());
request->setUri("http://localhost/archives/aria2-1.0.0.tar.bz2"); request->setUri("http://localhost/archives/aria2-1.0.0.tar.bz2");
@ -182,7 +183,7 @@ void HttpResponseTest::testDeterminFilename_with_ContentDisposition()
{ {
HttpResponse httpResponse; HttpResponse httpResponse;
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpHeader->put("content-disposition", httpHeader->put(HttpHeader::CONTENT_DISPOSITION,
"attachment; filename=\"aria2-current.tar.bz2\""); "attachment; filename=\"aria2-current.tar.bz2\"");
SharedHandle<HttpRequest> httpRequest(new HttpRequest()); SharedHandle<HttpRequest> httpRequest(new HttpRequest());
SharedHandle<Request> request(new Request()); SharedHandle<Request> request(new Request());
@ -211,7 +212,7 @@ void HttpResponseTest::testGetRedirectURI_with_Location()
{ {
HttpResponse httpResponse; HttpResponse httpResponse;
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpHeader->put("location", "http://localhost/download/aria2-1.0.0.tar.bz2"); httpHeader->put(HttpHeader::LOCATION, "http://localhost/download/aria2-1.0.0.tar.bz2");
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
CPPUNIT_ASSERT_EQUAL CPPUNIT_ASSERT_EQUAL
@ -224,7 +225,8 @@ void HttpResponseTest::testIsRedirect()
HttpResponse httpResponse; HttpResponse httpResponse;
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpHeader->setStatusCode(200); httpHeader->setStatusCode(200);
httpHeader->put("location", "http://localhost/download/aria2-1.0.0.tar.bz2"); httpHeader->put(HttpHeader::LOCATION,
"http://localhost/download/aria2-1.0.0.tar.bz2");
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
@ -244,7 +246,7 @@ void HttpResponseTest::testIsTransferEncodingSpecified()
CPPUNIT_ASSERT(!httpResponse.isTransferEncodingSpecified()); CPPUNIT_ASSERT(!httpResponse.isTransferEncodingSpecified());
httpHeader->put("transfer-encoding", "chunked"); httpHeader->put(HttpHeader::TRANSFER_ENCODING, "chunked");
CPPUNIT_ASSERT(httpResponse.isTransferEncodingSpecified()); CPPUNIT_ASSERT(httpResponse.isTransferEncodingSpecified());
} }
@ -258,7 +260,7 @@ void HttpResponseTest::testGetTransferEncoding()
CPPUNIT_ASSERT_EQUAL(std::string(""), httpResponse.getTransferEncoding()); CPPUNIT_ASSERT_EQUAL(std::string(""), httpResponse.getTransferEncoding());
httpHeader->put("transfer-encoding", "chunked"); httpHeader->put(HttpHeader::TRANSFER_ENCODING, "chunked");
CPPUNIT_ASSERT_EQUAL(std::string("chunked"), CPPUNIT_ASSERT_EQUAL(std::string("chunked"),
httpResponse.getTransferEncoding()); httpResponse.getTransferEncoding());
@ -273,7 +275,7 @@ void HttpResponseTest::testGetTransferEncodingStreamFilter()
CPPUNIT_ASSERT(!httpResponse.getTransferEncodingStreamFilter()); CPPUNIT_ASSERT(!httpResponse.getTransferEncodingStreamFilter());
httpHeader->put("transfer-encoding", "chunked"); httpHeader->put(HttpHeader::TRANSFER_ENCODING, "chunked");
CPPUNIT_ASSERT(httpResponse.getTransferEncodingStreamFilter()); CPPUNIT_ASSERT(httpResponse.getTransferEncodingStreamFilter());
} }
@ -287,7 +289,7 @@ void HttpResponseTest::testIsContentEncodingSpecified()
CPPUNIT_ASSERT(!httpResponse.isContentEncodingSpecified()); CPPUNIT_ASSERT(!httpResponse.isContentEncodingSpecified());
httpHeader->put("content-encoding", "gzip"); httpHeader->put(HttpHeader::CONTENT_ENCODING, "gzip");
CPPUNIT_ASSERT(httpResponse.isContentEncodingSpecified()); CPPUNIT_ASSERT(httpResponse.isContentEncodingSpecified());
} }
@ -301,7 +303,7 @@ void HttpResponseTest::testGetContentEncoding()
CPPUNIT_ASSERT_EQUAL(A2STR::NIL, httpResponse.getContentEncoding()); CPPUNIT_ASSERT_EQUAL(A2STR::NIL, httpResponse.getContentEncoding());
httpHeader->put("content-encoding", "gzip"); httpHeader->put(HttpHeader::CONTENT_ENCODING, "gzip");
CPPUNIT_ASSERT_EQUAL(std::string("gzip"), httpResponse.getContentEncoding()); CPPUNIT_ASSERT_EQUAL(std::string("gzip"), httpResponse.getContentEncoding());
} }
@ -316,7 +318,7 @@ void HttpResponseTest::testGetContentEncodingStreamFilter()
CPPUNIT_ASSERT(!httpResponse.getContentEncodingStreamFilter()); CPPUNIT_ASSERT(!httpResponse.getContentEncodingStreamFilter());
#ifdef HAVE_ZLIB #ifdef HAVE_ZLIB
httpHeader->put("content-encoding", "gzip"); httpHeader->put(HttpHeader::CONTENT_ENCODING, "gzip");
{ {
SharedHandle<StreamFilter> filter = SharedHandle<StreamFilter> filter =
httpResponse.getContentEncodingStreamFilter(); httpResponse.getContentEncodingStreamFilter();
@ -326,7 +328,7 @@ void HttpResponseTest::testGetContentEncodingStreamFilter()
} }
httpHeader.reset(new HttpHeader()); httpHeader.reset(new HttpHeader());
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
httpHeader->put("content-encoding", "deflate"); httpHeader->put(HttpHeader::CONTENT_ENCODING, "deflate");
{ {
SharedHandle<StreamFilter> filter = SharedHandle<StreamFilter> filter =
httpResponse.getContentEncodingStreamFilter(); httpResponse.getContentEncodingStreamFilter();
@ -337,7 +339,7 @@ void HttpResponseTest::testGetContentEncodingStreamFilter()
#endif // HAVE_ZLIB #endif // HAVE_ZLIB
httpHeader.reset(new HttpHeader()); httpHeader.reset(new HttpHeader());
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
httpHeader->put("content-encoding", "bzip2"); httpHeader->put(HttpHeader::CONTENT_ENCODING, "bzip2");
{ {
SharedHandle<StreamFilter> filter = SharedHandle<StreamFilter> filter =
httpResponse.getContentEncodingStreamFilter(); httpResponse.getContentEncodingStreamFilter();
@ -359,7 +361,8 @@ void HttpResponseTest::testValidateResponse()
} catch(Exception& e) { } catch(Exception& e) {
} }
httpHeader->put("location", "http://localhost/archives/aria2-1.0.0.tar.bz2"); httpHeader->put(HttpHeader::LOCATION,
"http://localhost/archives/aria2-1.0.0.tar.bz2");
try { try {
httpResponse.validateResponse(); httpResponse.validateResponse();
} catch(Exception& e) { } catch(Exception& e) {
@ -384,7 +387,7 @@ void HttpResponseTest::testValidateResponse_good_range()
httpRequest->setRequest(request); httpRequest->setRequest(request);
httpResponse.setHttpRequest(httpRequest); httpResponse.setHttpRequest(httpRequest);
httpHeader->setStatusCode(206); httpHeader->setStatusCode(206);
httpHeader->put("content-range", "bytes 1048576-10485760/10485760"); httpHeader->put(HttpHeader::CONTENT_RANGE, "bytes 1048576-10485760/10485760");
try { try {
httpResponse.validateResponse(); httpResponse.validateResponse();
@ -411,7 +414,7 @@ void HttpResponseTest::testValidateResponse_bad_range()
httpRequest->setRequest(request); httpRequest->setRequest(request);
httpResponse.setHttpRequest(httpRequest); httpResponse.setHttpRequest(httpRequest);
httpHeader->setStatusCode(206); httpHeader->setStatusCode(206);
httpHeader->put("content-range", "bytes 0-10485760/10485761"); httpHeader->put(HttpHeader::CONTENT_RANGE, "bytes 0-10485760/10485761");
try { try {
httpResponse.validateResponse(); httpResponse.validateResponse();
@ -437,8 +440,8 @@ void HttpResponseTest::testValidateResponse_chunked()
httpRequest->setRequest(request); httpRequest->setRequest(request);
httpResponse.setHttpRequest(httpRequest); httpResponse.setHttpRequest(httpRequest);
httpHeader->setStatusCode(206); httpHeader->setStatusCode(206);
httpHeader->put("content-range", "bytes 0-10485760/10485761"); httpHeader->put(HttpHeader::CONTENT_RANGE, "bytes 0-10485760/10485761");
httpHeader->put("transfer-encoding", "chunked"); httpHeader->put(HttpHeader::TRANSFER_ENCODING, "chunked");
// if transfer-encoding is specified, then range validation is skipped. // if transfer-encoding is specified, then range validation is skipped.
try { try {
@ -471,7 +474,7 @@ void HttpResponseTest::testHasRetryAfter()
SharedHandle<HttpHeader> httpHeader(new HttpHeader()); SharedHandle<HttpHeader> httpHeader(new HttpHeader());
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
httpHeader->put("retry-after", "60"); httpHeader->put(HttpHeader::RETRY_AFTER, "60");
CPPUNIT_ASSERT(httpResponse.hasRetryAfter()); CPPUNIT_ASSERT(httpResponse.hasRetryAfter());
CPPUNIT_ASSERT_EQUAL((time_t)60, httpResponse.getRetryAfter()); CPPUNIT_ASSERT_EQUAL((time_t)60, httpResponse.getRetryAfter());
@ -489,13 +492,13 @@ void HttpResponseTest::testProcessRedirect()
httpRequest->setRequest(request); httpRequest->setRequest(request);
httpResponse.setHttpRequest(httpRequest); httpResponse.setHttpRequest(httpRequest);
httpHeader->put("location", "http://mirror/aria2-1.0.0.tar.bz2"); httpHeader->put(HttpHeader::LOCATION, "http://mirror/aria2-1.0.0.tar.bz2");
httpResponse.processRedirect(); httpResponse.processRedirect();
httpHeader->clearField(); httpHeader->clearField();
// Test for percent-encode // Test for percent-encode
httpHeader->put("location", "http://example.org/white space#aria2"); httpHeader->put(HttpHeader::LOCATION, "http://example.org/white space#aria2");
httpResponse.processRedirect(); httpResponse.processRedirect();
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/white%20space"), CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/white%20space"),
request->getCurrentUri()); request->getCurrentUri());
@ -503,7 +506,8 @@ void HttpResponseTest::testProcessRedirect()
httpHeader->clearField(); httpHeader->clearField();
// Give unsupported scheme // Give unsupported scheme
httpHeader->put("location", "unsupported://mirror/aria2-1.0.0.tar.bz2"); httpHeader->put(HttpHeader::LOCATION,
"unsupported://mirror/aria2-1.0.0.tar.bz2");
try { try {
httpResponse.processRedirect(); httpResponse.processRedirect();
CPPUNIT_FAIL("DlRetryEx exception must be thrown."); CPPUNIT_FAIL("DlRetryEx exception must be thrown.");
@ -528,11 +532,13 @@ void HttpResponseTest::testRetrieveCookie()
httpRequest->setCookieStorage(st); httpRequest->setCookieStorage(st);
httpResponse.setHttpRequest(httpRequest); httpResponse.setHttpRequest(httpRequest);
httpHeader->put("set-cookie", "k1=v1; expires=Sun, 10-Jun-2007 11:00:00 GMT;" httpHeader->put(HttpHeader::SET_COOKIE,
"k1=v1; expires=Sun, 10-Jun-2007 11:00:00 GMT;"
"path=/; domain=.aria2.org;"); "path=/; domain=.aria2.org;");
httpHeader->put("set-cookie", "k2=v2; expires=Sun, 01-Jan-38 00:00:00 GMT;" httpHeader->put(HttpHeader::SET_COOKIE,
"k2=v2; expires=Sun, 01-Jan-38 00:00:00 GMT;"
"path=/; domain=.aria2.org;"); "path=/; domain=.aria2.org;");
httpHeader->put("set-cookie", "k3=v3;"); httpHeader->put(HttpHeader::SET_COOKIE, "k3=v3;");
httpResponse.retrieveCookie(); httpResponse.retrieveCookie();
@ -554,19 +560,19 @@ void HttpResponseTest::testSupportsPersistentConnection()
httpHeader->setVersion("HTTP/1.1"); httpHeader->setVersion("HTTP/1.1");
CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
httpHeader->put("connection", "close"); httpHeader->put(HttpHeader::CONNECTION, "close");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("connection", "keep-alive"); httpHeader->put(HttpHeader::CONNECTION, "keep-alive");
CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->setVersion("HTTP/1.0"); httpHeader->setVersion("HTTP/1.0");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->put("connection", "close"); httpHeader->put(HttpHeader::CONNECTION, "close");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("connection", "keep-alive"); httpHeader->put(HttpHeader::CONNECTION, "keep-alive");
CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
@ -576,35 +582,35 @@ void HttpResponseTest::testSupportsPersistentConnection()
httpHeader->setVersion("HTTP/1.1"); httpHeader->setVersion("HTTP/1.1");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->put("connection", "close"); httpHeader->put(HttpHeader::CONNECTION, "close");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("connection", "keep-alive"); httpHeader->put(HttpHeader::CONNECTION, "keep-alive");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("proxy-connection", "keep-alive"); httpHeader->put(HttpHeader::PROXY_CONNECTION, "keep-alive");
CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
httpHeader->put("connection", "close"); httpHeader->put(HttpHeader::CONNECTION, "close");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("proxy-connection", "close"); httpHeader->put(HttpHeader::PROXY_CONNECTION, "close");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->setVersion("HTTP/1.0"); httpHeader->setVersion("HTTP/1.0");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->put("connection", "close"); httpHeader->put(HttpHeader::CONNECTION, "close");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("connection", "keep-alive"); httpHeader->put(HttpHeader::CONNECTION, "keep-alive");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->put("proxy-connection", "keep-alive"); httpHeader->put(HttpHeader::PROXY_CONNECTION, "keep-alive");
CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("proxy-connection", "keep-alive"); httpHeader->put(HttpHeader::PROXY_CONNECTION, "keep-alive");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
httpHeader->put("proxy-connection", "close"); httpHeader->put(HttpHeader::PROXY_CONNECTION, "close");
CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection()); CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
httpHeader->clearField(); httpHeader->clearField();
} }
@ -616,13 +622,16 @@ void HttpResponseTest::testGetMetalinKHttpEntries()
httpResponse.setHttpHeader(httpHeader); httpResponse.setHttpHeader(httpHeader);
SharedHandle<Option> option(new Option()); SharedHandle<Option> option(new Option());
httpHeader->put("link", "<http://uri1/>; rel=duplicate; pri=1; pref; geo=JP"); httpHeader->put(HttpHeader::LINK,
httpHeader->put("link", "<http://uri2/>; rel=duplicate"); "<http://uri1/>; rel=duplicate; pri=1; pref; geo=JP");
httpHeader->put("link", "<http://uri3/>;;;;;;;;rel=duplicate;;;;;pri=2;;;;;"); httpHeader->put(HttpHeader::LINK,
httpHeader->put("link", "<http://uri4/>;rel=duplicate;=pri=1;pref"); "<http://uri2/>; rel=duplicate");
httpHeader->put("link", "<http://describedby>; rel=describedby"); httpHeader->put(HttpHeader::LINK,
httpHeader->put("link", "<http://norel/>"); "<http://uri3/>;;;;;;;;rel=duplicate;;;;;pri=2;;;;;");
httpHeader->put("link", "<baduri>; rel=duplicate; pri=-1;"); httpHeader->put(HttpHeader::LINK, "<http://uri4/>;rel=duplicate;=pri=1;pref");
httpHeader->put(HttpHeader::LINK, "<http://describedby>; rel=describedby");
httpHeader->put(HttpHeader::LINK, "<http://norel/>");
httpHeader->put(HttpHeader::LINK, "<baduri>; rel=duplicate; pri=-1;");
std::vector<MetalinkHttpEntry> result; std::vector<MetalinkHttpEntry> result;
httpResponse.getMetalinKHttpEntries(result, option); httpResponse.getMetalinKHttpEntries(result, option);
CPPUNIT_ASSERT_EQUAL((size_t)5, result.size()); CPPUNIT_ASSERT_EQUAL((size_t)5, result.size());
@ -667,11 +676,13 @@ void HttpResponseTest::testGetDigest()
SharedHandle<Option> option(new Option()); SharedHandle<Option> option(new Option());
// Python binascii.hexlify(base64.b64decode(B64ED_HASH)) is handy to // Python binascii.hexlify(base64.b64decode(B64ED_HASH)) is handy to
// retrieve ascii hex hash string. // retrieve ascii hex hash string.
httpHeader->put("digest", "SHA-1=82AD8itGL/oYQ5BTPFANiYnp9oE="); httpHeader->put(HttpHeader::DIGEST, "SHA-1=82AD8itGL/oYQ5BTPFANiYnp9oE=");
httpHeader->put("digest", "NOT_SUPPORTED"); httpHeader->put(HttpHeader::DIGEST, "NOT_SUPPORTED");
httpHeader->put("digest", "SHA-224=rQdowoLHQJTMVZ3rF7vmYOIzUXlu7F+FcMbPnA=="); httpHeader->put(HttpHeader::DIGEST,
httpHeader->put("digest", "SHA-224=6Ik6LNZ1iPy6cbmlKO4NHfvxzaiurmHilMyhGA=="); "SHA-224=rQdowoLHQJTMVZ3rF7vmYOIzUXlu7F+FcMbPnA==");
httpHeader->put("digest", httpHeader->put(HttpHeader::DIGEST,
"SHA-224=6Ik6LNZ1iPy6cbmlKO4NHfvxzaiurmHilMyhGA==");
httpHeader->put(HttpHeader::DIGEST,
"SHA-256=+D8nGudz3G/kpkVKQeDrI3xD57v0UeQmzGCZOk03nsU=," "SHA-256=+D8nGudz3G/kpkVKQeDrI3xD57v0UeQmzGCZOk03nsU=,"
"MD5=LJDK2+9ClF8Nz/K5WZd/+A=="); "MD5=LJDK2+9ClF8Nz/K5WZd/+A==");
std::vector<Checksum> result; std::vector<Checksum> result;