brpc_hpack_unittest.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. // brpc - A framework to host and access services throughout Baidu.
  18. // Date: 2017/04/25 00:23:12
  19. #include <gtest/gtest.h>
  20. #include "brpc/details/hpack.h"
  21. #include "butil/logging.h"
  22. class HPackTest : public testing::Test {
  23. };
  24. // Copied test cases from example of rfc7541
  25. TEST_F(HPackTest, header_with_indexing) {
  26. brpc::HPacker p1;
  27. ASSERT_EQ(0, p1.Init(4096));
  28. brpc::HPacker p2;
  29. ASSERT_EQ(0, p2.Init(4096));
  30. brpc::HPacker::Header h;
  31. h.name = "Custom-Key";
  32. h.value = "custom-header";
  33. brpc::HPackOptions options;
  34. options.index_policy = brpc::HPACK_INDEX_HEADER;
  35. butil::IOBufAppender buf;
  36. p1.Encode(&buf, h, options);
  37. const ssize_t nwrite = buf.buf().size();
  38. LOG(INFO) << butil::ToPrintable(buf.buf());
  39. uint8_t expected[] = {
  40. 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79,
  41. 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64,
  42. 0x65, 0x72};
  43. butil::StringPiece sp((char*)expected, sizeof(expected));
  44. ASSERT_TRUE(buf.buf().equals(sp));
  45. brpc::HPacker::Header h2;
  46. ssize_t nread = p2.Decode(&buf.buf(), &h2);
  47. ASSERT_EQ(nread, nwrite);
  48. ASSERT_TRUE(buf.buf().empty());
  49. std::string lowercase_name = h.name;
  50. brpc::tolower(&lowercase_name);
  51. ASSERT_EQ(lowercase_name, h2.name);
  52. ASSERT_EQ(h.value, h2.value);
  53. }
  54. TEST_F(HPackTest, header_without_indexing) {
  55. brpc::HPacker p1;
  56. ASSERT_EQ(0, p1.Init(4096));
  57. brpc::HPacker p2;
  58. ASSERT_EQ(0, p2.Init(4096));
  59. brpc::HPacker::Header h;
  60. h.name = ":path";
  61. h.value = "/sample/path";
  62. brpc::HPackOptions options;
  63. options.index_policy = brpc::HPACK_NOT_INDEX_HEADER;
  64. butil::IOBufAppender buf;
  65. p1.Encode(&buf, h, options);
  66. const ssize_t nwrite = buf.buf().size();
  67. LOG(INFO) << butil::ToPrintable(buf.buf());
  68. uint8_t expected[] = {
  69. 0x04, 0x0c, 0x2f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x70, 0x61,
  70. 0x74, 0x68,
  71. };
  72. butil::StringPiece sp((char*)expected, sizeof(expected));
  73. ASSERT_TRUE(buf.buf().equals(sp));
  74. brpc::HPacker::Header h2;
  75. ssize_t nread = p2.Decode(&buf.buf(), &h2);
  76. ASSERT_EQ(nread, nwrite);
  77. ASSERT_TRUE(buf.buf().empty());
  78. std::string lowercase_name = h.name;
  79. brpc::tolower(&lowercase_name);
  80. ASSERT_EQ(lowercase_name, h2.name);
  81. ASSERT_EQ(h.value, h2.value);
  82. }
  83. TEST_F(HPackTest, header_never_indexed) {
  84. brpc::HPacker p1;
  85. ASSERT_EQ(0, p1.Init(4096));
  86. brpc::HPacker p2;
  87. ASSERT_EQ(0, p2.Init(4096));
  88. brpc::HPacker::Header h;
  89. h.name = "password";
  90. h.value = "secret";
  91. brpc::HPackOptions options;
  92. options.index_policy = brpc::HPACK_NEVER_INDEX_HEADER;
  93. butil::IOBufAppender buf;
  94. p1.Encode(&buf, h, options);
  95. const ssize_t nwrite = buf.buf().size();
  96. LOG(INFO) << butil::ToPrintable(buf.buf());
  97. uint8_t expected[] = {
  98. 0x10, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
  99. 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
  100. };
  101. butil::StringPiece sp((char*)expected, sizeof(expected));
  102. ASSERT_TRUE(buf.buf().equals(sp));
  103. brpc::HPacker::Header h2;
  104. ssize_t nread = p2.Decode(&buf.buf(), &h2);
  105. ASSERT_EQ(nread, nwrite);
  106. ASSERT_TRUE(buf.buf().empty());
  107. ASSERT_EQ(h.name, h2.name);
  108. ASSERT_EQ(h.value, h2.value);
  109. }
  110. TEST_F(HPackTest, indexed_header) {
  111. brpc::HPacker p1;
  112. ASSERT_EQ(0, p1.Init(4096));
  113. brpc::HPacker p2;
  114. ASSERT_EQ(0, p2.Init(4096));
  115. brpc::HPacker::Header h;
  116. h.name = ":method";
  117. h.value = "GET";
  118. brpc::HPackOptions options;
  119. options.index_policy = brpc::HPACK_INDEX_HEADER;
  120. butil::IOBufAppender buf;
  121. p1.Encode(&buf, h, options);
  122. const ssize_t nwrite = buf.buf().size();
  123. LOG(INFO) << butil::ToPrintable(buf.buf());
  124. uint8_t expected[] = {
  125. 0x82,
  126. };
  127. butil::StringPiece sp((char*)expected, sizeof(expected));
  128. ASSERT_TRUE(buf.buf().equals(sp));
  129. brpc::HPacker::Header h2;
  130. ssize_t nread = p2.Decode(&buf.buf(), &h2);
  131. ASSERT_EQ(nread, nwrite);
  132. ASSERT_TRUE(buf.buf().empty());
  133. ASSERT_EQ(h.name, h2.name);
  134. ASSERT_EQ(h.value, h2.value);
  135. }
  136. struct ConstHeader {
  137. const char* name;
  138. const char* value;
  139. };
  140. TEST_F(HPackTest, requests_without_huffman) {
  141. brpc::HPacker p1;
  142. ASSERT_EQ(0, p1.Init(4096));
  143. brpc::HPacker p2;
  144. ASSERT_EQ(0, p2.Init(4096));
  145. ConstHeader header1[] = {
  146. {":method", "GET"},
  147. {":scheme", "http"},
  148. {":path", "/"},
  149. {":authority", "www.example.com"},
  150. };
  151. butil::IOBufAppender buf;
  152. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  153. brpc::HPacker::Header h;
  154. h.name = header1[i].name;
  155. h.value = header1[i].value;
  156. brpc::HPackOptions options;
  157. options.index_policy = brpc::HPACK_INDEX_HEADER;
  158. p1.Encode(&buf, h, options);
  159. }
  160. uint8_t expected1[] = {
  161. 0x82, 0x86, 0x84, 0x41, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78,
  162. 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
  163. };
  164. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected1, sizeof(expected1))));
  165. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  166. brpc::HPacker::Header h;
  167. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  168. ASSERT_EQ(header1[i].name, h.name);
  169. ASSERT_EQ(header1[i].value, h.value);
  170. }
  171. ASSERT_TRUE(buf.buf().empty());
  172. ConstHeader header2[] = {
  173. {":method", "GET"},
  174. {":scheme", "http"},
  175. {":path", "/"},
  176. {":authority", "www.example.com"},
  177. {"cache-control", "no-cache"},
  178. };
  179. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  180. brpc::HPacker::Header h;
  181. h.name = header2[i].name;
  182. h.value = header2[i].value;
  183. brpc::HPackOptions options;
  184. options.index_policy = brpc::HPACK_INDEX_HEADER;
  185. p1.Encode(&buf, h, options);
  186. }
  187. uint8_t expected2[] = {
  188. 0x82, 0x86, 0x84, 0xbe, 0x58, 0x08, 0x6e, 0x6f, 0x2d,
  189. 0x63, 0x61, 0x63, 0x68, 0x65,
  190. };
  191. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected2, sizeof(expected2))));
  192. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  193. brpc::HPacker::Header h;
  194. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  195. ASSERT_EQ(header2[i].name, h.name);
  196. ASSERT_EQ(header2[i].value, h.value);
  197. }
  198. ASSERT_TRUE(buf.buf().empty());
  199. ConstHeader header3[] = {
  200. {":method", "GET"},
  201. {":scheme", "https"},
  202. {":path", "/index.html"},
  203. {":authority", "www.example.com"},
  204. {"custom-key", "custom-value"},
  205. };
  206. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  207. brpc::HPacker::Header h;
  208. h.name = header3[i].name;
  209. h.value = header3[i].value;
  210. brpc::HPackOptions options;
  211. options.index_policy = brpc::HPACK_INDEX_HEADER;
  212. p1.Encode(&buf, h, options);
  213. }
  214. uint8_t expected3[] = {
  215. 0x82, 0x87, 0x85, 0xbf, 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
  216. 0x2d, 0x6b, 0x65, 0x79, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d,
  217. 0x76, 0x61, 0x6c, 0x75, 0x65,
  218. };
  219. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected3, sizeof(expected3))));
  220. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  221. brpc::HPacker::Header h;
  222. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  223. ASSERT_EQ(header3[i].name, h.name);
  224. ASSERT_EQ(header3[i].value, h.value);
  225. }
  226. ASSERT_TRUE(buf.buf().empty());
  227. }
  228. TEST_F(HPackTest, requests_with_huffman) {
  229. brpc::HPacker p1;
  230. ASSERT_EQ(0, p1.Init(4096));
  231. brpc::HPacker p2;
  232. ASSERT_EQ(0, p2.Init(4096));
  233. ConstHeader header1[] = {
  234. {":method", "GET"},
  235. {":scheme", "http"},
  236. {":path", "/"},
  237. {":authority", "www.example.com"},
  238. };
  239. butil::IOBufAppender buf;
  240. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  241. brpc::HPacker::Header h;
  242. h.name = header1[i].name;
  243. h.value = header1[i].value;
  244. brpc::HPackOptions options;
  245. options.index_policy = brpc::HPACK_INDEX_HEADER;
  246. options.encode_name = true;
  247. options.encode_value = true;
  248. p1.Encode(&buf, h, options);
  249. }
  250. uint8_t expected1[] = {
  251. 0x82, 0x86, 0x84, 0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b,
  252. 0xa0, 0xab, 0x90, 0xf4, 0xff
  253. };
  254. LOG(INFO) << butil::ToPrintable(buf.buf());
  255. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected1, sizeof(expected1))));
  256. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  257. brpc::HPacker::Header h;
  258. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  259. ASSERT_EQ(header1[i].name, h.name);
  260. ASSERT_EQ(header1[i].value, h.value);
  261. }
  262. ASSERT_TRUE(buf.buf().empty());
  263. ConstHeader header2[] = {
  264. {":method", "GET"},
  265. {":scheme", "http"},
  266. {":path", "/"},
  267. {":authority", "www.example.com"},
  268. {"cache-control", "no-cache"},
  269. };
  270. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  271. brpc::HPacker::Header h;
  272. h.name = header2[i].name;
  273. h.value = header2[i].value;
  274. brpc::HPackOptions options;
  275. options.encode_name = true;
  276. options.encode_value = true;
  277. options.index_policy = brpc::HPACK_INDEX_HEADER;
  278. p1.Encode(&buf, h, options);
  279. }
  280. uint8_t expected2[] = {
  281. 0x82, 0x86, 0x84, 0xbe, 0x58, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf,
  282. };
  283. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected2, sizeof(expected2))));
  284. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  285. brpc::HPacker::Header h;
  286. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  287. ASSERT_EQ(header2[i].name, h.name);
  288. ASSERT_EQ(header2[i].value, h.value);
  289. }
  290. ASSERT_TRUE(buf.buf().empty());
  291. ConstHeader header3[] = {
  292. {":method", "GET"},
  293. {":scheme", "https"},
  294. {":path", "/index.html"},
  295. {":authority", "www.example.com"},
  296. {"custom-key", "custom-value"},
  297. };
  298. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  299. brpc::HPacker::Header h;
  300. h.name = header3[i].name;
  301. h.value = header3[i].value;
  302. brpc::HPackOptions options;
  303. options.encode_name = true;
  304. options.encode_value = true;
  305. options.index_policy = brpc::HPACK_INDEX_HEADER;
  306. p1.Encode(&buf, h, options);
  307. }
  308. uint8_t expected3[] = {
  309. 0x82, 0x87, 0x85, 0xbf, 0x40, 0x88, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9,
  310. 0x7d, 0x7f, 0x89, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xb8, 0xe8, 0xb4, 0xbf,
  311. };
  312. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected3, sizeof(expected3))));
  313. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  314. brpc::HPacker::Header h;
  315. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  316. ASSERT_EQ(header3[i].name, h.name);
  317. ASSERT_EQ(header3[i].value, h.value);
  318. }
  319. ASSERT_TRUE(buf.buf().empty());
  320. }
  321. TEST_F(HPackTest, responses_without_huffman) {
  322. // https://tools.ietf.org/html/rfc7541#appendix-C.5
  323. brpc::HPacker p1;
  324. ASSERT_EQ(0, p1.Init(256));
  325. brpc::HPacker p2;
  326. ASSERT_EQ(0, p2.Init(256));
  327. ConstHeader header1[] = {
  328. {":status", "302"},
  329. {"cache-control", "private"},
  330. {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
  331. {"location", "https://www.example.com"},
  332. };
  333. butil::IOBufAppender buf;
  334. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  335. brpc::HPacker::Header h;
  336. h.name = header1[i].name;
  337. h.value = header1[i].value;
  338. brpc::HPackOptions options;
  339. options.index_policy = brpc::HPACK_INDEX_HEADER;
  340. p1.Encode(&buf, h, options);
  341. }
  342. uint8_t expected1[] = {
  343. 0x48, 0x03, 0x33, 0x30, 0x32, 0x58, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61,
  344. 0x74, 0x65, 0x61, 0x1d, 0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x31, 0x20,
  345. 0x4f, 0x63, 0x74, 0x20, 0x32, 0x30, 0x31, 0x33, 0x20, 0x32, 0x30, 0x3a,
  346. 0x31, 0x33, 0x3a, 0x32, 0x31, 0x20, 0x47, 0x4d, 0x54, 0x6e, 0x17, 0x68,
  347. 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x65,
  348. 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
  349. };
  350. LOG(INFO) << butil::ToPrintable(buf.buf());
  351. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected1, sizeof(expected1))));
  352. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  353. brpc::HPacker::Header h;
  354. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  355. ASSERT_EQ(header1[i].name, h.name);
  356. ASSERT_EQ(header1[i].value, h.value);
  357. }
  358. ASSERT_TRUE(buf.buf().empty());
  359. ConstHeader header2[] = {
  360. {":status", "307"},
  361. {"cache-control", "private"},
  362. {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
  363. {"location", "https://www.example.com"},
  364. };
  365. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  366. brpc::HPacker::Header h;
  367. h.name = header2[i].name;
  368. h.value = header2[i].value;
  369. brpc::HPackOptions options;
  370. options.index_policy = brpc::HPACK_INDEX_HEADER;
  371. p1.Encode(&buf, h, options);
  372. }
  373. uint8_t expected2[] = {
  374. 0x48, 0x03, 0x33, 0x30, 0x37, 0xc1, 0xc0, 0xbf,
  375. };
  376. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected2, sizeof(expected2))));
  377. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  378. brpc::HPacker::Header h;
  379. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  380. ASSERT_EQ(header2[i].name, h.name);
  381. ASSERT_EQ(header2[i].value, h.value);
  382. }
  383. ASSERT_TRUE(buf.buf().empty());
  384. ConstHeader header3[] = {
  385. {":status", "200"},
  386. {"cache-control", "private"},
  387. {"date", "Mon, 21 Oct 2013 20:13:22 GMT"},
  388. {"location", "https://www.example.com"},
  389. {"content-encoding", "gzip"},
  390. {"set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
  391. };
  392. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  393. brpc::HPacker::Header h;
  394. h.name = header3[i].name;
  395. h.value = header3[i].value;
  396. brpc::HPackOptions options;
  397. options.index_policy = brpc::HPACK_INDEX_HEADER;
  398. p1.Encode(&buf, h, options);
  399. }
  400. uint8_t expected3[] = {
  401. 0x88, 0xc1, 0x61, 0x1d, 0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x31, 0x20,
  402. 0x4f, 0x63, 0x74, 0x20, 0x32, 0x30, 0x31, 0x33, 0x20, 0x32, 0x30, 0x3a,
  403. 0x31, 0x33, 0x3a, 0x32, 0x32, 0x20, 0x47, 0x4d, 0x54, 0xc0, 0x5a, 0x04,
  404. 0x67, 0x7a, 0x69, 0x70, 0x77, 0x38, 0x66, 0x6f, 0x6f, 0x3d, 0x41, 0x53,
  405. 0x44, 0x4a, 0x4b, 0x48, 0x51, 0x4b, 0x42, 0x5a, 0x58, 0x4f, 0x51, 0x57,
  406. 0x45, 0x4f, 0x50, 0x49, 0x55, 0x41, 0x58, 0x51, 0x57, 0x45, 0x4f, 0x49,
  407. 0x55, 0x3b, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, 0x3d, 0x33,
  408. 0x36, 0x30, 0x30, 0x3b, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
  409. 0x3d, 0x31,
  410. };
  411. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected3, sizeof(expected3))));
  412. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  413. brpc::HPacker::Header h;
  414. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  415. ASSERT_EQ(header3[i].name, h.name);
  416. ASSERT_EQ(header3[i].value, h.value);
  417. }
  418. ASSERT_TRUE(buf.buf().empty());
  419. }
  420. TEST_F(HPackTest, responses_with_huffman) {
  421. // https://tools.ietf.org/html/rfc7541#appendix-C.5
  422. brpc::HPacker p1;
  423. ASSERT_EQ(0, p1.Init(256));
  424. brpc::HPacker p2;
  425. ASSERT_EQ(0, p2.Init(256));
  426. ConstHeader header1[] = {
  427. {":status", "302"},
  428. {"cache-control", "private"},
  429. {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
  430. {"location", "https://www.example.com"},
  431. };
  432. butil::IOBufAppender buf;
  433. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  434. brpc::HPacker::Header h;
  435. h.name = header1[i].name;
  436. h.value = header1[i].value;
  437. brpc::HPackOptions options;
  438. options.encode_name = true;
  439. options.encode_value = true;
  440. options.index_policy = brpc::HPACK_INDEX_HEADER;
  441. p1.Encode(&buf, h, options);
  442. }
  443. uint8_t expected1[] = {
  444. 0x48, 0x82, 0x64, 0x02, 0x58, 0x85, 0xae, 0xc3, 0x77, 0x1a, 0x4b, 0x61,
  445. 0x96, 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05,
  446. 0x95, 0x04, 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b, 0xff, 0x6e,
  447. 0x91, 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8,
  448. 0xe9, 0xae, 0x82, 0xae, 0x43, 0xd3,
  449. };
  450. LOG(INFO) << butil::ToPrintable(buf.buf());
  451. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected1, sizeof(expected1))));
  452. for (size_t i = 0; i < ARRAY_SIZE(header1); ++i) {
  453. brpc::HPacker::Header h;
  454. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  455. ASSERT_EQ(header1[i].name, h.name);
  456. ASSERT_EQ(header1[i].value, h.value);
  457. }
  458. ASSERT_TRUE(buf.buf().empty());
  459. ConstHeader header2[] = {
  460. {":status", "307"},
  461. {"cache-control", "private"},
  462. {"date", "Mon, 21 Oct 2013 20:13:21 GMT"},
  463. {"location", "https://www.example.com"},
  464. };
  465. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  466. brpc::HPacker::Header h;
  467. h.name = header2[i].name;
  468. h.value = header2[i].value;
  469. brpc::HPackOptions options;
  470. options.encode_name = true;
  471. options.encode_value = true;
  472. options.index_policy = brpc::HPACK_INDEX_HEADER;
  473. p1.Encode(&buf, h, options);
  474. }
  475. uint8_t expected2[] = {
  476. 0x48, 0x83, 0x64, 0x0e, 0xff, 0xc1, 0xc0, 0xbf,
  477. };
  478. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected2, sizeof(expected2))));
  479. for (size_t i = 0; i < ARRAY_SIZE(header2); ++i) {
  480. brpc::HPacker::Header h;
  481. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  482. ASSERT_EQ(header2[i].name, h.name);
  483. ASSERT_EQ(header2[i].value, h.value);
  484. }
  485. ASSERT_TRUE(buf.buf().empty());
  486. ConstHeader header3[] = {
  487. {":status", "200"},
  488. {"cache-control", "private"},
  489. {"date", "Mon, 21 Oct 2013 20:13:22 GMT"},
  490. {"location", "https://www.example.com"},
  491. {"content-encoding", "gzip"},
  492. {"set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
  493. };
  494. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  495. brpc::HPacker::Header h;
  496. h.name = header3[i].name;
  497. h.value = header3[i].value;
  498. brpc::HPackOptions options;
  499. options.encode_name = true;
  500. options.encode_value = true;
  501. options.index_policy = brpc::HPACK_INDEX_HEADER;
  502. p1.Encode(&buf, h, options);
  503. }
  504. uint8_t expected3[] = {
  505. 0x88, 0xc1, 0x61, 0x96, 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44,
  506. 0xa8, 0x20, 0x05, 0x95, 0x04, 0x0b, 0x81, 0x66, 0xe0, 0x84, 0xa6, 0x2d,
  507. 0x1b, 0xff, 0xc0, 0x5a, 0x83, 0x9b, 0xd9, 0xab, 0x77, 0xad, 0x94, 0xe7,
  508. 0x82, 0x1d, 0xd7, 0xf2, 0xe6, 0xc7, 0xb3, 0x35, 0xdf, 0xdf, 0xcd, 0x5b,
  509. 0x39, 0x60, 0xd5, 0xaf, 0x27, 0x08, 0x7f, 0x36, 0x72, 0xc1, 0xab, 0x27,
  510. 0x0f, 0xb5, 0x29, 0x1f, 0x95, 0x87, 0x31, 0x60, 0x65, 0xc0, 0x03, 0xed,
  511. 0x4e, 0xe5, 0xb1, 0x06, 0x3d, 0x50, 0x07,
  512. };
  513. ASSERT_TRUE(buf.buf().equals(butil::StringPiece((char*)expected3, sizeof(expected3))));
  514. for (size_t i = 0; i < ARRAY_SIZE(header3); ++i) {
  515. brpc::HPacker::Header h;
  516. ASSERT_GT(p2.Decode(&buf.buf(), &h), 0);
  517. ASSERT_EQ(header3[i].name, h.name);
  518. ASSERT_EQ(header3[i].value, h.value);
  519. }
  520. ASSERT_TRUE(buf.buf().empty());
  521. }