blob: 46742a0ce63f6e9ad6d57d6c70c4768857fef232 [file] [log] [blame]
Ed Tanous9bd21fc2018-04-26 16:08:56 -07001#pragma once
Tanousf00032d2018-11-05 01:18:10 -03002
Ed Tanous11ba3972022-07-11 09:50:41 -07003#include <boost/algorithm/string/classification.hpp>
Nan Zhoud5c80ad2022-07-11 01:16:31 +00004#include <boost/algorithm/string/constants.hpp>
Ed Tanous11ba3972022-07-11 09:50:41 -07005#include <boost/algorithm/string/split.hpp>
Nan Zhoud5c80ad2022-07-11 01:16:31 +00006#include <boost/iterator/iterator_facade.hpp>
7#include <boost/type_index/type_index_facade.hpp>
8
9#include <cctype>
10#include <iomanip>
11#include <ostream>
12#include <string>
13#include <string_view>
14#include <vector>
15
16// IWYU pragma: no_include <ctype.h>
17// IWYU pragma: no_include <boost/algorithm/string/detail/classification.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050018
Ed Tanous1abe55e2018-09-05 08:30:59 -070019namespace http_helpers
20{
George Liu647b3cd2021-07-05 12:43:56 +080021inline std::vector<std::string> parseAccept(std::string_view header)
Ed Tanous1abe55e2018-09-05 08:30:59 -070022{
Ed Tanous753d0342021-07-01 07:57:30 -070023 std::vector<std::string> encodings;
24 // chrome currently sends 6 accepts headers, firefox sends 4.
25 encodings.reserve(6);
26 boost::split(encodings, header, boost::is_any_of(", "),
27 boost::token_compress_on);
George Liu647b3cd2021-07-05 12:43:56 +080028
29 return encodings;
30}
31
32inline bool requestPrefersHtml(std::string_view header)
33{
34 for (const std::string& encoding : parseAccept(header))
Ed Tanous1abe55e2018-09-05 08:30:59 -070035 {
Ed Tanous753d0342021-07-01 07:57:30 -070036 if (encoding == "text/html")
Ed Tanous1abe55e2018-09-05 08:30:59 -070037 {
38 return true;
39 }
Ed Tanous753d0342021-07-01 07:57:30 -070040 if (encoding == "application/json")
Ed Tanous1abe55e2018-09-05 08:30:59 -070041 {
42 return false;
43 }
Ed Tanous9bd21fc2018-04-26 16:08:56 -070044 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070045 return false;
Ed Tanous9bd21fc2018-04-26 16:08:56 -070046}
Ed Tanous6b5e77d2018-11-16 14:52:56 -080047
George Liu647b3cd2021-07-05 12:43:56 +080048inline bool isOctetAccepted(std::string_view header)
49{
50 for (const std::string& encoding : parseAccept(header))
51 {
52 if (encoding == "*/*" || encoding == "application/octet-stream")
53 {
54 return true;
55 }
56 }
57 return false;
58}
59
Ed Tanous39e77502019-03-04 17:35:53 -080060inline std::string urlEncode(const std::string_view value)
Ed Tanous6b5e77d2018-11-16 14:52:56 -080061{
62 std::ostringstream escaped;
63 escaped.fill('0');
64 escaped << std::hex;
65
66 for (const char c : value)
67 {
68 // Keep alphanumeric and other accepted characters intact
Ed Tanouse662eae2022-01-25 10:39:19 -080069 if ((isalnum(c) != 0) || c == '-' || c == '_' || c == '.' || c == '~')
Ed Tanous6b5e77d2018-11-16 14:52:56 -080070 {
71 escaped << c;
72 continue;
73 }
74
75 // Any other characters are percent-encoded
76 escaped << std::uppercase;
77 escaped << '%' << std::setw(2)
78 << static_cast<int>(static_cast<unsigned char>(c));
79 escaped << std::nouppercase;
80 }
81
82 return escaped.str();
83}
Ed Tanous23a21a12020-07-25 04:45:05 +000084} // namespace http_helpers