mirror of https://github.com/aria2/aria2
				
				
				
			2008-05-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Reimplemented transparent metalink using Accept request header. * src/HttpRequest.cc * src/HttpRequest.h * src/HttpRequestCommand.cc * src/Metalink2RequestGroup.cc * src/RequestGroup.cc * src/RequestGroup.h * test/HttpRequestTest.ccpull/1/head
							parent
							
								
									b892b54e4b
								
							
						
					
					
						commit
						f596de9eec
					
				
							
								
								
									
										11
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										11
									
								
								ChangeLog
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,14 @@
 | 
			
		|||
2008-05-05  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	Reimplemented transparent metalink using Accept request header.
 | 
			
		||||
	* src/HttpRequest.cc
 | 
			
		||||
	* src/HttpRequest.h
 | 
			
		||||
	* src/HttpRequestCommand.cc
 | 
			
		||||
	* src/Metalink2RequestGroup.cc
 | 
			
		||||
	* src/RequestGroup.cc
 | 
			
		||||
	* src/RequestGroup.h
 | 
			
		||||
	* test/HttpRequestTest.cc
 | 
			
		||||
	
 | 
			
		||||
2008-04-27  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 | 
			
		||||
 | 
			
		||||
	Bump up version number to 0.13.2a
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,7 @@
 | 
			
		|||
#include "prefs.h"
 | 
			
		||||
#include "AuthConfigFactory.h"
 | 
			
		||||
#include "AuthConfig.h"
 | 
			
		||||
#include "a2functional.h"
 | 
			
		||||
#include <numeric>
 | 
			
		||||
 | 
			
		||||
namespace aria2 {
 | 
			
		||||
| 
						 | 
				
			
			@ -145,11 +146,17 @@ std::string HttpRequest::createRequest() const
 | 
			
		|||
  }
 | 
			
		||||
  requestLine +=
 | 
			
		||||
    std::string(" HTTP/1.1\r\n")+
 | 
			
		||||
    "User-Agent: "+userAgent+"\r\n"+
 | 
			
		||||
    "Accept: */*\r\n"+        /* */
 | 
			
		||||
    "User-Agent: "+userAgent+"\r\n";
 | 
			
		||||
  
 | 
			
		||||
  requestLine +=
 | 
			
		||||
    std::accumulate(_acceptTypes.begin(), _acceptTypes.end(),
 | 
			
		||||
		    std::string("Accept: */*"), Concat(","))+"\r\n"; /* */
 | 
			
		||||
 | 
			
		||||
  requestLine +=
 | 
			
		||||
    "Host: "+getHostText(getHost(), getPort())+"\r\n"+
 | 
			
		||||
    "Pragma: no-cache\r\n"+
 | 
			
		||||
    "Cache-Control: no-cache\r\n";
 | 
			
		||||
 | 
			
		||||
  if(!request->isKeepAliveEnabled() && !request->isPipeliningEnabled()) {
 | 
			
		||||
    requestLine += "Connection: close\r\n";
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -232,6 +239,11 @@ void HttpRequest::addHeader(const std::string& headersString)
 | 
			
		|||
  _headers.insert(_headers.end(), headers.begin(), headers.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HttpRequest::addAcceptType(const std::string& type)
 | 
			
		||||
{
 | 
			
		||||
  _acceptTypes.push_back(type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HttpRequest::configure(const Option* option)
 | 
			
		||||
{
 | 
			
		||||
  authEnabled = option->get(PREF_HTTP_AUTH_ENABLED) == V_TRUE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,8 @@ private:
 | 
			
		|||
 | 
			
		||||
  std::deque<std::string> _headers;
 | 
			
		||||
 | 
			
		||||
  std::deque<std::string> _acceptTypes;
 | 
			
		||||
 | 
			
		||||
  std::string getHostText(const std::string& host, uint16_t port) const;
 | 
			
		||||
 | 
			
		||||
  std::string getProxyAuthString() const;
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +173,14 @@ public:
 | 
			
		|||
  
 | 
			
		||||
  // accepts multiline headers, deliminated by LF
 | 
			
		||||
  void addHeader(const std::string& headers);
 | 
			
		||||
 | 
			
		||||
  void addAcceptType(const std::string& type);
 | 
			
		||||
 | 
			
		||||
  template<typename InputIterator>
 | 
			
		||||
  void addAcceptType(InputIterator first, InputIterator last)
 | 
			
		||||
  {
 | 
			
		||||
    _acceptTypes.insert(_acceptTypes.end(), first, last);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef SharedHandle<HttpRequest> HttpRequestHandle;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,7 +71,7 @@ createHttpRequest(const SharedHandle<Request>& req,
 | 
			
		|||
		  const SharedHandle<Segment>& segment,
 | 
			
		||||
		  uint64_t totalLength,
 | 
			
		||||
		  const Option* option,
 | 
			
		||||
		  const std::deque<std::string>& acceptFeatures)
 | 
			
		||||
		  const RequestGroup* rg)
 | 
			
		||||
{
 | 
			
		||||
  HttpRequestHandle httpRequest(new HttpRequest());
 | 
			
		||||
  httpRequest->setUserAgent(option->get(PREF_USER_AGENT));
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,8 @@ createHttpRequest(const SharedHandle<Request>& req,
 | 
			
		|||
  httpRequest->setSegment(segment);
 | 
			
		||||
  httpRequest->setEntityLength(totalLength);
 | 
			
		||||
  httpRequest->addHeader(option->get(PREF_HEADER));
 | 
			
		||||
  if(acceptFeatures.size()) {
 | 
			
		||||
  if(rg->getAcceptFeatures().size()) {
 | 
			
		||||
    const std::deque<std::string>& acceptFeatures = rg->getAcceptFeatures();
 | 
			
		||||
    std::string acceptFeaturesHeader = "Accept-Features: "+
 | 
			
		||||
      Util::trim
 | 
			
		||||
      (std::accumulate(acceptFeatures.begin()+1, acceptFeatures.end(),
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +89,8 @@ createHttpRequest(const SharedHandle<Request>& req,
 | 
			
		|||
       ",");
 | 
			
		||||
    httpRequest->addHeader(acceptFeaturesHeader);
 | 
			
		||||
  }
 | 
			
		||||
  httpRequest->addAcceptType(rg->getAcceptTypes().begin(),
 | 
			
		||||
			     rg->getAcceptTypes().end());
 | 
			
		||||
  httpRequest->configure(option);
 | 
			
		||||
 | 
			
		||||
  return httpRequest;
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +106,7 @@ bool HttpRequestCommand::executeInternal() {
 | 
			
		|||
    HttpRequestHandle httpRequest
 | 
			
		||||
      (createHttpRequest(req, SharedHandle<Segment>(),
 | 
			
		||||
			 _requestGroup->getTotalLength(), e->option,
 | 
			
		||||
			 _requestGroup->getAcceptFeatures()));
 | 
			
		||||
			 _requestGroup));
 | 
			
		||||
    _httpConnection->sendRequest(httpRequest);
 | 
			
		||||
  } else {
 | 
			
		||||
    for(Segments::iterator itr = _segments.begin(); itr != _segments.end(); ++itr) {
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +115,7 @@ bool HttpRequestCommand::executeInternal() {
 | 
			
		|||
	HttpRequestHandle httpRequest
 | 
			
		||||
	  (createHttpRequest(req, segment,
 | 
			
		||||
			     _requestGroup->getTotalLength(), e->option,
 | 
			
		||||
			     _requestGroup->getAcceptFeatures()));
 | 
			
		||||
			     _requestGroup));
 | 
			
		||||
	_httpConnection->sendRequest(httpRequest);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,9 +169,9 @@ Metalink2RequestGroup::createRequestGroup(std::deque<SharedHandle<MetalinkEntry>
 | 
			
		|||
      torrentRg->setDownloadContext(dctx);
 | 
			
		||||
      torrentRg->clearPreDowloadHandler();
 | 
			
		||||
      torrentRg->clearPostDowloadHandler();
 | 
			
		||||
      // remove "metalink" from Accept-Feature list to avoid loop in tranparent
 | 
			
		||||
      // remove "metalink" from Accept Type list to avoid loop in tranparent
 | 
			
		||||
      // metalink
 | 
			
		||||
      torrentRg->removeAcceptFeatureHeader(RequestGroup::FEATURE_METALINK);
 | 
			
		||||
      torrentRg->removeAcceptType(RequestGroup::ACCEPT_METALINK);
 | 
			
		||||
      // make it in-memory download
 | 
			
		||||
      SharedHandle<PreDownloadHandler> preh(new MemoryBufferPreDownloadHandler());
 | 
			
		||||
      {
 | 
			
		||||
| 
						 | 
				
			
			@ -222,9 +222,9 @@ Metalink2RequestGroup::createRequestGroup(std::deque<SharedHandle<MetalinkEntry>
 | 
			
		|||
				std::min(_option->getAsInt(PREF_METALINK_SERVERS), entry->maxConnections));
 | 
			
		||||
    // In metalink, multi connection to a single host is not allowed by default.
 | 
			
		||||
    rg->setSingleHostMultiConnectionEnabled(!_option->getAsBool(PREF_METALINK_ENABLE_UNIQUE_PROTOCOL));
 | 
			
		||||
    // remove "metalink" from Accept-Feature list to avoid loop in tranparent
 | 
			
		||||
    // remove "metalink" from Accept Type list to avoid loop in tranparent
 | 
			
		||||
    // metalink
 | 
			
		||||
    rg->removeAcceptFeatureHeader(RequestGroup::FEATURE_METALINK);
 | 
			
		||||
    rg->removeAcceptType(RequestGroup::ACCEPT_METALINK);
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_BITTORRENT
 | 
			
		||||
    // Inject depenency between rg and torrentRg here if torrentRg.isNull() == false
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ namespace aria2 {
 | 
			
		|||
 | 
			
		||||
int32_t RequestGroup::_gidCounter = 0;
 | 
			
		||||
 | 
			
		||||
const std::string RequestGroup::FEATURE_METALINK = "metalink";
 | 
			
		||||
const std::string RequestGroup::ACCEPT_METALINK = "application/metalink+xml";
 | 
			
		||||
 | 
			
		||||
RequestGroup::RequestGroup(const Option* option,
 | 
			
		||||
			   const std::deque<std::string>& uris):
 | 
			
		||||
| 
						 | 
				
			
			@ -127,11 +127,11 @@ RequestGroup::RequestGroup(const Option* option,
 | 
			
		|||
  } else {
 | 
			
		||||
    _fileAllocationEnabled = false;
 | 
			
		||||
  }
 | 
			
		||||
  // For now, only supported 'Accept-Features' is "metalink" used for
 | 
			
		||||
  // transparent metalink.
 | 
			
		||||
  // Add types to be sent as a Accept header value here.
 | 
			
		||||
  // It would be good to put this value in Option so that user can tweak
 | 
			
		||||
  // and add this list.
 | 
			
		||||
  _acceptFeatures.push_back(FEATURE_METALINK);
 | 
			
		||||
  // ACCEPT_METALINK is used for `transparent metalink'.
 | 
			
		||||
  addAcceptType(ACCEPT_METALINK);
 | 
			
		||||
 | 
			
		||||
  initializePreDownloadHandler();
 | 
			
		||||
  initializePostDownloadHandler();
 | 
			
		||||
| 
						 | 
				
			
			@ -969,4 +969,22 @@ void RequestGroup::removeAcceptFeatureHeader(const std::string& feature)
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const std::deque<std::string>& RequestGroup::getAcceptTypes() const
 | 
			
		||||
{
 | 
			
		||||
  return _acceptTypes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RequestGroup::addAcceptType(const std::string& type)
 | 
			
		||||
{
 | 
			
		||||
  if(std::find(_acceptTypes.begin(), _acceptTypes.end(), type) == _acceptTypes.end()) {
 | 
			
		||||
    _acceptTypes.push_back(type);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RequestGroup::removeAcceptType(const std::string& type)
 | 
			
		||||
{
 | 
			
		||||
  _acceptTypes.erase(std::remove(_acceptTypes.begin(), _acceptTypes.end(), type),
 | 
			
		||||
		     _acceptTypes.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace aria2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,6 +110,8 @@ private:
 | 
			
		|||
 | 
			
		||||
  std::deque<std::string> _acceptFeatures;
 | 
			
		||||
 | 
			
		||||
  std::deque<std::string> _acceptTypes;
 | 
			
		||||
 | 
			
		||||
  const Option* _option;
 | 
			
		||||
 | 
			
		||||
  Logger* _logger;
 | 
			
		||||
| 
						 | 
				
			
			@ -343,7 +345,13 @@ public:
 | 
			
		|||
 | 
			
		||||
  void removeAcceptFeatureHeader(const std::string& feature);
 | 
			
		||||
 | 
			
		||||
  static const std::string FEATURE_METALINK;
 | 
			
		||||
  const std::deque<std::string>& getAcceptTypes() const;
 | 
			
		||||
 | 
			
		||||
  void addAcceptType(const std::string& type);
 | 
			
		||||
 | 
			
		||||
  void removeAcceptType(const std::string& type);
 | 
			
		||||
 | 
			
		||||
  static const std::string ACCEPT_METALINK;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef SharedHandle<RequestGroup> RequestGroupHandle;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
#include "Request.h"
 | 
			
		||||
#include "CookieBox.h"
 | 
			
		||||
#include "Option.h"
 | 
			
		||||
#include "array_fun.h"
 | 
			
		||||
#include <cppunit/extensions/HelperMacros.h>
 | 
			
		||||
 | 
			
		||||
namespace aria2 {
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +25,7 @@ class HttpRequestTest : public CppUnit::TestFixture {
 | 
			
		|||
  CPPUNIT_TEST(testIsRangeSatisfied);
 | 
			
		||||
  CPPUNIT_TEST(testUserAgent);
 | 
			
		||||
  CPPUNIT_TEST(testAddHeader);
 | 
			
		||||
  CPPUNIT_TEST(testAddAcceptType);
 | 
			
		||||
  CPPUNIT_TEST_SUITE_END();
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +42,7 @@ public:
 | 
			
		|||
  void testIsRangeSatisfied();
 | 
			
		||||
  void testUserAgent();
 | 
			
		||||
  void testAddHeader();
 | 
			
		||||
  void testAddAcceptType();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -641,5 +644,29 @@ void HttpRequestTest::testAddHeader()
 | 
			
		|||
  CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HttpRequestTest::testAddAcceptType()
 | 
			
		||||
{
 | 
			
		||||
  std::string acceptTypes[] = { "cream/custard",
 | 
			
		||||
				"muffin/chocolate" };
 | 
			
		||||
 | 
			
		||||
  SharedHandle<Request> request(new Request());
 | 
			
		||||
  request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
 | 
			
		||||
 | 
			
		||||
  HttpRequest httpRequest;
 | 
			
		||||
  httpRequest.setRequest(request);
 | 
			
		||||
  httpRequest.addAcceptType(&acceptTypes[0], &acceptTypes[arrayLength(acceptTypes)]);
 | 
			
		||||
 | 
			
		||||
  std::string expectedText =
 | 
			
		||||
    "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n"
 | 
			
		||||
    "User-Agent: aria2\r\n"
 | 
			
		||||
    "Accept: */*,cream/custard,muffin/chocolate\r\n"
 | 
			
		||||
    "Host: localhost\r\n"
 | 
			
		||||
    "Pragma: no-cache\r\n"
 | 
			
		||||
    "Cache-Control: no-cache\r\n"
 | 
			
		||||
    "Connection: close\r\n"
 | 
			
		||||
    "\r\n";
 | 
			
		||||
 | 
			
		||||
  CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace aria2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue