HttpRequest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "HttpRequest.h"
  36. #include <cassert>
  37. #include <numeric>
  38. #include <vector>
  39. #include "Segment.h"
  40. #include "Range.h"
  41. #include "CookieStorage.h"
  42. #include "Option.h"
  43. #include "util.h"
  44. #include "base64.h"
  45. #include "prefs.h"
  46. #include "AuthConfigFactory.h"
  47. #include "AuthConfig.h"
  48. #include "a2functional.h"
  49. #include "TimeA2.h"
  50. #include "array_fun.h"
  51. #include "Request.h"
  52. #include "DownloadHandlerConstants.h"
  53. namespace aria2 {
  54. const std::string HttpRequest::USER_AGENT("aria2");
  55. HttpRequest::HttpRequest():contentEncodingEnabled_(true),
  56. userAgent_(USER_AGENT),
  57. acceptMetalink_(false),
  58. option_(0),
  59. noCache_(true),
  60. acceptGzip_(false),
  61. endOffsetOverride_(0)
  62. {}
  63. HttpRequest::~HttpRequest() {}
  64. void HttpRequest::setSegment(const SharedHandle<Segment>& segment)
  65. {
  66. segment_ = segment;
  67. }
  68. void HttpRequest::setRequest(const SharedHandle<Request>& request)
  69. {
  70. request_ = request;
  71. }
  72. int64_t HttpRequest::getStartByte() const
  73. {
  74. if(!segment_) {
  75. return 0;
  76. } else {
  77. return fileEntry_->gtoloff(segment_->getPositionToWrite());
  78. }
  79. }
  80. int64_t HttpRequest::getEndByte() const
  81. {
  82. if(!segment_ || !request_) {
  83. return 0;
  84. } else {
  85. if(request_->isPipeliningEnabled()) {
  86. int64_t endByte =
  87. fileEntry_->gtoloff(segment_->getPosition()+segment_->getLength()-1);
  88. return std::min(endByte, fileEntry_->getLength()-1);
  89. } else if(endOffsetOverride_ > 0) {
  90. return endOffsetOverride_ - 1;
  91. } else {
  92. return 0;
  93. }
  94. }
  95. }
  96. Range HttpRequest::getRange() const
  97. {
  98. // content-length is always 0
  99. if(!segment_) {
  100. return Range();
  101. } else {
  102. return Range(getStartByte(), getEndByte(), fileEntry_->getLength());
  103. }
  104. }
  105. bool HttpRequest::isRangeSatisfied(const Range& range) const
  106. {
  107. if(!segment_) {
  108. return true;
  109. }
  110. if((getStartByte() == range.startByte) &&
  111. ((getEndByte() == 0) ||
  112. (getEndByte() == range.endByte)) &&
  113. ((fileEntry_->getLength() == 0) ||
  114. (fileEntry_->getLength() == range.entityLength))) {
  115. return true;
  116. } else {
  117. return false;
  118. }
  119. }
  120. namespace {
  121. std::string getHostText(const std::string& host, uint16_t port)
  122. {
  123. std::string hosttext = host;
  124. if(!(port == 80 || port == 443)) {
  125. hosttext += fmt(":%u", port);;
  126. }
  127. return hosttext;
  128. }
  129. } // namespace
  130. std::string HttpRequest::createRequest()
  131. {
  132. authConfig_ = authConfigFactory_->createAuthConfig(request_, option_);
  133. std::string requestLine = request_->getMethod();
  134. requestLine += " ";
  135. if(proxyRequest_) {
  136. if(getProtocol() == "ftp" &&
  137. request_->getUsername().empty() && authConfig_) {
  138. // Insert user into URI, like ftp://USER@host/
  139. std::string uri = getCurrentURI();
  140. assert(uri.size() >= 6);
  141. uri.insert(6, util::percentEncode(authConfig_->getUser())+"@");
  142. requestLine += uri;
  143. } else {
  144. requestLine += getCurrentURI();
  145. }
  146. } else {
  147. requestLine += getDir();
  148. requestLine += getFile();
  149. requestLine += getQuery();
  150. }
  151. requestLine += " HTTP/1.1\r\n";
  152. std::vector<std::pair<std::string, std::string> > builtinHds;
  153. builtinHds.reserve(20);
  154. builtinHds.push_back(std::make_pair("User-Agent:", userAgent_));
  155. std::string acceptTypes = "*/*";
  156. if(acceptMetalink_) {
  157. // The mime types of Metalink are used for "transparent metalink".
  158. const char** metalinkTypes = getMetalinkContentTypes();
  159. for(size_t i = 0; metalinkTypes[i]; ++i) {
  160. acceptTypes += ",";
  161. acceptTypes += metalinkTypes[i];
  162. }
  163. }
  164. builtinHds.push_back(std::make_pair("Accept:", acceptTypes));
  165. if(contentEncodingEnabled_) {
  166. std::string acceptableEncodings;
  167. #ifdef HAVE_ZLIB
  168. if(acceptGzip_) {
  169. acceptableEncodings += "deflate, gzip";
  170. }
  171. #endif // HAVE_ZLIB
  172. if(!acceptableEncodings.empty()) {
  173. builtinHds.push_back
  174. (std::make_pair("Accept-Encoding:", acceptableEncodings));
  175. }
  176. }
  177. builtinHds.push_back
  178. (std::make_pair("Host:", getHostText(getURIHost(), getPort())));
  179. if(noCache_) {
  180. builtinHds.push_back(std::make_pair("Pragma:", "no-cache"));
  181. builtinHds.push_back(std::make_pair("Cache-Control:", "no-cache"));
  182. }
  183. if(!request_->isKeepAliveEnabled() && !request_->isPipeliningEnabled()) {
  184. builtinHds.push_back(std::make_pair("Connection:", "close"));
  185. }
  186. if(segment_ && segment_->getLength() > 0 &&
  187. (request_->isPipeliningEnabled() || getStartByte() > 0 ||
  188. getEndByte() > 0)) {
  189. std::string rangeHeader(fmt("bytes=%" PRId64 "-", getStartByte()));
  190. if(request_->isPipeliningEnabled()) {
  191. rangeHeader += util::itos(getEndByte());
  192. } else if(getEndByte() > 0) {
  193. // FTP via http proxy does not support endbytes
  194. rangeHeader += util::itos(getEndByte());
  195. }
  196. builtinHds.push_back(std::make_pair("Range:", rangeHeader));
  197. }
  198. if(proxyRequest_) {
  199. if(request_->isKeepAliveEnabled() || request_->isPipeliningEnabled()) {
  200. builtinHds.push_back(std::make_pair("Connection:", "Keep-Alive"));
  201. }
  202. }
  203. if(proxyRequest_ && !proxyRequest_->getUsername().empty()) {
  204. builtinHds.push_back(getProxyAuthString());
  205. }
  206. if(authConfig_) {
  207. std::string authText = authConfig_->getAuthText();
  208. std::string val = "Basic ";
  209. val += base64::encode(authText.begin(), authText.end());
  210. builtinHds.push_back(std::make_pair("Authorization:", val));
  211. }
  212. if(!getPreviousURI().empty()) {
  213. builtinHds.push_back(std::make_pair("Referer:", getPreviousURI()));
  214. }
  215. if(cookieStorage_) {
  216. std::string cookiesValue;
  217. std::string path = getDir();
  218. path += getFile();
  219. std::vector<Cookie> cookies =
  220. cookieStorage_->criteriaFind(getHost(), path,
  221. Time().getTime(),
  222. getProtocol() == "https");
  223. for(std::vector<Cookie>::const_iterator itr = cookies.begin(),
  224. eoi = cookies.end(); itr != eoi; ++itr) {
  225. cookiesValue += (*itr).toString();
  226. cookiesValue += ";";
  227. }
  228. if(!cookiesValue.empty()) {
  229. builtinHds.push_back(std::make_pair("Cookie:", cookiesValue));
  230. }
  231. }
  232. if(!ifModSinceHeader_.empty()) {
  233. builtinHds.push_back
  234. (std::make_pair("If-Modified-Since:", ifModSinceHeader_));
  235. }
  236. for(std::vector<std::pair<std::string, std::string> >::const_iterator i =
  237. builtinHds.begin(), eoi = builtinHds.end(); i != eoi; ++i) {
  238. std::vector<std::string>::const_iterator j = headers_.begin();
  239. std::vector<std::string>::const_iterator jend = headers_.end();
  240. for(; j != jend; ++j) {
  241. if(util::startsWith(*j, (*i).first)) {
  242. break;
  243. }
  244. }
  245. if(j == jend) {
  246. requestLine += (*i).first;
  247. requestLine += " ";
  248. requestLine += (*i).second;
  249. requestLine += "\r\n";
  250. }
  251. }
  252. // append additional headers given by user.
  253. for(std::vector<std::string>::const_iterator i = headers_.begin(),
  254. eoi = headers_.end(); i != eoi; ++i) {
  255. requestLine += *i;
  256. requestLine += "\r\n";
  257. }
  258. requestLine += "\r\n";
  259. return requestLine;
  260. }
  261. std::string HttpRequest::createProxyRequest() const
  262. {
  263. assert(proxyRequest_);
  264. std::string requestLine(fmt("CONNECT %s:%u HTTP/1.1\r\n"
  265. "User-Agent: %s\r\n"
  266. "Host: %s:%u\r\n",
  267. getURIHost().c_str(),
  268. getPort(),
  269. userAgent_.c_str(),
  270. getURIHost().c_str(),
  271. getPort()));
  272. if(!proxyRequest_->getUsername().empty()) {
  273. std::pair<std::string, std::string> auth = getProxyAuthString();
  274. requestLine += auth.first;
  275. requestLine += " ";
  276. requestLine += auth.second;
  277. requestLine += "\r\n";
  278. }
  279. requestLine += "\r\n";
  280. return requestLine;
  281. }
  282. std::pair<std::string, std::string> HttpRequest::getProxyAuthString() const
  283. {
  284. std::string authText = proxyRequest_->getUsername();
  285. authText += ":";
  286. authText += proxyRequest_->getPassword();
  287. std::string val = "Basic ";
  288. val += base64::encode(authText.begin(), authText.end());
  289. return std::make_pair("Proxy-Authorization:", val);
  290. }
  291. void HttpRequest::enableContentEncoding()
  292. {
  293. contentEncodingEnabled_ = true;
  294. }
  295. void HttpRequest::disableContentEncoding()
  296. {
  297. contentEncodingEnabled_ = false;
  298. }
  299. void HttpRequest::addHeader(const std::string& headersString)
  300. {
  301. util::split(headersString.begin(), headersString.end(),
  302. std::back_inserter(headers_), '\n', true);
  303. }
  304. void HttpRequest::clearHeader()
  305. {
  306. headers_.clear();
  307. }
  308. void HttpRequest::setCookieStorage
  309. (const SharedHandle<CookieStorage>& cookieStorage)
  310. {
  311. cookieStorage_ = cookieStorage;
  312. }
  313. void HttpRequest::setAuthConfigFactory
  314. (const SharedHandle<AuthConfigFactory>& factory, const Option* option)
  315. {
  316. authConfigFactory_ = factory;
  317. option_ = option;
  318. }
  319. void HttpRequest::setProxyRequest(const SharedHandle<Request>& proxyRequest)
  320. {
  321. proxyRequest_ = proxyRequest;
  322. }
  323. bool HttpRequest::isProxyRequestSet() const
  324. {
  325. return proxyRequest_;
  326. }
  327. bool HttpRequest::authenticationUsed() const
  328. {
  329. return authConfig_;
  330. }
  331. const SharedHandle<AuthConfig>& HttpRequest::getAuthConfig() const
  332. {
  333. return authConfig_;
  334. }
  335. int64_t HttpRequest::getEntityLength() const
  336. {
  337. assert(fileEntry_);
  338. return fileEntry_->getLength();
  339. }
  340. const std::string& HttpRequest::getHost() const
  341. {
  342. return request_->getHost();
  343. }
  344. uint16_t HttpRequest::getPort() const
  345. {
  346. return request_->getPort();
  347. }
  348. const std::string& HttpRequest::getMethod() const
  349. {
  350. return request_->getMethod();
  351. }
  352. const std::string& HttpRequest::getProtocol() const
  353. {
  354. return request_->getProtocol();
  355. }
  356. const std::string& HttpRequest::getCurrentURI() const
  357. {
  358. return request_->getCurrentUri();
  359. }
  360. const std::string& HttpRequest::getDir() const
  361. {
  362. return request_->getDir();
  363. }
  364. const std::string& HttpRequest::getFile() const
  365. {
  366. return request_->getFile();
  367. }
  368. const std::string& HttpRequest::getQuery() const
  369. {
  370. return request_->getQuery();
  371. }
  372. const std::string& HttpRequest::getPreviousURI() const
  373. {
  374. return request_->getPreviousUri();
  375. }
  376. std::string HttpRequest::getURIHost() const
  377. {
  378. return request_->getURIHost();
  379. }
  380. void HttpRequest::setUserAgent(const std::string& userAgent)
  381. {
  382. userAgent_ = userAgent;
  383. }
  384. void HttpRequest::setFileEntry(const SharedHandle<FileEntry>& fileEntry)
  385. {
  386. fileEntry_ = fileEntry;
  387. }
  388. void HttpRequest::setIfModifiedSinceHeader(const std::string& hd)
  389. {
  390. ifModSinceHeader_ = hd;
  391. }
  392. bool HttpRequest::conditionalRequest() const
  393. {
  394. if(!ifModSinceHeader_.empty()) {
  395. return true;
  396. }
  397. for(std::vector<std::string>::const_iterator i = headers_.begin(),
  398. eoi = headers_.end(); i != eoi; ++i) {
  399. if(util::istartsWith(*i, "if-modified-since") ||
  400. util::istartsWith(*i, "if-none-match")) {
  401. return true;
  402. }
  403. }
  404. return false;
  405. }
  406. } // namespace aria2