瀏覽代碼

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.
Tatsuhiro Tsujikawa 13 年之前
父節點
當前提交
dd7014a612

+ 66 - 43
src/HttpHeader.cc

@@ -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 =
-    table_.find(name);
+  std::multimap<int, std::string>::const_iterator itr = table_.find(hdKey);
   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::multimap<std::string, std::string>::const_iterator> itrpair =
-    table_.equal_range(name);
+  std::pair<std::multimap<int, std::string>::const_iterator,
+            std::multimap<int, std::string>::const_iterator> itrpair =
+    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::multimap<std::string, std::string>::const_iterator>
-HttpHeader::equalRange(const std::string& name) const
+std::pair<std::multimap<int, std::string>::const_iterator,
+          std::multimap<int, std::string>::const_iterator>
+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,
-                               const std::string& value)
+bool HttpHeader::fieldContains(int hdKey, const char* value)
 {
 {
-  std::pair<std::multimap<std::string, std::string>::const_iterator,
-            std::multimap<std::string, std::string>::const_iterator> range =
-    equalRange(name);
-  for(std::multimap<std::string, std::string>::const_iterator i = range.first;
+  std::pair<std::multimap<int, std::string>::const_iterator,
+            std::multimap<int, std::string>::const_iterator> range =
+    equalRange(hdKey);
+  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

+ 45 - 29
src/HttpHeader.h

@@ -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);
-  bool defined(const std::string& name) const;
-  const std::string& find(const std::string& name) const;
-  std::vector<std::string> findAll(const std::string& name) const;
-  std::pair<std::multimap<std::string, std::string>::const_iterator,
-            std::multimap<std::string, std::string>::const_iterator>
-  equalRange(const std::string& name) const;
-  int32_t findAsInt(const std::string& name) const;
-  int64_t findAsLLInt(const std::string& name) const;
+  void put(int hdKey, const std::string& value);
+  bool defined(int hdKey) const;
+  const std::string& find(int hdKey) const;
+  std::vector<std::string> findAll(int hdKey) const;
+  std::pair<std::multimap<int, std::string>::const_iterator,
+            std::multimap<int, std::string>::const_iterator>
+  equalRange(int hdKey) const;
+  int32_t findAsInt(int hdKey) 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);
-
-  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;
+  bool fieldContains(int hdKey, const char* value);
 
 
   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

+ 28 - 4
src/HttpHeaderProcessor.cc

@@ -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_);
-          result_->put(lastFieldName_, util::strip(buf_));
+          if(lastFieldHdKey_ != HttpHeader::MAX_INTERESTING_HEADER) {
+            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,7 +324,11 @@ 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;
-        i = getText(buf_, data, length, i);
+        if(lastFieldHdKey_ == HttpHeader::MAX_INTERESTING_HEADER) {
+          i = ignoreText(buf_, data, length, i);
+        } else {
+          i = getText(buf_, data, length, i);
+        }
       }
       }
       break;
       break;
     case FIELD_VALUE:
     case FIELD_VALUE:
@@ -318,7 +337,11 @@ bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length)
       } else if(c == '\n') {
       } else if(c == '\n') {
         state_ = PREV_FIELD_NAME;
         state_ = PREV_FIELD_NAME;
       } else {
       } else {
-        i = getText(buf_, data, length, i);
+        if(lastFieldHdKey_ == HttpHeader::MAX_INTERESTING_HEADER) {
+          i = ignoreText(buf_, data, length, i);
+        } else {
+          i = getText(buf_, data, length, i);
+        }
       }
       }
       break;
       break;
     case PREV_EOH:
     case PREV_EOH:
@@ -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();
 }
 }

+ 1 - 0
src/HttpHeaderProcessor.h

@@ -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_;
 };
 };

+ 6 - 7
src/HttpResponse.cc

@@ -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::multimap<std::string, std::string>::const_iterator> r =
+  std::pair<std::multimap<int, std::string>::const_iterator,
+            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::multimap<std::string, std::string>::const_iterator> p =
+  std::pair<std::multimap<int, std::string>::const_iterator,
+            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::multimap<std::string, std::string>::const_iterator> p =
+  std::pair<std::multimap<int, std::string>::const_iterator,
+            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;

+ 4 - 4
src/HttpServerBodyCommand.cc

@@ -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() &&
-             !header->find("access-control-request-method").empty() &&
-             !httpServer_->getAllowOrigin().empty()) {
+          if(!header->find(HttpHeader::ORIGIN).empty() &&
+             !header->find(HttpHeader::ACCESS_CONTROL_REQUEST_METHOD).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: ";

+ 6 - 5
src/HttpServerCommand.cc

@@ -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") &&
-         header->fieldContains("connection", "upgrade")) {
+      if(header->fieldContains(HttpHeader::UPGRADE, "websocket") &&
+         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()));

+ 2 - 4
src/LpdMessageReceiver.cc

@@ -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";
-    static const std::string A2_PORT = "port";
-    const std::string& infoHashString = header->find(A2_INFOHASH);
-    uint16_t port = header->findAsInt(A2_PORT);
+    const std::string& infoHashString = header->find(HttpHeader::INFOHASH);
+    uint16_t port = header->findAsInt(HttpHeader::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,

+ 5 - 0
src/util.cc

@@ -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

+ 3 - 0
src/util.h

@@ -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,

+ 19 - 25
test/HttpHeaderProcessorTest.cc

@@ -26,7 +26,7 @@ class HttpHeaderProcessorTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testGetHeaderString);
   CPPUNIT_TEST(testGetHeaderString);
   CPPUNIT_TEST(testGetHttpRequestHeader);
   CPPUNIT_TEST(testGetHttpRequestHeader);
   CPPUNIT_TEST_SUITE_END();
   CPPUNIT_TEST_SUITE_END();
-  
+
 public:
 public:
   void testParse1();
   void testParse1();
   void testParse2();
   void testParse2();
@@ -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"
-    "Duplicate: bar\r\n"
-    "No-value:\r\n"
+    "Authorization: foo\r\n"
+    "Authorization: bar\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"),
-                       h->find("host"));
-  CPPUNIT_ASSERT_EQUAL(std::string("close"),
-                       h->find("connection"));
+  CPPUNIT_ASSERT_EQUAL(std::string("close"), h->find(HttpHeader::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]);
-  CPPUNIT_ASSERT_EQUAL(std::string(""), h->find("no-value"));
-  CPPUNIT_ASSERT(h->defined("no-value"));
+                       h->findAll(HttpHeader::AUTHORIZATION)[1]);
+  CPPUNIT_ASSERT_EQUAL(std::string(""), h->find(HttpHeader::CONTENT_TYPE));
+  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"));
-  CPPUNIT_ASSERT(!header->defined("entity"));
+                       header->find(HttpHeader::CONTENT_TYPE));
+  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(!httpHeader->defined("entity"));
+  CPPUNIT_ASSERT_EQUAL(std::string("close"),
+                       httpHeader->find(HttpHeader::CONNECTION));
+  CPPUNIT_ASSERT(!httpHeader->defined(HttpHeader::CONTENT_ENCODING));
 }
 }
 
 
 } // namespace aria2
 } // namespace aria2

+ 33 - 33
test/HttpHeaderTest.cc

@@ -15,7 +15,7 @@ class HttpHeaderTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testClearField);
   CPPUNIT_TEST(testClearField);
   CPPUNIT_TEST(testFieldContains);
   CPPUNIT_TEST(testFieldContains);
   CPPUNIT_TEST_SUITE_END();
   CPPUNIT_TEST_SUITE_END();
-  
+
 public:
 public:
   void testGetRange();
   void testGetRange();
   void testFindAll();
   void testFindAll();
@@ -29,9 +29,9 @@ 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();
 
 
     CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775800LL, range->getStartByte());
     CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775800LL, range->getStartByte());
@@ -40,9 +40,9 @@ 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();
 
 
     CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775800LL, range->getStartByte());
     CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775800LL, range->getStartByte());
@@ -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("A", "101");
-  h.put("B", "200");
-  
-  std::vector<std::string> r(h.findAll("A"));
+  h.put(HttpHeader::LINK, "100");
+  h.put(HttpHeader::LINK, "101");
+  h.put(HttpHeader::CONNECTION, "200");
+
+  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");
-  
-  CPPUNIT_ASSERT_EQUAL(std::string("Bar"), h.find("Foo"));
+  h.put(HttpHeader::LINK, "Bar");
+
+  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("upgrade", "WebSocket");
-  h.put("sec-websocket-version", "13");
-  h.put("sec-websocket-version", "8, 7");
-  CPPUNIT_ASSERT(h.fieldContains("connection", "upgrade"));
-  CPPUNIT_ASSERT(h.fieldContains("connection", "keep-alive"));
-  CPPUNIT_ASSERT(!h.fieldContains("connection", "close"));
-  CPPUNIT_ASSERT(h.fieldContains("upgrade", "websocket"));
-  CPPUNIT_ASSERT(!h.fieldContains("upgrade", "spdy"));
-  CPPUNIT_ASSERT(h.fieldContains("sec-websocket-version", "13"));
-  CPPUNIT_ASSERT(h.fieldContains("sec-websocket-version", "8"));
-  CPPUNIT_ASSERT(!h.fieldContains("sec-websocket-version", "6"));
+  h.put(HttpHeader::CONNECTION, "Keep-Alive, Upgrade");
+  h.put(HttpHeader::UPGRADE, "WebSocket");
+  h.put(HttpHeader::SEC_WEBSOCKET_VERSION, "13");
+  h.put(HttpHeader::SEC_WEBSOCKET_VERSION, "8, 7");
+  CPPUNIT_ASSERT(h.fieldContains(HttpHeader::CONNECTION, "upgrade"));
+  CPPUNIT_ASSERT(h.fieldContains(HttpHeader::CONNECTION, "keep-alive"));
+  CPPUNIT_ASSERT(!h.fieldContains(HttpHeader::CONNECTION, "close"));
+  CPPUNIT_ASSERT(h.fieldContains(HttpHeader::UPGRADE, "websocket"));
+  CPPUNIT_ASSERT(!h.fieldContains(HttpHeader::UPGRADE, "spdy"));
+  CPPUNIT_ASSERT(h.fieldContains(HttpHeader::SEC_WEBSOCKET_VERSION, "13"));
+  CPPUNIT_ASSERT(h.fieldContains(HttpHeader::SEC_WEBSOCKET_VERSION, "8"));
+  CPPUNIT_ASSERT(!h.fieldContains(HttpHeader::SEC_WEBSOCKET_VERSION, "6"));
 }
 }
 
 
 } // namespace aria2
 } // namespace aria2

+ 76 - 65
test/HttpResponseTest.cc

@@ -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());
@@ -204,14 +205,14 @@ void HttpResponseTest::testGetRedirectURI_without_Location()
   httpResponse.setHttpHeader(httpHeader);
   httpResponse.setHttpHeader(httpHeader);
 
 
   CPPUNIT_ASSERT_EQUAL(std::string(""),
   CPPUNIT_ASSERT_EQUAL(std::string(""),
-                       httpResponse.getRedirectURI());  
+                       httpResponse.getRedirectURI());
 }
 }
 
 
 void HttpResponseTest::testGetRedirectURI_with_Location()
 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);
 
 
@@ -232,7 +234,7 @@ void HttpResponseTest::testIsRedirect()
 
 
   httpHeader->setStatusCode(301);
   httpHeader->setStatusCode(301);
 
 
-  CPPUNIT_ASSERT(httpResponse.isRedirect());  
+  CPPUNIT_ASSERT(httpResponse.isRedirect());
 }
 }
 
 
 void HttpResponseTest::testIsTransferEncodingSpecified()
 void HttpResponseTest::testIsTransferEncodingSpecified()
@@ -242,9 +244,9 @@ void HttpResponseTest::testIsTransferEncodingSpecified()
 
 
   httpResponse.setHttpHeader(httpHeader);
   httpResponse.setHttpHeader(httpHeader);
 
 
-  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());
 }
 }
@@ -256,9 +258,9 @@ void HttpResponseTest::testGetTransferEncoding()
 
 
   httpResponse.setHttpHeader(httpHeader);
   httpResponse.setHttpHeader(httpHeader);
 
 
-  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());
 }
 }
@@ -282,12 +284,12 @@ void HttpResponseTest::testIsContentEncodingSpecified()
 {
 {
   HttpResponse httpResponse;
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  
+
   httpResponse.setHttpHeader(httpHeader);
   httpResponse.setHttpHeader(httpHeader);
 
 
   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());
 }
 }
@@ -296,12 +298,12 @@ void HttpResponseTest::testGetContentEncoding()
 {
 {
   HttpResponse httpResponse;
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  
+
   httpResponse.setHttpHeader(httpHeader);
   httpResponse.setHttpHeader(httpHeader);
 
 
   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());
 }
 }
@@ -310,13 +312,13 @@ void HttpResponseTest::testGetContentEncodingStreamFilter()
 {
 {
   HttpResponse httpResponse;
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  
+
   httpResponse.setHttpHeader(httpHeader);
   httpResponse.setHttpHeader(httpHeader);
 
 
   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,14 +361,15 @@ 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) {
     CPPUNIT_FAIL("exception must not be thrown.");
     CPPUNIT_FAIL("exception must not be thrown.");
   }
   }
 }
 }
- 
+
 void HttpResponseTest::testValidateResponse_good_range()
 void HttpResponseTest::testValidateResponse_good_range()
 {
 {
   HttpResponse httpResponse;
   HttpResponse httpResponse;
@@ -384,8 +387,8 @@ 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();
   } catch(Exception& e) {
   } catch(Exception& e) {
@@ -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("transfer-encoding", "chunked");
+  httpHeader->put(HttpHeader::CONTENT_RANGE, "bytes 0-10485760/10485761");
+  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());
@@ -488,14 +491,14 @@ void HttpResponseTest::testProcessRedirect()
   request->setUri("http://localhost/archives/aria2-1.0.0.tar.bz2");
   request->setUri("http://localhost/archives/aria2-1.0.0.tar.bz2");
   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,57 +560,57 @@ 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();
 
 
   // test proxy connection
   // test proxy connection
   SharedHandle<Request> proxyRequest(new Request());
   SharedHandle<Request> proxyRequest(new Request());
   httpRequest->setProxyRequest(proxyRequest);
   httpRequest->setProxyRequest(proxyRequest);
-  
+
   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("link", "<http://uri2/>; rel=duplicate");
-  httpHeader->put("link", "<http://uri3/>;;;;;;;;rel=duplicate;;;;;pri=2;;;;;");
-  httpHeader->put("link", "<http://uri4/>;rel=duplicate;=pri=1;pref");
-  httpHeader->put("link", "<http://describedby>; rel=describedby");
-  httpHeader->put("link", "<http://norel/>");
-  httpHeader->put("link", "<baduri>; rel=duplicate; pri=-1;");
+  httpHeader->put(HttpHeader::LINK,
+                  "<http://uri1/>; rel=duplicate; pri=1; pref; geo=JP");
+  httpHeader->put(HttpHeader::LINK,
+                  "<http://uri2/>; rel=duplicate");
+  httpHeader->put(HttpHeader::LINK,
+                  "<http://uri3/>;;;;;;;;rel=duplicate;;;;;pri=2;;;;;");
+  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("digest", "NOT_SUPPORTED");
-  httpHeader->put("digest", "SHA-224=rQdowoLHQJTMVZ3rF7vmYOIzUXlu7F+FcMbPnA==");
-  httpHeader->put("digest", "SHA-224=6Ik6LNZ1iPy6cbmlKO4NHfvxzaiurmHilMyhGA==");
-  httpHeader->put("digest",
+  httpHeader->put(HttpHeader::DIGEST, "SHA-1=82AD8itGL/oYQ5BTPFANiYnp9oE=");
+  httpHeader->put(HttpHeader::DIGEST, "NOT_SUPPORTED");
+  httpHeader->put(HttpHeader::DIGEST,
+                  "SHA-224=rQdowoLHQJTMVZ3rF7vmYOIzUXlu7F+FcMbPnA==");
+  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;