field.ipp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. //
  2. // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_HTTP_IMPL_FIELD_IPP
  10. #define BOOST_BEAST_HTTP_IMPL_FIELD_IPP
  11. #include <boost/beast/core/string.hpp>
  12. #include <algorithm>
  13. #include <array>
  14. #include <unordered_map>
  15. #include <vector>
  16. #include <boost/assert.hpp>
  17. namespace boost {
  18. namespace beast {
  19. namespace http {
  20. namespace detail {
  21. struct field_table
  22. {
  23. using array_type =
  24. std::array<string_view, 353>;
  25. struct hash
  26. {
  27. std::size_t
  28. operator()(string_view s) const
  29. {
  30. auto const n = s.size();
  31. return
  32. beast::detail::ascii_tolower(s[0]) *
  33. beast::detail::ascii_tolower(s[n/2]) ^
  34. beast::detail::ascii_tolower(s[n-1]); // hist[] = 331, 10, max_load_factor = 0.15f
  35. }
  36. };
  37. struct iequal
  38. {
  39. // assumes inputs have equal length
  40. bool
  41. operator()(
  42. string_view lhs,
  43. string_view rhs) const
  44. {
  45. auto p1 = lhs.data();
  46. auto p2 = rhs.data();
  47. auto pend = lhs.end();
  48. char a, b;
  49. while(p1 < pend)
  50. {
  51. a = *p1++;
  52. b = *p2++;
  53. if(a != b)
  54. goto slow;
  55. }
  56. return true;
  57. while(p1 < pend)
  58. {
  59. slow:
  60. if( beast::detail::ascii_tolower(a) !=
  61. beast::detail::ascii_tolower(b))
  62. return false;
  63. a = *p1++;
  64. b = *p2++;
  65. }
  66. return true;
  67. }
  68. };
  69. using map_type = std::unordered_map<
  70. string_view, field, hash, iequal>;
  71. array_type by_name_;
  72. std::vector<map_type> by_size_;
  73. /*
  74. From:
  75. https://www.iana.org/assignments/message-headers/message-headers.xhtml
  76. */
  77. field_table()
  78. : by_name_({{
  79. "<unknown-field>",
  80. "A-IM",
  81. "Accept",
  82. "Accept-Additions",
  83. "Accept-Charset",
  84. "Accept-Datetime",
  85. "Accept-Encoding",
  86. "Accept-Features",
  87. "Accept-Language",
  88. "Accept-Patch",
  89. "Accept-Post",
  90. "Accept-Ranges",
  91. "Access-Control",
  92. "Access-Control-Allow-Credentials",
  93. "Access-Control-Allow-Headers",
  94. "Access-Control-Allow-Methods",
  95. "Access-Control-Allow-Origin",
  96. "Access-Control-Expose-Headers",
  97. "Access-Control-Max-Age",
  98. "Access-Control-Request-Headers",
  99. "Access-Control-Request-Method",
  100. "Age",
  101. "Allow",
  102. "ALPN",
  103. "Also-Control",
  104. "Alt-Svc",
  105. "Alt-Used",
  106. "Alternate-Recipient",
  107. "Alternates",
  108. "Apparently-To",
  109. "Apply-To-Redirect-Ref",
  110. "Approved",
  111. "Archive",
  112. "Archived-At",
  113. "Article-Names",
  114. "Article-Updates",
  115. "Authentication-Control",
  116. "Authentication-Info",
  117. "Authentication-Results",
  118. "Authorization",
  119. "Auto-Submitted",
  120. "Autoforwarded",
  121. "Autosubmitted",
  122. "Base",
  123. "Bcc",
  124. "Body",
  125. "C-Ext",
  126. "C-Man",
  127. "C-Opt",
  128. "C-PEP",
  129. "C-PEP-Info",
  130. "Cache-Control",
  131. "CalDAV-Timezones",
  132. "Cancel-Key",
  133. "Cancel-Lock",
  134. "Cc",
  135. "Close",
  136. "Comments",
  137. "Compliance",
  138. "Connection",
  139. "Content-Alternative",
  140. "Content-Base",
  141. "Content-Description",
  142. "Content-Disposition",
  143. "Content-Duration",
  144. "Content-Encoding",
  145. "Content-features",
  146. "Content-ID",
  147. "Content-Identifier",
  148. "Content-Language",
  149. "Content-Length",
  150. "Content-Location",
  151. "Content-MD5",
  152. "Content-Range",
  153. "Content-Return",
  154. "Content-Script-Type",
  155. "Content-Style-Type",
  156. "Content-Transfer-Encoding",
  157. "Content-Type",
  158. "Content-Version",
  159. "Control",
  160. "Conversion",
  161. "Conversion-With-Loss",
  162. "Cookie",
  163. "Cookie2",
  164. "Cost",
  165. "DASL",
  166. "Date",
  167. "Date-Received",
  168. "DAV",
  169. "Default-Style",
  170. "Deferred-Delivery",
  171. "Delivery-Date",
  172. "Delta-Base",
  173. "Depth",
  174. "Derived-From",
  175. "Destination",
  176. "Differential-ID",
  177. "Digest",
  178. "Discarded-X400-IPMS-Extensions",
  179. "Discarded-X400-MTS-Extensions",
  180. "Disclose-Recipients",
  181. "Disposition-Notification-Options",
  182. "Disposition-Notification-To",
  183. "Distribution",
  184. "DKIM-Signature",
  185. "DL-Expansion-History",
  186. "Downgraded-Bcc",
  187. "Downgraded-Cc",
  188. "Downgraded-Disposition-Notification-To",
  189. "Downgraded-Final-Recipient",
  190. "Downgraded-From",
  191. "Downgraded-In-Reply-To",
  192. "Downgraded-Mail-From",
  193. "Downgraded-Message-Id",
  194. "Downgraded-Original-Recipient",
  195. "Downgraded-Rcpt-To",
  196. "Downgraded-References",
  197. "Downgraded-Reply-To",
  198. "Downgraded-Resent-Bcc",
  199. "Downgraded-Resent-Cc",
  200. "Downgraded-Resent-From",
  201. "Downgraded-Resent-Reply-To",
  202. "Downgraded-Resent-Sender",
  203. "Downgraded-Resent-To",
  204. "Downgraded-Return-Path",
  205. "Downgraded-Sender",
  206. "Downgraded-To",
  207. "EDIINT-Features",
  208. "Eesst-Version",
  209. "Encoding",
  210. "Encrypted",
  211. "Errors-To",
  212. "ETag",
  213. "Expect",
  214. "Expires",
  215. "Expiry-Date",
  216. "Ext",
  217. "Followup-To",
  218. "Forwarded",
  219. "From",
  220. "Generate-Delivery-Report",
  221. "GetProfile",
  222. "Hobareg",
  223. "Host",
  224. "HTTP2-Settings",
  225. "If",
  226. "If-Match",
  227. "If-Modified-Since",
  228. "If-None-Match",
  229. "If-Range",
  230. "If-Schedule-Tag-Match",
  231. "If-Unmodified-Since",
  232. "IM",
  233. "Importance",
  234. "In-Reply-To",
  235. "Incomplete-Copy",
  236. "Injection-Date",
  237. "Injection-Info",
  238. "Jabber-ID",
  239. "Keep-Alive",
  240. "Keywords",
  241. "Label",
  242. "Language",
  243. "Last-Modified",
  244. "Latest-Delivery-Time",
  245. "Lines",
  246. "Link",
  247. "List-Archive",
  248. "List-Help",
  249. "List-ID",
  250. "List-Owner",
  251. "List-Post",
  252. "List-Subscribe",
  253. "List-Unsubscribe",
  254. "List-Unsubscribe-Post",
  255. "Location",
  256. "Lock-Token",
  257. "Man",
  258. "Max-Forwards",
  259. "Memento-Datetime",
  260. "Message-Context",
  261. "Message-ID",
  262. "Message-Type",
  263. "Meter",
  264. "Method-Check",
  265. "Method-Check-Expires",
  266. "MIME-Version",
  267. "MMHS-Acp127-Message-Identifier",
  268. "MMHS-Authorizing-Users",
  269. "MMHS-Codress-Message-Indicator",
  270. "MMHS-Copy-Precedence",
  271. "MMHS-Exempted-Address",
  272. "MMHS-Extended-Authorisation-Info",
  273. "MMHS-Handling-Instructions",
  274. "MMHS-Message-Instructions",
  275. "MMHS-Message-Type",
  276. "MMHS-Originator-PLAD",
  277. "MMHS-Originator-Reference",
  278. "MMHS-Other-Recipients-Indicator-CC",
  279. "MMHS-Other-Recipients-Indicator-To",
  280. "MMHS-Primary-Precedence",
  281. "MMHS-Subject-Indicator-Codes",
  282. "MT-Priority",
  283. "Negotiate",
  284. "Newsgroups",
  285. "NNTP-Posting-Date",
  286. "NNTP-Posting-Host",
  287. "Non-Compliance",
  288. "Obsoletes",
  289. "Opt",
  290. "Optional",
  291. "Optional-WWW-Authenticate",
  292. "Ordering-Type",
  293. "Organization",
  294. "Origin",
  295. "Original-Encoded-Information-Types",
  296. "Original-From",
  297. "Original-Message-ID",
  298. "Original-Recipient",
  299. "Original-Sender",
  300. "Original-Subject",
  301. "Originator-Return-Address",
  302. "Overwrite",
  303. "P3P",
  304. "Path",
  305. "PEP",
  306. "Pep-Info",
  307. "PICS-Label",
  308. "Position",
  309. "Posting-Version",
  310. "Pragma",
  311. "Prefer",
  312. "Preference-Applied",
  313. "Prevent-NonDelivery-Report",
  314. "Priority",
  315. "Privicon",
  316. "ProfileObject",
  317. "Protocol",
  318. "Protocol-Info",
  319. "Protocol-Query",
  320. "Protocol-Request",
  321. "Proxy-Authenticate",
  322. "Proxy-Authentication-Info",
  323. "Proxy-Authorization",
  324. "Proxy-Connection",
  325. "Proxy-Features",
  326. "Proxy-Instruction",
  327. "Public",
  328. "Public-Key-Pins",
  329. "Public-Key-Pins-Report-Only",
  330. "Range",
  331. "Received",
  332. "Received-SPF",
  333. "Redirect-Ref",
  334. "References",
  335. "Referer",
  336. "Referer-Root",
  337. "Relay-Version",
  338. "Reply-By",
  339. "Reply-To",
  340. "Require-Recipient-Valid-Since",
  341. "Resent-Bcc",
  342. "Resent-Cc",
  343. "Resent-Date",
  344. "Resent-From",
  345. "Resent-Message-ID",
  346. "Resent-Reply-To",
  347. "Resent-Sender",
  348. "Resent-To",
  349. "Resolution-Hint",
  350. "Resolver-Location",
  351. "Retry-After",
  352. "Return-Path",
  353. "Safe",
  354. "Schedule-Reply",
  355. "Schedule-Tag",
  356. "Sec-WebSocket-Accept",
  357. "Sec-WebSocket-Extensions",
  358. "Sec-WebSocket-Key",
  359. "Sec-WebSocket-Protocol",
  360. "Sec-WebSocket-Version",
  361. "Security-Scheme",
  362. "See-Also",
  363. "Sender",
  364. "Sensitivity",
  365. "Server",
  366. "Set-Cookie",
  367. "Set-Cookie2",
  368. "SetProfile",
  369. "SIO-Label",
  370. "SIO-Label-History",
  371. "SLUG",
  372. "SoapAction",
  373. "Solicitation",
  374. "Status-URI",
  375. "Strict-Transport-Security",
  376. "Subject",
  377. "SubOK",
  378. "Subst",
  379. "Summary",
  380. "Supersedes",
  381. "Surrogate-Capability",
  382. "Surrogate-Control",
  383. "TCN",
  384. "TE",
  385. "Timeout",
  386. "Title",
  387. "To",
  388. "Topic",
  389. "Trailer",
  390. "Transfer-Encoding",
  391. "TTL",
  392. "UA-Color",
  393. "UA-Media",
  394. "UA-Pixels",
  395. "UA-Resolution",
  396. "UA-Windowpixels",
  397. "Upgrade",
  398. "Urgency",
  399. "URI",
  400. "User-Agent",
  401. "Variant-Vary",
  402. "Vary",
  403. "VBR-Info",
  404. "Version",
  405. "Via",
  406. "Want-Digest",
  407. "Warning",
  408. "WWW-Authenticate",
  409. "X-Archived-At",
  410. "X-Device-Accept",
  411. "X-Device-Accept-Charset",
  412. "X-Device-Accept-Encoding",
  413. "X-Device-Accept-Language",
  414. "X-Device-User-Agent",
  415. "X-Frame-Options",
  416. "X-Mittente",
  417. "X-PGP-Sig",
  418. "X-Ricevuta",
  419. "X-Riferimento-Message-ID",
  420. "X-TipoRicevuta",
  421. "X-Trasporto",
  422. "X-VerificaSicurezza",
  423. "X400-Content-Identifier",
  424. "X400-Content-Return",
  425. "X400-Content-Type",
  426. "X400-MTS-Identifier",
  427. "X400-Originator",
  428. "X400-Received",
  429. "X400-Recipients",
  430. "X400-Trace",
  431. "Xref"
  432. }})
  433. {
  434. // find the longest field length
  435. std::size_t high = 0;
  436. for(auto const& s : by_name_)
  437. if(high < s.size())
  438. high = s.size();
  439. // build by_size map
  440. // skip field::unknown
  441. by_size_.resize(high + 1);
  442. for(auto& map : by_size_)
  443. map.max_load_factor(.15f);
  444. for(std::size_t i = 1;
  445. i < by_name_.size(); ++i)
  446. {
  447. auto const& s = by_name_[i];
  448. by_size_[s.size()].emplace(
  449. s, static_cast<field>(i));
  450. }
  451. #if 0
  452. // This snippet calculates the performance
  453. // of the hash function and map settings
  454. {
  455. std::vector<std::size_t> hist;
  456. for(auto const& map : by_size_)
  457. {
  458. for(std::size_t i = 0; i < map.bucket_count(); ++i)
  459. {
  460. auto const n = map.bucket_size(i);
  461. if(n > 0)
  462. {
  463. if(hist.size() < n)
  464. hist.resize(n);
  465. ++hist[n-1];
  466. }
  467. }
  468. }
  469. }
  470. #endif
  471. }
  472. field
  473. string_to_field(string_view s) const
  474. {
  475. if(s.size() >= by_size_.size())
  476. return field::unknown;
  477. auto const& map = by_size_[s.size()];
  478. if(map.empty())
  479. return field::unknown;
  480. auto it = map.find(s);
  481. if(it == map.end())
  482. return field::unknown;
  483. return it->second;
  484. }
  485. //
  486. // Deprecated
  487. //
  488. using const_iterator =
  489. array_type::const_iterator;
  490. std::size_t
  491. size() const
  492. {
  493. return by_name_.size();
  494. }
  495. const_iterator
  496. begin() const
  497. {
  498. return by_name_.begin();
  499. }
  500. const_iterator
  501. end() const
  502. {
  503. return by_name_.end();
  504. }
  505. };
  506. inline
  507. field_table const&
  508. get_field_table()
  509. {
  510. static field_table const tab;
  511. return tab;
  512. }
  513. template<class = void>
  514. string_view
  515. to_string(field f)
  516. {
  517. auto const& v = get_field_table();
  518. BOOST_ASSERT(static_cast<unsigned>(f) < v.size());
  519. return v.begin()[static_cast<unsigned>(f)];
  520. }
  521. } // detail
  522. inline
  523. string_view
  524. to_string(field f)
  525. {
  526. return detail::to_string(f);
  527. }
  528. inline
  529. field
  530. string_to_field(string_view s)
  531. {
  532. return detail::get_field_table().string_to_field(s);
  533. }
  534. } // http
  535. } // beast
  536. } // boost
  537. #endif