Pārlūkot izejas kodu

2010-02-20 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	User-defined custom request headers specified by --header option
	now override builtin headers if they have same name.
	* src/HttpRequest.cc
	* src/HttpRequest.h
	* test/HttpRequestTest.cc
Tatsuhiro Tsujikawa 15 gadi atpakaļ
vecāks
revīzija
aee471e52c
4 mainītis faili ar 73 papildinājumiem un 45 dzēšanām
  1. 8 0
      ChangeLog
  2. 60 41
      src/HttpRequest.cc
  3. 3 2
      src/HttpRequest.h
  4. 2 2
      test/HttpRequestTest.cc

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+2010-02-20  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	User-defined custom request headers specified by --header option
+	now override builtin headers if they have same name.
+	* src/HttpRequest.cc
+	* src/HttpRequest.h
+	* test/HttpRequestTest.cc
+
 2010-02-19  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Rewirtten util::isNumber()

+ 60 - 41
src/HttpRequest.cc

@@ -49,6 +49,7 @@
 #include "AuthConfig.h"
 #include "a2functional.h"
 #include "TimeA2.h"
+#include "array_fun.h"
 
 namespace aria2 {
 
@@ -155,59 +156,63 @@ std::string HttpRequest::createRequest()
     requestLine += getQuery();
   }
   requestLine += " HTTP/1.1\r\n";
-  strappend(requestLine, "User-Agent: ", userAgent, "\r\n");
-  
-  requestLine += "Accept: */*"; /* */
-  for(std::deque<std::string>::const_iterator i = _acceptTypes.begin();
-      i != _acceptTypes.end(); ++i) {
-    strappend(requestLine, ",", (*i));
-  }
-  requestLine += "\r\n";
 
+  std::vector<std::pair<std::string, std::string> > builtinHds;
+  builtinHds.reserve(20);
+  builtinHds.push_back(std::make_pair("User-Agent:", userAgent));
+  std::string acceptTypes = "*/*";
+  for(std::deque<std::string>::const_iterator i = _acceptTypes.begin(),
+        end = _acceptTypes.end(); i != end; ++i) {
+    strappend(acceptTypes, ",", (*i));
+  }
+  builtinHds.push_back(std::make_pair("Accept:", acceptTypes));
   if(_contentEncodingEnabled) {
     std::string acceptableEncodings;
 #ifdef HAVE_LIBZ
     acceptableEncodings += "deflate, gzip";
 #endif // HAVE_LIBZ
     if(!acceptableEncodings.empty()) {
-      strappend(requestLine, "Accept-Encoding: ", acceptableEncodings, "\r\n");
+      builtinHds.push_back
+        (std::make_pair("Accept-Encoding:", acceptableEncodings));
     }
   }
-
-  strappend(requestLine, "Host: ", getHostText(getURIHost(), getPort()), "\r\n");
+  builtinHds.push_back
+    (std::make_pair("Host:", getHostText(getURIHost(), getPort())));
   if(_noCache) {
-    requestLine += "Pragma: no-cache\r\n";
-    requestLine += "Cache-Control: no-cache\r\n";
+    builtinHds.push_back(std::make_pair("Pragma:", "no-cache"));
+    builtinHds.push_back(std::make_pair("Cache-Control:", "no-cache"));
   }
   if(!request->isKeepAliveEnabled() && !request->isPipeliningEnabled()) {
-    requestLine += "Connection: close\r\n";
+    builtinHds.push_back(std::make_pair("Connection:", "close"));
   }
   if(!segment.isNull() && segment->getLength() > 0 && 
      (request->isPipeliningEnabled() || getStartByte() > 0)) {
-    requestLine += "Range: bytes=";
-    requestLine += util::itos(getStartByte());
-    requestLine += "-";
+    std::string rangeHeader = "bytes=";
+    rangeHeader += util::itos(getStartByte());
+    rangeHeader += "-";
     if(request->isPipeliningEnabled()) {
-      requestLine += util::itos(getEndByte());
+      rangeHeader += util::itos(getEndByte());
     }
-    requestLine += "\r\n";
+    builtinHds.push_back(std::make_pair("Range:", rangeHeader));
   }
   if(!_proxyRequest.isNull()) {
     if(request->isKeepAliveEnabled() || request->isPipeliningEnabled()) {
-      requestLine += "Proxy-Connection: Keep-Alive\r\n";
+      builtinHds.push_back(std::make_pair("Proxy-Connection:", "Keep-Alive"));
     } else {
-      requestLine += "Proxy-Connection: close\r\n";
+      builtinHds.push_back(std::make_pair("Proxy-Connection:", "close"));
     }
   }
   if(!_proxyRequest.isNull() && !_proxyRequest->getUsername().empty()) {
-    requestLine += getProxyAuthString();
+    builtinHds.push_back(getProxyAuthString());
   }
   if(!_authConfig.isNull()) {
-    strappend(requestLine, "Authorization: Basic ",
-              Base64::encode(_authConfig->getAuthText()), "\r\n");
+    builtinHds.push_back
+      (std::make_pair("Authorization:",
+                      strconcat("Basic ",
+                                Base64::encode(_authConfig->getAuthText()))));
   }
   if(getPreviousURI().size()) {
-    strappend(requestLine, "Referer: ", getPreviousURI(), "\r\n");
+    builtinHds.push_back(std::make_pair("Referer:", getPreviousURI()));
   }
   if(!_cookieStorage.isNull()) {
     std::string cookiesValue;
@@ -217,21 +222,33 @@ std::string HttpRequest::createRequest()
                                    Time().getTime(),
                                    getProtocol() == Request::PROTO_HTTPS ?
                                    true : false);
-    for(std::deque<Cookie>::const_iterator itr = cookies.begin();
-        itr != cookies.end(); ++itr) {
+    for(std::deque<Cookie>::const_iterator itr = cookies.begin(),
+          end = cookies.end(); itr != end; ++itr) {
       strappend(cookiesValue, (*itr).toString(), ";");
     }
     if(!cookiesValue.empty()) {
-      strappend(requestLine, "Cookie: ", cookiesValue, "\r\n");
+      builtinHds.push_back(std::make_pair("Cookie:", cookiesValue));
+    }
+  }
+  for(std::vector<std::pair<std::string, std::string> >::iterator i =
+        builtinHds.begin(); i != builtinHds.end(); ++i) {
+    std::vector<std::string>::const_iterator j = _headers.begin();
+    std::vector<std::string>::const_iterator jend = _headers.end();
+    for(; j != jend; ++j) {
+      if(util::startsWith(*j, (*i).first)) {
+        break;
+      }
+    }
+    if(j == jend) {
+      strappend(requestLine, (*i).first, " ", (*i).second, A2STR::CRLF);
     }
   }
   // append additional headers given by user.
-  for(std::deque<std::string>::const_iterator i = _headers.begin();
-      i != _headers.end(); ++i) {
-    strappend(requestLine, (*i), "\r\n");
+  for(std::vector<std::string>::const_iterator i = _headers.begin(),
+        end = _headers.end(); i != end; ++i) {
+    strappend(requestLine, (*i), A2STR::CRLF);
   }
-
-  requestLine += "\r\n";
+  requestLine += A2STR::CRLF;
   return requestLine;
 }
 
@@ -252,19 +269,21 @@ std::string HttpRequest::createProxyRequest() const
   //     requestLine += "Proxy-Connection: close\r\n";
   //   }
   if(!_proxyRequest->getUsername().empty()) {
-    requestLine += getProxyAuthString();
+    std::pair<std::string, std::string> auth = getProxyAuthString();
+    strappend(requestLine, auth.first, " ", auth.second, A2STR::CRLF);
   }
-  requestLine += "\r\n";
+  requestLine += A2STR::CRLF;
   return requestLine;
 }
 
-std::string HttpRequest::getProxyAuthString() const
+std::pair<std::string, std::string> HttpRequest::getProxyAuthString() const
 {
-  return strconcat("Proxy-Authorization: Basic ",
-                   Base64::encode(strconcat(_proxyRequest->getUsername(),
-                                            ":",
-                                            _proxyRequest->getPassword())),
-                   "\r\n");
+  return std::make_pair
+    ("Proxy-Authorization:",
+     strconcat("Basic ",
+               Base64::encode(strconcat(_proxyRequest->getUsername(),
+                                        ":",
+                                        _proxyRequest->getPassword()))));
 }
 
 void HttpRequest::enableContentEncoding()

+ 3 - 2
src/HttpRequest.h

@@ -40,6 +40,7 @@
 #include <cassert>
 #include <string>
 #include <deque>
+#include <vector>
 
 #include "SharedHandle.h"
 #include "Request.h"
@@ -69,7 +70,7 @@ private:
 
   std::string userAgent;
 
-  std::deque<std::string> _headers;
+  std::vector<std::string> _headers;
 
   std::deque<std::string> _acceptTypes;
 
@@ -85,7 +86,7 @@ private:
 
   bool _noCache;
 
-  std::string getProxyAuthString() const;
+  std::pair<std::string, std::string> getProxyAuthString() const;
 public:
   HttpRequest();
 

+ 2 - 2
test/HttpRequestTest.cc

@@ -663,16 +663,16 @@ void HttpRequestTest::testAddHeader()
   httpRequest.setRequest(request);
   httpRequest.setAuthConfigFactory(_authConfigFactory, _option.get());
   httpRequest.addHeader("X-ARIA2: v0.13\nX-ARIA2-DISTRIBUTE: enabled\n");
-
+  httpRequest.addHeader("Accept: text/html");
   std::string expectedText = "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n"
     "User-Agent: aria2\r\n"
-    "Accept: */*\r\n"
     "Host: localhost\r\n"
     "Pragma: no-cache\r\n"
     "Cache-Control: no-cache\r\n"
     "Connection: close\r\n"
     "X-ARIA2: v0.13\r\n"
     "X-ARIA2-DISTRIBUTE: enabled\r\n"
+    "Accept: text/html\r\n"
     "\r\n";
 
   CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());