瀏覽代碼

2008-04-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Added --header option. You can specify any number of additional 
HTTP headers
	like:
	aria2 --header="X-A: 300" --header="X-B: 900" http://host/file
	Unlike other commad-line option, you can use --header option 
multiple times.
	* src/HelpItemFactory.cc
	* src/HttpRequest.{cc, h}
	* src/HttpRequestCommand.cc
	* src/OptionHandlerFactory.cc
	* src/OptionHandlerImpl.h
	* src/option_processing.cc
	* src/prefs.h
	* src/usage_text.h
	* test/HttpRequestTest.cc (testUserHeaders)
Tatsuhiro Tsujikawa 17 年之前
父節點
當前提交
3eb74629cb

+ 16 - 0
ChangeLog

@@ -1,3 +1,19 @@
+2008-04-20  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Added --header option. You can specify any number of additional HTTP headers
+	like:
+	aria2 --header="X-A: 300" --header="X-B: 900" http://host/file
+	Unlike other commad-line option, you can use --header option multiple times.
+	* src/HelpItemFactory.cc
+	* src/HttpRequest.{cc, h}
+	* src/HttpRequestCommand.cc
+	* src/OptionHandlerFactory.cc
+	* src/OptionHandlerImpl.h
+	* src/option_processing.cc
+	* src/prefs.h
+	* src/usage_text.h
+	* test/HttpRequestTest.cc (testUserHeaders)
+
 2008-04-20  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Eliminates the time lag between sequential downloads and commands in

+ 5 - 0
src/HelpItemFactory.cc

@@ -432,6 +432,11 @@ TagContainerHandle HelpItemFactory::createHelpItems()
     item->addTag(TAG_ADVANCED);
     tc->addItem(item);
   }
+  {
+    HelpItemHandle item(new HelpItem(PREF_HEADER, TEXT_HEADER));
+    item->addTag(TAG_ADVANCED);
+    tc->addItem(item);
+  }
   {
     HelpItemHandle item(new HelpItem("help", TEXT_HELP, TAG_BASIC));
     char buf[64];

+ 14 - 0
src/HttpRequest.cc

@@ -44,6 +44,7 @@
 #include "prefs.h"
 #include "AuthConfigFactory.h"
 #include "AuthConfig.h"
+#include <numeric>
 
 namespace aria2 {
 
@@ -190,6 +191,12 @@ std::string HttpRequest::createRequest() const
   if(cookiesValue.size()) {
     requestLine += std::string("Cookie: ")+cookiesValue+"\r\n";
   }
+  // append additional headers given by user.
+  for(std::deque<std::string>::const_iterator i = _userHeaders.begin();
+      i != _userHeaders.end(); ++i) {
+    requestLine += (*i)+"\r\n";
+  }
+
   requestLine += "\r\n";
   return requestLine;
 }
@@ -218,6 +225,13 @@ std::string HttpRequest::getProxyAuthString() const {
     Base64::encode(AuthConfigFactorySingleton::instance()->createAuthConfigForHttpProxy(request)->getAuthText())+"\r\n";
 }
 
+void HttpRequest::setUserHeaders(const std::string& userHeadersString)
+{
+  std::deque<std::string> headers;
+  Util::slice(headers, userHeadersString, '\n', true);
+  _userHeaders = headers;
+}
+
 void HttpRequest::configure(const Option* option)
 {
   authEnabled = option->get(PREF_HTTP_AUTH_ENABLED) == V_TRUE;

+ 4 - 0
src/HttpRequest.h

@@ -66,6 +66,8 @@ private:
 
   std::string userAgent;
 
+  std::deque<std::string> _userHeaders;
+
   std::string getHostText(const std::string& host, uint16_t port) const;
 
   std::string getProxyAuthString() const;
@@ -164,6 +166,8 @@ public:
   {
     this->userAgent = userAgent;
   }
+
+  void setUserHeaders(const std::string& userHeaders);
 };
 
 typedef SharedHandle<HttpRequest> HttpRequestHandle;

+ 1 - 0
src/HttpRequestCommand.cc

@@ -84,6 +84,7 @@ bool HttpRequestCommand::executeInternal() {
     httpRequest->setUserAgent(e->option->get(PREF_USER_AGENT));
     httpRequest->setRequest(req);
     httpRequest->setEntityLength(_requestGroup->getTotalLength());
+    httpRequest->setUserHeaders(e->option->get(PREF_HEADER));
     httpRequest->configure(e->option);
     
     _httpConnection->sendRequest(httpRequest);

+ 1 - 1
src/OptionHandlerFactory.cc

@@ -126,7 +126,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
   handlers.push_back(SH(new NumberOptionHandler(PREF_STOP, 0, INT32_MAX)));
   handlers.push_back(SH(new ParameterOptionHandler(PREF_BT_MIN_CRYPTO_LEVEL, V_PLAIN, V_ARC4)));
   handlers.push_back(SH(new BooleanOptionHandler(PREF_BT_REQUIRE_CRYPTO)));
-  
+  handlers.push_back(SH(new CumulativeOptionHandler(PREF_HEADER, "\n")));
   return handlers;
 }
 

+ 19 - 0
src/OptionHandlerImpl.h

@@ -192,6 +192,25 @@ public:
   }
 };
 
+class CumulativeOptionHandler : public NameMatchOptionHandler {
+private:
+  std::string _delim;
+public:
+  CumulativeOptionHandler(const std::string& optName,
+			  const std::string& delim):
+    NameMatchOptionHandler(optName),
+    _delim(delim) {}
+
+  virtual ~CumulativeOptionHandler() {}
+
+  virtual void parseArg(Option* option, const std::string& optarg)
+  {
+    std::string value = option->get(_optName);
+    value += optarg+_delim;
+    option->put(_optName, value);
+  }
+};
+
 class ParameterOptionHandler : public NameMatchOptionHandler {
 private:
   std::deque<std::string> _validParamValues;

+ 4 - 0
src/option_processing.cc

@@ -204,6 +204,7 @@ Option* option_processing(int argc, char* const argv[])
       { PREF_NO_CONF, no_argument, &lopt, 212 },
       { PREF_CONF_PATH, required_argument, &lopt, 213 },
       { PREF_STOP, required_argument, &lopt, 214 },
+      { PREF_HEADER, required_argument, &lopt, 215 },
 #if defined ENABLE_BITTORRENT || ENABLE_METALINK
       { PREF_SHOW_FILES, no_argument, NULL, 'S' },
       { PREF_SELECT_FILE, required_argument, &lopt, 21 },
@@ -402,6 +403,9 @@ Option* option_processing(int argc, char* const argv[])
       case 214:
 	cmdstream << PREF_STOP << "=" << optarg << "\n";
 	break;
+      case 215:
+	cmdstream << PREF_HEADER << "=" << optarg << "\n";
+	break;
       }
       break;
     }

+ 2 - 0
src/prefs.h

@@ -163,6 +163,8 @@
 #define PREF_ENABLE_HTTP_PIPELINING "enable-http-pipelining"
 // value: 1*digit
 #define PREF_MAX_HTTP_PIPELINING "max-http-pipelining"
+// value: string
+#define PREF_HEADER "header"
 
 /** 
  * HTTP proxy related preferences

+ 6 - 0
src/usage_text.h

@@ -330,3 +330,9 @@ _(" --conf-path=PATH             Change the configuration file path to PATH.")
 #define TEXT_STOP \
 _(" --stop=SEC                   Stop application after SEC seconds has passed.\n" \
   "                              If 0 is given, this feature is disabled.")
+#define TEXT_HEADER \
+_(" --header=HEADER              Append HEADER to HTTP request header. You can use\n"\
+  "                              this option repeatedly to specify more than one\n"\
+  "                              header:\n"\
+  "                              aria2c --header=\"X-A: b78\" --header=\"X-B: 9J1\"\n"\
+  "                              http://host/file")

+ 26 - 0
test/HttpRequestTest.cc

@@ -22,6 +22,7 @@ class HttpRequestTest : public CppUnit::TestFixture {
   CPPUNIT_TEST(testCreateProxyRequest);
   CPPUNIT_TEST(testIsRangeSatisfied);
   CPPUNIT_TEST(testUserAgent);
+  CPPUNIT_TEST(testUserHeaders);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -36,6 +37,7 @@ public:
   void testCreateProxyRequest();
   void testIsRangeSatisfied();
   void testUserAgent();
+  void testUserHeaders();
 };
 
 
@@ -557,4 +559,28 @@ void HttpRequestTest::testUserAgent()
   CPPUNIT_ASSERT_EQUAL(expectedTextForProxy, httpRequest.createProxyRequest());
 }
 
+void HttpRequestTest::testUserHeaders()
+{
+  SharedHandle<Request> request(new Request());
+  request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
+
+  HttpRequest httpRequest;
+  httpRequest.setRequest(request);
+  httpRequest.setUserHeaders("X-ARIA2: v0.13\nX-ARIA2-DISTRIBUTE: enabled\n");
+
+  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"
+    "\r\n";
+
+  CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
+}
+
+
 } // namespace aria2