Przeglądaj źródła

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

	Now HTTP status and version are a member variable of HttpHeader.
	HTTP status is processed as a string, not integer.
	* src/AbstractProxyResponseCommand.cc
	* src/HttpConnection.cc
	* src/HttpHeader.cc
	* src/HttpHeader.h
	* src/HttpHeaderProcessor.cc
	* src/HttpHeaderProcessor.h
	* src/HttpResponse.cc
	* src/HttpResponse.h
	* test/HttpHeaderProcessorTest.cc
	* test/HttpResponseTest.cc
Tatsuhiro Tsujikawa 17 lat temu
rodzic
commit
e1fa62e6c7

+ 15 - 0
ChangeLog

@@ -1,3 +1,18 @@
+2008-04-21  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Now HTTP status and version are a member variable of HttpHeader.
+	HTTP status is processed as a string, not integer.
+	* src/AbstractProxyResponseCommand.cc
+	* src/HttpConnection.cc
+	* src/HttpHeader.cc
+	* src/HttpHeader.h
+	* src/HttpHeaderProcessor.cc
+	* src/HttpHeaderProcessor.h
+	* src/HttpResponse.cc
+	* src/HttpResponse.h
+	* test/HttpHeaderProcessorTest.cc
+	* test/HttpResponseTest.cc
+
 2008-04-20  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Added --header option. You can specify any number of additional HTTP headers

+ 1 - 1
src/AbstractProxyResponseCommand.cc

@@ -65,7 +65,7 @@ bool AbstractProxyResponseCommand::executeInternal() {
     e->commands.push_back(this);
     return false;
   }
-  if(httpResponse->getStatus() != 200) {
+  if(httpResponse->getResponseStatus() != "200") {
     throw new DlRetryEx(EX_PROXY_CONNECTION_FAILED);
   }
   e->commands.push_back(getNextCommand());

+ 3 - 4
src/HttpConnection.cc

@@ -134,15 +134,14 @@ HttpResponseHandle HttpConnection::receiveResponse()
   // OK, we got all headers.
   logger->info(MSG_RECEIVE_RESPONSE, cuid, proc->getHeaderString().c_str());
 
-  std::pair<std::string, HttpHeaderHandle> httpStatusHeader = proc->getHttpStatusHeader();
-  if(Util::toLower(httpStatusHeader.second->getFirst("Connection")).find("close") != std::string::npos) {
+  SharedHandle<HttpHeader> httpHeader = proc->getHttpResponseHeader();
+  if(Util::toLower(httpHeader->getFirst("Connection")).find("close") != std::string::npos) {
     entry->getHttpRequest()->getRequest()->setKeepAlive(false);
   }
 
   HttpResponseHandle httpResponse(new HttpResponse());
   httpResponse->setCuid(cuid);
-  httpResponse->setStatus(Util::parseInt(httpStatusHeader.first));
-  httpResponse->setHttpHeader(httpStatusHeader.second);
+  httpResponse->setHttpHeader(httpHeader);
   httpResponse->setHttpRequest(entry->getHttpRequest());
 
   outstandingHttpRequests.pop_front();

+ 35 - 0
src/HttpHeader.cc

@@ -35,6 +35,7 @@
 #include "HttpHeader.h"
 #include "Range.h"
 #include "Util.h"
+#include <istream>
 
 namespace aria2 {
 
@@ -120,4 +121,38 @@ RangeHandle HttpHeader::getRange() const
   return SharedHandle<Range>(new Range(startByte, endByte, entityLength));
 }
 
+const std::string& HttpHeader::getResponseStatus() const
+{
+  return _responseStatus;
+}
+
+void HttpHeader::setResponseStatus(const std::string& responseStatus)
+{
+  _responseStatus = responseStatus;
+}
+
+const std::string& HttpHeader::getVersion() const
+{
+  return _version;
+}
+
+void HttpHeader::setVersion(const std::string& version)
+{
+  _version = version;
+}
+
+void HttpHeader::fill(std::istream& in)
+{
+  std::string line;
+  while(std::getline(in, line)) {
+    line = Util::trim(line);
+    if(line.empty()) {
+      break;
+    }
+    std::pair<std::string, std::string> hp;
+    Util::split(hp, line, ':');
+    put(hp.first, hp.second);
+  }
+}
+
 } // namespace aria2

+ 18 - 0
src/HttpHeader.h

@@ -40,6 +40,7 @@
 #include <map>
 #include <deque>
 #include <string>
+#include <iosfwd>
 
 namespace aria2 {
 
@@ -48,6 +49,13 @@ class Range;
 class HttpHeader {
 private:
   std::multimap<std::string, std::string> table;
+
+  // for HTTP response header only
+  // response status, e.g. "200"
+  std::string _responseStatus;
+
+  // HTTP version, e.g. HTTP/1.1
+  std::string _version;
 public:
   HttpHeader() {}
   ~HttpHeader() {}
@@ -60,6 +68,16 @@ public:
   uint64_t getFirstAsULLInt(const std::string& name) const;
 
   SharedHandle<Range> getRange() const;
+
+  const std::string& getResponseStatus() const;
+
+  void setResponseStatus(const std::string& responseStatus);
+
+  const std::string& getVersion() const;
+
+  void setVersion(const std::string& version);
+
+  void fill(std::istream& in);
 };
 
 typedef SharedHandle<HttpHeader> HttpHeaderHandle;

+ 6 - 14
src/HttpHeaderProcessor.cc

@@ -77,7 +77,7 @@ bool HttpHeaderProcessor::eoh() const
 
 size_t HttpHeaderProcessor::getPutBackDataLength() const
 {
-  std::string str = strm.str();
+  const std::string& str = strm.str();
   std::string::size_type delimpos = std::string::npos;
   if((delimpos = str.find("\r\n\r\n")) != std::string::npos) {
     return str.size()-(delimpos+4);
@@ -93,7 +93,7 @@ void HttpHeaderProcessor::clear()
   strm.str("");
 }
 
-std::pair<std::string, HttpHeaderHandle> HttpHeaderProcessor::getHttpStatusHeader()
+SharedHandle<HttpHeader> HttpHeaderProcessor::getHttpResponseHeader()
 {
   strm.seekg(0, std::ios::beg);
   std::string line;
@@ -102,19 +102,11 @@ std::pair<std::string, HttpHeaderHandle> HttpHeaderProcessor::getHttpStatusHeade
   if(line.size() <= 12) {
     throw new DlRetryEx(EX_NO_STATUS_HEADER);
   }
-  std::string status = line.substr(9, 3);
   HttpHeaderHandle httpHeader(new HttpHeader());
-  while(getline(strm, line)) {
-    line = Util::trim(line);
-    if(line.empty()) {
-      break;
-    }
-    std::pair<std::string, std::string> hp;
-    Util::split(hp, line, ':');
-    httpHeader->put(hp.first, hp.second);
-  }
-  
-  return std::pair<std::string, HttpHeaderHandle>(status, httpHeader);
+  httpHeader->setResponseStatus(line.substr(9, 3));
+  httpHeader->setVersion(line.substr(0, 8));
+  httpHeader->fill(strm);
+  return httpHeader;
 }
 
 std::string HttpHeaderProcessor::getHeaderString() const

+ 5 - 1
src/HttpHeaderProcessor.h

@@ -70,7 +70,11 @@ public:
    */
   size_t getPutBackDataLength() const;
 
-  std::pair<std::string, SharedHandle<HttpHeader> > getHttpStatusHeader();
+  /**
+   * Processes the recieved header as a http response header and returns
+   * HttpHeader object.
+   */
+   SharedHandle<HttpHeader> getHttpResponseHeader();
 
   std::string getHeaderString() const;
 

+ 15 - 9
src/HttpResponse.cc

@@ -50,7 +50,6 @@
 namespace aria2 {
 
 HttpResponse::HttpResponse():cuid(0),
-			     status(0),
 			     logger(LogFactory::getInstance())
 {}
 
@@ -58,19 +57,19 @@ HttpResponse::~HttpResponse() {}
 
 void HttpResponse::validateResponse() const
 {
-  if(status == 401) {
+  const std::string& status = getResponseStatus();
+  if(status == "401") {
     throw new DlAbortEx(EX_AUTH_FAILED);
   }
-  if(status == 404) {
+  if(status == "404") {
     throw new DlAbortEx(MSG_RESOURCE_NOT_FOUND);
   }
-  if(status >= 400) {
-    throw new DlAbortEx(EX_BAD_STATUS, status);
+  if(status >= "400") {
+    throw new DlAbortEx(EX_BAD_STATUS, Util::parseUInt(status));
   }
-  if(status >= 300) {
+  if(status >= "300") {
     if(!httpHeader->defined("Location")) {
-      throw new DlAbortEx(EX_LOCATION_HEADER_REQUIRED,
-			  status);
+      throw new DlAbortEx(EX_LOCATION_HEADER_REQUIRED, Util::parseUInt(status));
     }
   } else {
     if(!httpHeader->defined("Transfer-Encoding")) {
@@ -114,7 +113,8 @@ void HttpResponse::retrieveCookie()
 
 bool HttpResponse::isRedirect() const
 {
-  return 300 <= status && status < 400 && httpHeader->defined("Location");
+  const std::string& status = getResponseStatus();
+  return "300" <= status && status < "400" && httpHeader->defined("Location");
 }
 
 void HttpResponse::processRedirect()
@@ -195,4 +195,10 @@ SharedHandle<HttpRequest> HttpResponse::getHttpRequest() const
   return httpRequest;
 }
 
+// TODO return std::string
+const std::string& HttpResponse::getResponseStatus() const
+{
+  return httpHeader->getResponseStatus();
+}
+
 } // namespace aria2

+ 1 - 10
src/HttpResponse.h

@@ -49,7 +49,6 @@ class Logger;
 class HttpResponse {
 private:
   int32_t cuid;
-  unsigned int status;
   SharedHandle<HttpRequest> httpRequest;
   SharedHandle<HttpHeader> httpHeader;
   const Logger* logger;
@@ -95,15 +94,7 @@ public:
 
   SharedHandle<HttpHeader> getHttpHeader() const;
 
-  void setStatus(unsigned int status)
-  {
-    this->status = status;
-  }
-
-  unsigned int getStatus() const
-  {
-    return status;
-  }
+  const std::string& getResponseStatus() const;
 
   void setHttpRequest(const SharedHandle<HttpRequest>& httpRequest);
 

+ 26 - 24
test/HttpHeaderProcessorTest.cc

@@ -14,10 +14,10 @@ class HttpHeaderProcessorTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testUpdate2);
   CPPUNIT_TEST(testGetPutBackDataLength);
   CPPUNIT_TEST(testGetPutBackDataLength_nullChar);
-  CPPUNIT_TEST(testGetHttpStatusHeader);
-  CPPUNIT_TEST(testGetHttpStatusHeader_empty);
-  CPPUNIT_TEST(testGetHttpStatusHeader_statusOnly);
-  CPPUNIT_TEST(testGetHttpStatusHeader_insufficientStatusLength);
+  CPPUNIT_TEST(testGetHttpResponseHeader);
+  CPPUNIT_TEST(testGetHttpResponseHeader_empty);
+  CPPUNIT_TEST(testGetHttpResponseHeader_statusOnly);
+  CPPUNIT_TEST(testGetHttpResponseHeader_insufficientStatusLength);
   CPPUNIT_TEST(testBeyondLimit);
   CPPUNIT_TEST(testGetHeaderString);
   CPPUNIT_TEST_SUITE_END();
@@ -27,12 +27,13 @@ public:
   void testUpdate2();
   void testGetPutBackDataLength();
   void testGetPutBackDataLength_nullChar();
-  void testGetHttpStatusHeader();
-  void testGetHttpStatusHeader_empty();
-  void testGetHttpStatusHeader_statusOnly();
-  void testGetHttpStatusHeader_insufficientStatusLength();
+  void testGetHttpResponseHeader();
+  void testGetHttpResponseHeader_empty();
+  void testGetHttpResponseHeader_statusOnly();
+  void testGetHttpResponseHeader_insufficientStatusLength();
   void testBeyondLimit();
   void testGetHeaderString();
+  void testGetHttpRequestHeader();
 };
 
 
@@ -88,7 +89,7 @@ void HttpHeaderProcessorTest::testGetPutBackDataLength_nullChar()
   CPPUNIT_ASSERT_EQUAL((size_t)9, proc.getPutBackDataLength());
 }
 
-void HttpHeaderProcessorTest::testGetHttpStatusHeader()
+void HttpHeaderProcessorTest::testGetHttpResponseHeader()
 {
   HttpHeaderProcessor proc;
   std::string hd = "HTTP/1.1 200 OK\r\n"
@@ -104,22 +105,24 @@ void HttpHeaderProcessorTest::testGetHttpStatusHeader()
 
   proc.update(hd);
 
-  std::pair<std::string, SharedHandle<HttpHeader> > statusHeader = proc.getHttpStatusHeader();
-  std::string status = statusHeader.first;
-  SharedHandle<HttpHeader> header = statusHeader.second;
-  CPPUNIT_ASSERT_EQUAL(std::string("200"), status);
-  CPPUNIT_ASSERT_EQUAL(std::string("Mon, 25 Jun 2007 16:04:59 GMT"), header->getFirst("Date"));
-  CPPUNIT_ASSERT_EQUAL(std::string("Apache/2.2.3 (Debian)"), header->getFirst("Server"));
+  SharedHandle<HttpHeader> header = proc.getHttpResponseHeader();
+  CPPUNIT_ASSERT_EQUAL(std::string("200"), header->getResponseStatus());
+  CPPUNIT_ASSERT_EQUAL(std::string("HTTP/1.1"), header->getVersion());
+  CPPUNIT_ASSERT_EQUAL(std::string("Mon, 25 Jun 2007 16:04:59 GMT"),
+		       header->getFirst("Date"));
+  CPPUNIT_ASSERT_EQUAL(std::string("Apache/2.2.3 (Debian)"),
+		       header->getFirst("Server"));
   CPPUNIT_ASSERT_EQUAL(9187ULL, header->getFirstAsULLInt("Content-Length"));
-  CPPUNIT_ASSERT_EQUAL(std::string("text/html; charset=UTF-8"), header->getFirst("Content-Type"));
+  CPPUNIT_ASSERT_EQUAL(std::string("text/html; charset=UTF-8"),
+		       header->getFirst("Content-Type"));
 }
 
-void HttpHeaderProcessorTest::testGetHttpStatusHeader_empty()
+void HttpHeaderProcessorTest::testGetHttpResponseHeader_empty()
 {
   HttpHeaderProcessor proc;
 
   try {
-    std::pair<std::string, SharedHandle<HttpHeader> > statusHeader = proc.getHttpStatusHeader();
+    proc.getHttpResponseHeader();
     CPPUNIT_FAIL("Exception must be thrown.");
   } catch(DlRetryEx* ex) {
     std::cout << ex->getMsg() << std::endl;
@@ -128,25 +131,24 @@ void HttpHeaderProcessorTest::testGetHttpStatusHeader_empty()
   
 }
 
-void HttpHeaderProcessorTest::testGetHttpStatusHeader_statusOnly()
+void HttpHeaderProcessorTest::testGetHttpResponseHeader_statusOnly()
 {
   HttpHeaderProcessor proc;
 
   std::string hd = "HTTP/1.1 200\r\n\r\n";
   proc.update(hd);
-  std::pair<std::string, SharedHandle<HttpHeader> > statusHeader = proc.getHttpStatusHeader();
-  CPPUNIT_ASSERT_EQUAL(std::string("200"), statusHeader.first);
-  CPPUNIT_ASSERT(!statusHeader.second.isNull());
+  SharedHandle<HttpHeader> header = proc.getHttpResponseHeader();
+  CPPUNIT_ASSERT_EQUAL(std::string("200"), header->getResponseStatus());
 }
 
-void HttpHeaderProcessorTest::testGetHttpStatusHeader_insufficientStatusLength()
+void HttpHeaderProcessorTest::testGetHttpResponseHeader_insufficientStatusLength()
 {
   HttpHeaderProcessor proc;
 
   std::string hd = "HTTP/1.1 20\r\n\r\n";
   proc.update(hd);  
   try {
-    std::pair<std::string, SharedHandle<HttpHeader> > statusHeader = proc.getHttpStatusHeader();
+    proc.getHttpResponseHeader();
     CPPUNIT_FAIL("Exception must be thrown.");
   } catch(DlRetryEx* ex) {
     std::cout << ex->getMsg() << std::endl;

+ 11 - 10
test/HttpResponseTest.cc

@@ -184,14 +184,14 @@ void HttpResponseTest::testIsRedirect()
 {
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
+  httpHeader->setResponseStatus("200");
   httpHeader->put("Location", "http://localhost/download/aria2-1.0.0.tar.bz2");
 
   httpResponse.setHttpHeader(httpHeader);
-  httpResponse.setStatus(200);
 
   CPPUNIT_ASSERT(!httpResponse.isRedirect());
 
-  httpResponse.setStatus(304);
+  httpHeader->setResponseStatus("304");
 
   CPPUNIT_ASSERT(httpResponse.isRedirect());  
 }
@@ -242,7 +242,9 @@ void HttpResponseTest::testValidateResponse()
 {
   HttpResponse httpResponse;
 
-  httpResponse.setStatus(401);
+  SharedHandle<HttpHeader> httpHeader(new HttpHeader());
+  httpHeader->setResponseStatus("401");
+  httpResponse.setHttpHeader(httpHeader);
 
   try {
     httpResponse.validateResponse();
@@ -251,7 +253,7 @@ void HttpResponseTest::testValidateResponse()
     delete e;
   }
 
-  httpResponse.setStatus(505);
+  httpHeader->setResponseStatus("505");
 
   try {
     httpResponse.validateResponse();
@@ -260,9 +262,8 @@ void HttpResponseTest::testValidateResponse()
     delete e;
   }
 
-  httpResponse.setStatus(304);
-  SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  httpResponse.setHttpHeader(httpHeader);
+  httpHeader->setResponseStatus("304");
+
   try {
     httpResponse.validateResponse();
     CPPUNIT_FAIL("exception must be thrown.");
@@ -295,7 +296,7 @@ void HttpResponseTest::testValidateResponse_good_range()
   request->setKeepAlive(false);
   httpRequest->setRequest(request);
   httpResponse.setHttpRequest(httpRequest);
-  httpResponse.setStatus(206);
+  httpHeader->setResponseStatus("206");
   httpHeader->put("Content-Range", "bytes 1048576-10485760/10485761");
   
   try {
@@ -322,7 +323,7 @@ void HttpResponseTest::testValidateResponse_bad_range()
   request->setKeepAlive(false);
   httpRequest->setRequest(request);
   httpResponse.setHttpRequest(httpRequest);
-  httpResponse.setStatus(206);
+  httpHeader->setResponseStatus("206");
   httpHeader->put("Content-Range", "bytes 0-10485760/10485761");
 
   try {
@@ -348,7 +349,7 @@ void HttpResponseTest::testValidateResponse_chunked()
   request->setKeepAlive(false);
   httpRequest->setRequest(request);
   httpResponse.setHttpRequest(httpRequest);
-  httpResponse.setStatus(206);
+  httpHeader->setResponseStatus("206");
   httpHeader->put("Content-Range", "bytes 0-10485760/10485761");
   httpHeader->put("Transfer-Encoding", "chunked");