HttpResponseTest.cc 16 KB

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