HttpResponseTest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. #include <iostream>
  2. #include <cppunit/extensions/HelperMacros.h>
  3. #include "HttpResponse.h"
  4. #include "prefs.h"
  5. #include "PiecedSegment.h"
  6. #include "Piece.h"
  7. #include "Request.h"
  8. #include "HttpHeader.h"
  9. #include "HttpRequest.h"
  10. #include "Exception.h"
  11. #include "A2STR.h"
  12. #include "Decoder.h"
  13. #include "DlRetryEx.h"
  14. #include "CookieStorage.h"
  15. #include "AuthConfigFactory.h"
  16. namespace aria2 {
  17. class HttpResponseTest : public CppUnit::TestFixture {
  18. CPPUNIT_TEST_SUITE(HttpResponseTest);
  19. CPPUNIT_TEST(testGetContentLength_null);
  20. CPPUNIT_TEST(testGetContentLength_contentLength);
  21. //CPPUNIT_TEST(testGetContentLength_range);
  22. CPPUNIT_TEST(testGetEntityLength);
  23. CPPUNIT_TEST(testGetContentType);
  24. CPPUNIT_TEST(testDeterminFilename_without_ContentDisposition);
  25. CPPUNIT_TEST(testDeterminFilename_with_ContentDisposition_zero_length);
  26. CPPUNIT_TEST(testDeterminFilename_with_ContentDisposition);
  27. CPPUNIT_TEST(testGetRedirectURI_without_Location);
  28. CPPUNIT_TEST(testGetRedirectURI_with_Location);
  29. CPPUNIT_TEST(testIsRedirect);
  30. CPPUNIT_TEST(testIsTransferEncodingSpecified);
  31. CPPUNIT_TEST(testGetTransferEncoding);
  32. CPPUNIT_TEST(testGetTransferEncodingDecoder);
  33. CPPUNIT_TEST(testIsContentEncodingSpecified);
  34. CPPUNIT_TEST(testGetContentEncoding);
  35. CPPUNIT_TEST(testGetContentEncodingDecoder);
  36. CPPUNIT_TEST(testValidateResponse);
  37. CPPUNIT_TEST(testValidateResponse_good_range);
  38. CPPUNIT_TEST(testValidateResponse_bad_range);
  39. CPPUNIT_TEST(testValidateResponse_chunked);
  40. CPPUNIT_TEST(testHasRetryAfter);
  41. CPPUNIT_TEST(testProcessRedirect);
  42. CPPUNIT_TEST(testRetrieveCookie);
  43. CPPUNIT_TEST(testSupportsPersistentConnection);
  44. CPPUNIT_TEST_SUITE_END();
  45. private:
  46. public:
  47. void setUp() {
  48. }
  49. void testGetContentLength_null();
  50. void testGetContentLength_contentLength();
  51. void testGetEntityLength();
  52. void testGetContentType();
  53. void testDeterminFilename_without_ContentDisposition();
  54. void testDeterminFilename_with_ContentDisposition_zero_length();
  55. void testDeterminFilename_with_ContentDisposition();
  56. void testGetRedirectURI_without_Location();
  57. void testGetRedirectURI_with_Location();
  58. void testIsRedirect();
  59. void testIsTransferEncodingSpecified();
  60. void testGetTransferEncoding();
  61. void testGetTransferEncodingDecoder();
  62. void testIsContentEncodingSpecified();
  63. void testGetContentEncoding();
  64. void testGetContentEncodingDecoder();
  65. void testValidateResponse();
  66. void testValidateResponse_good_range();
  67. void testValidateResponse_bad_range();
  68. void testValidateResponse_chunked();
  69. void testHasRetryAfter();
  70. void testProcessRedirect();
  71. void testRetrieveCookie();
  72. void testSupportsPersistentConnection();
  73. };
  74. CPPUNIT_TEST_SUITE_REGISTRATION( HttpResponseTest );
  75. void HttpResponseTest::testGetContentLength_null()
  76. {
  77. HttpResponse httpResponse;
  78. CPPUNIT_ASSERT_EQUAL((uint64_t)0ULL, httpResponse.getContentLength());
  79. }
  80. void HttpResponseTest::testGetContentLength_contentLength()
  81. {
  82. HttpResponse httpResponse;
  83. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  84. httpHeader->put("Content-Length", "4294967296");
  85. httpResponse.setHttpHeader(httpHeader);
  86. CPPUNIT_ASSERT_EQUAL((uint64_t)4294967296ULL, httpResponse.getContentLength());
  87. }
  88. void HttpResponseTest::testGetEntityLength()
  89. {
  90. HttpResponse httpResponse;
  91. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  92. httpHeader->put("Content-Length", "4294967296");
  93. httpResponse.setHttpHeader(httpHeader);
  94. CPPUNIT_ASSERT_EQUAL((uint64_t)4294967296ULL, httpResponse.getEntityLength());
  95. httpHeader->put("Content-Range", "bytes 1-4294967296/4294967297");
  96. CPPUNIT_ASSERT_EQUAL((uint64_t)4294967297ULL, httpResponse.getEntityLength());
  97. }
  98. void HttpResponseTest::testGetContentType()
  99. {
  100. HttpResponse httpResponse;
  101. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  102. httpHeader->put("content-type", "application/octet-stream");
  103. httpResponse.setHttpHeader(httpHeader);
  104. CPPUNIT_ASSERT_EQUAL(std::string("application/octet-stream"),
  105. httpResponse.getContentType());
  106. }
  107. void HttpResponseTest::testDeterminFilename_without_ContentDisposition()
  108. {
  109. HttpResponse httpResponse;
  110. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  111. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  112. SharedHandle<Request> request(new Request());
  113. request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
  114. httpRequest->setRequest(request);
  115. httpResponse.setHttpHeader(httpHeader);
  116. httpResponse.setHttpRequest(httpRequest);
  117. CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"),
  118. httpResponse.determinFilename());
  119. }
  120. void HttpResponseTest::testDeterminFilename_with_ContentDisposition_zero_length
  121. ()
  122. {
  123. HttpResponse httpResponse;
  124. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  125. httpHeader->put("Content-Disposition", "attachment; filename=\"\"");
  126. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  127. SharedHandle<Request> request(new Request());
  128. request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
  129. httpRequest->setRequest(request);
  130. httpResponse.setHttpHeader(httpHeader);
  131. httpResponse.setHttpRequest(httpRequest);
  132. CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"),
  133. httpResponse.determinFilename());
  134. }
  135. void HttpResponseTest::testDeterminFilename_with_ContentDisposition()
  136. {
  137. HttpResponse httpResponse;
  138. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  139. httpHeader->put("Content-Disposition",
  140. "attachment; filename=\"aria2-current.tar.bz2\"");
  141. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  142. SharedHandle<Request> request(new Request());
  143. request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
  144. httpRequest->setRequest(request);
  145. httpResponse.setHttpHeader(httpHeader);
  146. httpResponse.setHttpRequest(httpRequest);
  147. CPPUNIT_ASSERT_EQUAL(std::string("aria2-current.tar.bz2"),
  148. httpResponse.determinFilename());
  149. }
  150. void HttpResponseTest::testGetRedirectURI_without_Location()
  151. {
  152. HttpResponse httpResponse;
  153. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  154. httpResponse.setHttpHeader(httpHeader);
  155. CPPUNIT_ASSERT_EQUAL(std::string(""),
  156. httpResponse.getRedirectURI());
  157. }
  158. void HttpResponseTest::testGetRedirectURI_with_Location()
  159. {
  160. HttpResponse httpResponse;
  161. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  162. httpHeader->put("Location", "http://localhost/download/aria2-1.0.0.tar.bz2");
  163. httpResponse.setHttpHeader(httpHeader);
  164. CPPUNIT_ASSERT_EQUAL
  165. (std::string("http://localhost/download/aria2-1.0.0.tar.bz2"),
  166. httpResponse.getRedirectURI());
  167. }
  168. void HttpResponseTest::testIsRedirect()
  169. {
  170. HttpResponse httpResponse;
  171. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  172. httpHeader->setResponseStatus("200");
  173. httpHeader->put("Location", "http://localhost/download/aria2-1.0.0.tar.bz2");
  174. httpResponse.setHttpHeader(httpHeader);
  175. CPPUNIT_ASSERT(!httpResponse.isRedirect());
  176. httpHeader->setResponseStatus("304");
  177. CPPUNIT_ASSERT(httpResponse.isRedirect());
  178. }
  179. void HttpResponseTest::testIsTransferEncodingSpecified()
  180. {
  181. HttpResponse httpResponse;
  182. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  183. httpResponse.setHttpHeader(httpHeader);
  184. CPPUNIT_ASSERT(!httpResponse.isTransferEncodingSpecified());
  185. httpHeader->put("Transfer-Encoding", "chunked");
  186. CPPUNIT_ASSERT(httpResponse.isTransferEncodingSpecified());
  187. }
  188. void HttpResponseTest::testGetTransferEncoding()
  189. {
  190. HttpResponse httpResponse;
  191. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  192. httpResponse.setHttpHeader(httpHeader);
  193. CPPUNIT_ASSERT_EQUAL(std::string(""), httpResponse.getTransferEncoding());
  194. httpHeader->put("Transfer-Encoding", "chunked");
  195. CPPUNIT_ASSERT_EQUAL(std::string("chunked"),
  196. httpResponse.getTransferEncoding());
  197. }
  198. void HttpResponseTest::testGetTransferEncodingDecoder()
  199. {
  200. HttpResponse httpResponse;
  201. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  202. httpResponse.setHttpHeader(httpHeader);
  203. CPPUNIT_ASSERT(httpResponse.getTransferEncodingDecoder().isNull());
  204. httpHeader->put("Transfer-Encoding", "chunked");
  205. CPPUNIT_ASSERT(!httpResponse.getTransferEncodingDecoder().isNull());
  206. }
  207. void HttpResponseTest::testIsContentEncodingSpecified()
  208. {
  209. HttpResponse httpResponse;
  210. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  211. httpResponse.setHttpHeader(httpHeader);
  212. CPPUNIT_ASSERT(!httpResponse.isContentEncodingSpecified());
  213. httpHeader->put("Content-Encoding", "gzip");
  214. CPPUNIT_ASSERT(httpResponse.isContentEncodingSpecified());
  215. }
  216. void HttpResponseTest::testGetContentEncoding()
  217. {
  218. HttpResponse httpResponse;
  219. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  220. httpResponse.setHttpHeader(httpHeader);
  221. CPPUNIT_ASSERT_EQUAL(A2STR::NIL, httpResponse.getContentEncoding());
  222. httpHeader->put("Content-Encoding", "gzip");
  223. CPPUNIT_ASSERT_EQUAL(std::string("gzip"), httpResponse.getContentEncoding());
  224. }
  225. void HttpResponseTest::testGetContentEncodingDecoder()
  226. {
  227. HttpResponse httpResponse;
  228. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  229. httpResponse.setHttpHeader(httpHeader);
  230. CPPUNIT_ASSERT(httpResponse.getContentEncodingDecoder().isNull());
  231. #ifdef HAVE_LIBZ
  232. httpHeader->put("Content-Encoding", "gzip");
  233. {
  234. SharedHandle<Decoder> decoder = httpResponse.getContentEncodingDecoder();
  235. CPPUNIT_ASSERT(!decoder.isNull());
  236. CPPUNIT_ASSERT_EQUAL(std::string("GZipDecoder"), decoder->getName());
  237. }
  238. httpHeader.reset(new HttpHeader());
  239. httpResponse.setHttpHeader(httpHeader);
  240. httpHeader->put("Content-Encoding", "deflate");
  241. {
  242. SharedHandle<Decoder> decoder = httpResponse.getContentEncodingDecoder();
  243. CPPUNIT_ASSERT(!decoder.isNull());
  244. CPPUNIT_ASSERT_EQUAL(std::string("GZipDecoder"), decoder->getName());
  245. }
  246. #endif // HAVE_LIBZ
  247. httpHeader.reset(new HttpHeader());
  248. httpResponse.setHttpHeader(httpHeader);
  249. httpHeader->put("Content-Encoding", "bzip2");
  250. {
  251. SharedHandle<Decoder> decoder = httpResponse.getContentEncodingDecoder();
  252. CPPUNIT_ASSERT(decoder.isNull());
  253. }
  254. }
  255. void HttpResponseTest::testValidateResponse()
  256. {
  257. HttpResponse httpResponse;
  258. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  259. httpResponse.setHttpHeader(httpHeader);
  260. httpHeader->setResponseStatus("304");
  261. try {
  262. httpResponse.validateResponse();
  263. CPPUNIT_FAIL("exception must be thrown.");
  264. } catch(Exception& e) {
  265. }
  266. httpHeader->put("Location", "http://localhost/archives/aria2-1.0.0.tar.bz2");
  267. try {
  268. httpResponse.validateResponse();
  269. } catch(Exception& e) {
  270. CPPUNIT_FAIL("exception must not be thrown.");
  271. }
  272. }
  273. void HttpResponseTest::testValidateResponse_good_range()
  274. {
  275. HttpResponse httpResponse;
  276. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  277. httpResponse.setHttpHeader(httpHeader);
  278. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  279. SharedHandle<Piece> p(new Piece(1, 1024*1024));
  280. SharedHandle<Segment> segment(new PiecedSegment(1024*1024, p));
  281. httpRequest->setSegment(segment);
  282. SharedHandle<Request> request(new Request());
  283. request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
  284. httpRequest->setRequest(request);
  285. httpResponse.setHttpRequest(httpRequest);
  286. httpHeader->setResponseStatus("206");
  287. httpHeader->put("Content-Range", "bytes 1048576-10485760/10485761");
  288. try {
  289. httpResponse.validateResponse();
  290. } catch(Exception& e) {
  291. std::cerr << e.stackTrace() << std::endl;
  292. CPPUNIT_FAIL("exception must not be thrown.");
  293. }
  294. }
  295. void HttpResponseTest::testValidateResponse_bad_range()
  296. {
  297. HttpResponse httpResponse;
  298. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  299. httpResponse.setHttpHeader(httpHeader);
  300. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  301. SharedHandle<Piece> p(new Piece(1, 1024*1024));
  302. SharedHandle<Segment> segment(new PiecedSegment(1024*1024, p));
  303. httpRequest->setSegment(segment);
  304. SharedHandle<Request> request(new Request());
  305. request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
  306. httpRequest->setRequest(request);
  307. httpResponse.setHttpRequest(httpRequest);
  308. httpHeader->setResponseStatus("206");
  309. httpHeader->put("Content-Range", "bytes 0-10485760/10485761");
  310. try {
  311. httpResponse.validateResponse();
  312. CPPUNIT_FAIL("exception must be thrown.");
  313. } catch(Exception& e) {
  314. }
  315. }
  316. void HttpResponseTest::testValidateResponse_chunked()
  317. {
  318. HttpResponse httpResponse;
  319. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  320. httpResponse.setHttpHeader(httpHeader);
  321. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  322. SharedHandle<Piece> p(new Piece(1, 1024*1024));
  323. SharedHandle<Segment> segment(new PiecedSegment(1024*1024, p));
  324. httpRequest->setSegment(segment);
  325. SharedHandle<Request> request(new Request());
  326. request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
  327. httpRequest->setRequest(request);
  328. httpResponse.setHttpRequest(httpRequest);
  329. httpHeader->setResponseStatus("206");
  330. httpHeader->put("Content-Range", "bytes 0-10485760/10485761");
  331. httpHeader->put("Transfer-Encoding", "chunked");
  332. // if transfer-encoding is specified, then range validation is skipped.
  333. try {
  334. httpResponse.validateResponse();
  335. } catch(Exception& e) {
  336. CPPUNIT_FAIL("exception must not be thrown.");
  337. }
  338. }
  339. void HttpResponseTest::testHasRetryAfter()
  340. {
  341. HttpResponse httpResponse;
  342. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  343. httpResponse.setHttpHeader(httpHeader);
  344. httpHeader->put("Retry-After", "60");
  345. CPPUNIT_ASSERT(httpResponse.hasRetryAfter());
  346. CPPUNIT_ASSERT_EQUAL((time_t)60, httpResponse.getRetryAfter());
  347. }
  348. void HttpResponseTest::testProcessRedirect()
  349. {
  350. HttpResponse httpResponse;
  351. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  352. httpResponse.setHttpHeader(httpHeader);
  353. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  354. SharedHandle<Request> request(new Request());
  355. request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
  356. httpRequest->setRequest(request);
  357. httpResponse.setHttpRequest(httpRequest);
  358. httpHeader->put("Location", "http://mirror/aria2-1.0.0.tar.bz2");
  359. httpResponse.processRedirect();
  360. httpHeader->clearField();
  361. // Give unsupported scheme
  362. httpHeader->put("Location", "unsupported://mirror/aria2-1.0.0.tar.bz2");
  363. try {
  364. httpResponse.processRedirect();
  365. CPPUNIT_FAIL("DlRetryEx exception must be thrown.");
  366. } catch(DlRetryEx& e) {
  367. // Success
  368. } catch(...) {
  369. CPPUNIT_FAIL("DlRetryEx exception must be thrown.");
  370. }
  371. }
  372. void HttpResponseTest::testRetrieveCookie()
  373. {
  374. HttpResponse httpResponse;
  375. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  376. httpResponse.setHttpHeader(httpHeader);
  377. SharedHandle<HttpRequest> httpRequest(new HttpRequest());
  378. SharedHandle<Request> request(new Request());
  379. request->setUrl("http://www.aria2.org/archives/aria2-1.0.0.tar.bz2");
  380. httpRequest->setRequest(request);
  381. SharedHandle<CookieStorage> st(new CookieStorage());
  382. httpRequest->setCookieStorage(st);
  383. httpResponse.setHttpRequest(httpRequest);
  384. httpHeader->put("Set-Cookie", "k1=v1; expires=Sun, 10-Jun-2007 11:00:00 GMT;"
  385. "path=/; domain=.aria2.org;");
  386. httpHeader->put("Set-Cookie", "k2=v2; expires=Sun, 01-Jan-09 00:00:00 GMT;"
  387. "path=/; domain=.aria2.org;");
  388. httpHeader->put("Set-Cookie", "k3=v3;");
  389. httpResponse.retrieveCookie();
  390. CPPUNIT_ASSERT_EQUAL((size_t)2, st->size());
  391. std::deque<Cookie>::const_iterator citer = st->begin();
  392. CPPUNIT_ASSERT_EQUAL(std::string("k2=v2"), (*(st->begin())).toString());
  393. CPPUNIT_ASSERT_EQUAL(std::string("k3=v3"), (*(st->begin()+1)).toString());
  394. }
  395. void HttpResponseTest::testSupportsPersistentConnection()
  396. {
  397. HttpResponse httpResponse;
  398. SharedHandle<HttpHeader> httpHeader(new HttpHeader());
  399. httpResponse.setHttpHeader(httpHeader);
  400. httpHeader->setVersion("HTTP/1.1");
  401. CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
  402. httpHeader->setVersion("HTTP/1.0");
  403. CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
  404. httpHeader->setVersion("HTTP/1.1");
  405. httpHeader->put("Connection", "close");
  406. CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
  407. httpHeader->clearField();
  408. httpHeader->put("Connection", "keep-alive");
  409. CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
  410. }
  411. } // namespace aria2