/src/pistache/include/pistache/http_defs.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * SPDX-FileCopyrightText: 2015 Mathieu Stefani |
3 | | * |
4 | | * SPDX-License-Identifier: Apache-2.0 |
5 | | */ |
6 | | |
7 | | /* http_defs.h |
8 | | Mathieu Stefani, 01 September 2015 |
9 | | |
10 | | Various http definitions |
11 | | */ |
12 | | |
13 | | #pragma once |
14 | | |
15 | | #include <chrono> |
16 | | #include <functional> |
17 | | #include <ostream> |
18 | | #include <stdexcept> |
19 | | #include <string> |
20 | | |
21 | | namespace Pistache::Http |
22 | | { |
23 | | |
24 | | #define HTTP_METHODS \ |
25 | 0 | METHOD(Options, "OPTIONS") \ |
26 | 0 | METHOD(Get, "GET") \ |
27 | 0 | METHOD(Post, "POST") \ |
28 | 0 | METHOD(Head, "HEAD") \ |
29 | 0 | METHOD(Put, "PUT") \ |
30 | 0 | METHOD(Patch, "PATCH") \ |
31 | 0 | METHOD(Delete, "DELETE") \ |
32 | 0 | METHOD(Trace, "TRACE") \ |
33 | 0 | METHOD(Connect, "CONNECT") \ |
34 | 0 | METHOD(Acl, "ACL") \ |
35 | 0 | METHOD(BaselineControl, "BASELINE-CONTROL") \ |
36 | 0 | METHOD(Bind, "BIND") \ |
37 | 0 | METHOD(Checkin, "CHECKIN") \ |
38 | 0 | METHOD(Checkout, "CHECKOUT") \ |
39 | 0 | METHOD(Copy, "COPY") \ |
40 | 0 | METHOD(Label, "LABEL") \ |
41 | 0 | METHOD(Link, "LINK") \ |
42 | 0 | METHOD(Lock, "LOCK") \ |
43 | 0 | METHOD(Merge, "MERGE") \ |
44 | 0 | METHOD(Mkactivity, "MKACTIVITY") \ |
45 | 0 | METHOD(Mkcalendar, "MKCALENDAR") \ |
46 | 0 | METHOD(Mkcol, "MKCOL") \ |
47 | 0 | METHOD(Mkredirectref, "MKREDIRECTREF") \ |
48 | 0 | METHOD(Mkworkspace, "MKWORKSPACE") \ |
49 | 0 | METHOD(Move, "MOVE") \ |
50 | 0 | METHOD(Orderpatch, "ORDERPATCH") \ |
51 | 0 | METHOD(Pri, "PRI") \ |
52 | 0 | METHOD(Propfind, "PROPFIND") \ |
53 | 0 | METHOD(Proppatch, "PROPPATCH") \ |
54 | 0 | METHOD(Rebind, "REBIND") \ |
55 | 0 | METHOD(Report, "REPORT") \ |
56 | 0 | METHOD(Search, "SEARCH") \ |
57 | 0 | METHOD(Unbind, "UNBIND") \ |
58 | 0 | METHOD(Uncheckout, "UNCHECKOUT") \ |
59 | 0 | METHOD(Unlink, "UNLINK") \ |
60 | 0 | METHOD(Unlock, "UNLOCK") \ |
61 | 0 | METHOD(Update, "UPDATE") \ |
62 | 0 | METHOD(Updateredirectref, "UPDATEREDIRECTREF") \ |
63 | 0 | METHOD(VersionControl, "VERSION-CONTROL") |
64 | | |
65 | | // 10. Status Code Definitions |
66 | | #define STATUS_CODES \ |
67 | 0 | CODE(100, Continue, "Continue") \ |
68 | 0 | CODE(101, Switching_Protocols, "Switching Protocols") \ |
69 | 0 | CODE(102, Processing, "Processing") \ |
70 | 0 | CODE(103, Early_Hints, "Early Hints") \ |
71 | 0 | CODE(200, Ok, "OK") \ |
72 | 0 | CODE(201, Created, "Created") \ |
73 | 0 | CODE(202, Accepted, "Accepted") \ |
74 | 0 | CODE(203, NonAuthoritative_Information, "Non-Authoritative Information") \ |
75 | 0 | CODE(204, No_Content, "No Content") \ |
76 | 0 | CODE(205, Reset_Content, "Reset Content") \ |
77 | 0 | CODE(206, Partial_Content, "Partial Content") \ |
78 | 0 | CODE(207, MultiStatus, "Multi-Status") \ |
79 | 0 | CODE(208, Already_Reported, "Already Reported") \ |
80 | 0 | CODE(226, IM_Used, "IM Used") \ |
81 | 0 | CODE(300, Multiple_Choices, "Multiple Choices") \ |
82 | 0 | CODE(301, Moved_Permanently, "Moved Permanently") \ |
83 | 0 | CODE(302, Found, "Found") \ |
84 | 0 | CODE(303, See_Other, "See Other") \ |
85 | 0 | CODE(304, Not_Modified, "Not Modified") \ |
86 | 0 | CODE(305, Use_Proxy, "Use Proxy") \ |
87 | 0 | CODE(307, Temporary_Redirect, "Temporary Redirect") \ |
88 | 0 | CODE(308, Permanent_Redirect, "Permanent Redirect") \ |
89 | 0 | CODE(400, Bad_Request, "Bad Request") \ |
90 | 0 | CODE(401, Unauthorized, "Unauthorized") \ |
91 | 0 | CODE(402, Payment_Required, "Payment Required") \ |
92 | 0 | CODE(403, Forbidden, "Forbidden") \ |
93 | 0 | CODE(404, Not_Found, "Not Found") \ |
94 | 0 | CODE(405, Method_Not_Allowed, "Method Not Allowed") \ |
95 | 0 | CODE(406, Not_Acceptable, "Not Acceptable") \ |
96 | 0 | CODE(407, Proxy_Authentication_Required, "Proxy Authentication Required") \ |
97 | 0 | CODE(408, Request_Timeout, "Request Timeout") \ |
98 | 0 | CODE(409, Conflict, "Conflict") \ |
99 | 0 | CODE(410, Gone, "Gone") \ |
100 | 0 | CODE(411, Length_Required, "Length Required") \ |
101 | 0 | CODE(412, Precondition_Failed, "Precondition Failed") \ |
102 | 0 | CODE(413, Request_Entity_Too_Large, "Request Entity Too Large") \ |
103 | 0 | CODE(414, RequestURI_Too_Long, "Request-URI Too Long") \ |
104 | 0 | CODE(415, Unsupported_Media_Type, "Unsupported Media Type") \ |
105 | 0 | CODE(416, Requested_Range_Not_Satisfiable, \ |
106 | 0 | "Requested Range Not Satisfiable") \ |
107 | 0 | CODE(417, Expectation_Failed, "Expectation Failed") \ |
108 | 0 | CODE(418, I_m_a_teapot, "I'm a teapot") \ |
109 | 0 | CODE(421, Misdirected_Request, "Misdirected Request") \ |
110 | 0 | CODE(422, Unprocessable_Entity, "Unprocessable Entity") \ |
111 | 0 | CODE(423, Locked, "Locked") \ |
112 | 0 | CODE(424, Failed_Dependency, "Failed Dependency") \ |
113 | 0 | CODE(426, Upgrade_Required, "Upgrade Required") \ |
114 | 0 | CODE(428, Precondition_Required, "Precondition Required") \ |
115 | 0 | CODE(429, Too_Many_Requests, "Too Many Requests") \ |
116 | 0 | CODE(431, Request_Header_Fields_Too_Large, \ |
117 | 0 | "Request Header Fields Too Large") \ |
118 | 0 | CODE(444, Connection_Closed_Without_Response, \ |
119 | 0 | "Connection Closed Without Response") \ |
120 | 0 | CODE(451, Unavailable_For_Legal_Reasons, "Unavailable For Legal Reasons") \ |
121 | 0 | CODE(499, Client_Closed_Request, "Client Closed Request") \ |
122 | 0 | CODE(500, Internal_Server_Error, "Internal Server Error") \ |
123 | 0 | CODE(501, Not_Implemented, "Not Implemented") \ |
124 | 0 | CODE(502, Bad_Gateway, "Bad Gateway") \ |
125 | 0 | CODE(503, Service_Unavailable, "Service Unavailable") \ |
126 | 0 | CODE(504, Gateway_Timeout, "Gateway Timeout") \ |
127 | 0 | CODE(505, HTTP_Version_Not_Supported, "HTTP Version Not Supported") \ |
128 | 0 | CODE(506, Variant_Also_Negotiates, "Variant Also Negotiates") \ |
129 | 0 | CODE(507, Insufficient_Storage, "Insufficient Storage") \ |
130 | 0 | CODE(508, Loop_Detected, "Loop Detected") \ |
131 | 0 | CODE(510, Not_Extended, "Not Extended") \ |
132 | 0 | CODE(511, Network_Authentication_Required, \ |
133 | 0 | "Network Authentication Required") \ |
134 | 0 | CODE(599, Network_Connect_Timeout_Error, "Network Connect Timeout Error") |
135 | | |
136 | | // 3.4. Character Sets |
137 | | // See http://tools.ietf.org/html/rfc2978 and |
138 | | // http://www.iana.org/assignments/character-sets/character-sets.xhtml |
139 | | #define CHARSETS \ |
140 | | CHARSET(UsAscii, "us-ascii") \ |
141 | | CHARSET(Iso - 8859 - 1, "iso-8859-1") \ |
142 | | CHARSET(Iso - 8859 - 2, "iso-8859-2") \ |
143 | | CHARSET(Iso - 8859 - 3, "iso-8859-3") \ |
144 | | CHARSET(Iso - 8859 - 4, "iso-8859-4") \ |
145 | | CHARSET(Iso - 8859 - 5, "iso-8859-5") \ |
146 | | CHARSET(Iso - 8859 - 6, "iso-8859-6") \ |
147 | | CHARSET(Iso - 8859 - 7, "iso-8859-7") \ |
148 | | CHARSET(Iso - 8859 - 8, "iso-8859-8") \ |
149 | | CHARSET(Iso - 8859 - 9, "iso-8859-9") \ |
150 | | CHARSET(Iso - 8859 - 10, "iso-8859-10") \ |
151 | | CHARSET(Shift - JIS, "shift_jis") \ |
152 | | CHARSET(Utf7, "utf-7") \ |
153 | | CHARSET(Utf8, "utf-8") \ |
154 | | CHARSET(Utf16, "utf-16") \ |
155 | | CHARSET(Utf16 - BE, "utf-16be") \ |
156 | | CHARSET(Utf16 - LE, "utf-16le") \ |
157 | | CHARSET(Utf32, "utf-32") \ |
158 | | CHARSET(Utf32 - BE, "utf-32be") \ |
159 | | CHARSET(Utf32 - LE, "utf-32le") \ |
160 | | CHARSET(Unicode - 11, "unicode-1-1") |
161 | | |
162 | | enum class Method { |
163 | | #define METHOD(m, _) m, |
164 | | HTTP_METHODS |
165 | | #undef METHOD |
166 | | }; |
167 | | |
168 | | enum class Code { |
169 | | #define CODE(value, name, _) name = value, |
170 | | STATUS_CODES |
171 | | #undef CODE |
172 | | }; |
173 | | |
174 | | enum class Version { |
175 | | Http10, // HTTP/1.0 |
176 | | Http11 // HTTP/1.1 |
177 | | }; |
178 | | |
179 | | enum class ConnectionControl { Close, |
180 | | KeepAlive, |
181 | | Ext }; |
182 | | |
183 | | enum class Expectation { Continue, |
184 | | Ext }; |
185 | | |
186 | | class CacheDirective |
187 | | { |
188 | | public: |
189 | | enum Directive { |
190 | | NoCache, |
191 | | NoStore, |
192 | | MaxAge, |
193 | | MaxStale, |
194 | | MinFresh, |
195 | | NoTransform, |
196 | | OnlyIfCached, |
197 | | Public, |
198 | | Private, |
199 | | MustRevalidate, |
200 | | ProxyRevalidate, |
201 | | SMaxAge, |
202 | | Ext |
203 | | }; |
204 | | |
205 | | CacheDirective() |
206 | | : directive_() |
207 | | , data() |
208 | 0 | { } |
209 | | |
210 | | explicit CacheDirective(Directive directive); |
211 | | CacheDirective(Directive directive, std::chrono::seconds delta); |
212 | | |
213 | 357k | Directive directive() const { return directive_; } |
214 | | std::chrono::seconds delta() const; |
215 | | |
216 | | private: |
217 | | void init(Directive directive, std::chrono::seconds delta); |
218 | | Directive directive_; |
219 | | // Poor way of representing tagged unions in C++ |
220 | | union |
221 | | { |
222 | | uint64_t maxAge; |
223 | | uint64_t sMaxAge; |
224 | | uint64_t maxStale; |
225 | | uint64_t minFresh; |
226 | | } data; |
227 | | }; |
228 | | |
229 | | // 3.3.1 Full Date |
230 | | class FullDate |
231 | | { |
232 | | public: |
233 | | using time_point = std::chrono::system_clock::time_point; |
234 | | FullDate() |
235 | 9.38k | : date_() |
236 | 9.38k | { } |
237 | | |
238 | | enum class Type { RFC1123, |
239 | | RFC850, |
240 | | AscTime, |
241 | | RFC1123GMT }; |
242 | | |
243 | | explicit FullDate(time_point date) |
244 | 6.67k | : date_(date) |
245 | 6.67k | { } |
246 | | |
247 | 0 | time_point date() const { return date_; } |
248 | | void write(std::ostream& os, Type type = Type::RFC1123) const; |
249 | | |
250 | | static FullDate fromString(const std::string& str); |
251 | | |
252 | | private: |
253 | | time_point date_; |
254 | | }; |
255 | | |
256 | | const char* methodString(Method method); |
257 | | const char* versionString(Version version); |
258 | | const char* codeString(Code code); |
259 | | |
260 | | std::ostream& operator<<(std::ostream& os, Version version); |
261 | | std::ostream& operator<<(std::ostream& os, Method method); |
262 | | std::ostream& operator<<(std::ostream& os, Code code); |
263 | | |
264 | | struct HttpError : public std::exception |
265 | | { |
266 | | HttpError(Code code, std::string reason); |
267 | | HttpError(int code, std::string reason); |
268 | | |
269 | 9.71k | ~HttpError() noexcept override = default; |
270 | | |
271 | 0 | const char* what() const noexcept override { return reason_.c_str(); } |
272 | | |
273 | 0 | int code() const { return code_; } |
274 | 0 | std::string reason() const { return reason_; } |
275 | | |
276 | | private: |
277 | | int code_; |
278 | | std::string reason_; |
279 | | }; |
280 | | |
281 | | } // namespace Pistache::Http |
282 | | |
283 | | namespace std |
284 | | { |
285 | | |
286 | | template <> |
287 | | struct hash<Pistache::Http::Method> |
288 | | { |
289 | | size_t operator()(Pistache::Http::Method method) const |
290 | 0 | { |
291 | 0 | return std::hash<int>()(static_cast<int>(method)); |
292 | 0 | } |
293 | | }; |
294 | | |
295 | | } // namespace std |