Http.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /***************************************************************************
  2. *
  3. * Project _____ __ ____ _ _
  4. * ( _ ) /__\ (_ _)_| |_ _| |_
  5. * )(_)( /(__)\ )( (_ _)(_ _)
  6. * (_____)(__)(__)(__) |_| |_|
  7. *
  8. *
  9. * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ***************************************************************************/
  24. #ifndef oatpp_web_protocol_http_Http_hpp
  25. #define oatpp_web_protocol_http_Http_hpp
  26. #include "oatpp/network/tcp/Connection.hpp"
  27. #include "oatpp/web/protocol/CommunicationError.hpp"
  28. #include "oatpp/core/parser/Caret.hpp"
  29. #include "oatpp/core/data/share/LazyStringMap.hpp"
  30. #include "oatpp/core/Types.hpp"
  31. #include <unordered_map>
  32. #include <unordered_set>
  33. namespace oatpp { namespace web { namespace protocol { namespace http {
  34. /**
  35. * Typedef for headers map. Headers map key is case-insensitive.
  36. * For more info see &id:oatpp::data::share::LazyStringMultimap;.
  37. */
  38. typedef oatpp::data::share::LazyStringMultimap<oatpp::data::share::StringKeyLabelCI> Headers;
  39. /**
  40. * Typedef for query parameters map.
  41. * For more info see &id:oatpp::data::share::LazyStringMultimap;.
  42. */
  43. typedef oatpp::data::share::LazyStringMultimap<oatpp::data::share::StringKeyLabel> QueryParams;
  44. /**
  45. * Http status.
  46. */
  47. class Status{
  48. public:
  49. /**
  50. * Continue.
  51. */
  52. static const Status CODE_100;// Continue
  53. /**
  54. * Switching Protocols.
  55. */
  56. static const Status CODE_101;// Switching
  57. /**
  58. * Processing.
  59. */
  60. static const Status CODE_102;// Processing
  61. /**
  62. * OK.
  63. */
  64. static const Status CODE_200;// OK
  65. /**
  66. * Created.
  67. */
  68. static const Status CODE_201;// Created
  69. /**
  70. * Accepted.
  71. */
  72. static const Status CODE_202;// Accepted
  73. /**
  74. * Non-Authoritative Information.
  75. */
  76. static const Status CODE_203;// Non-Authoritative Information
  77. /**
  78. * No Content.
  79. */
  80. static const Status CODE_204;// No Content
  81. /**
  82. * Reset Content.
  83. */
  84. static const Status CODE_205;// Reset Content
  85. /**
  86. * Partial Content.
  87. */
  88. static const Status CODE_206;// Partial Content
  89. /**
  90. * Multi-Status.
  91. */
  92. static const Status CODE_207;// Multi-Status
  93. /**
  94. * IM Used.
  95. */
  96. static const Status CODE_226;// IM Used
  97. /**
  98. * Multiple Choices.
  99. */
  100. static const Status CODE_300;// Multiple Choices
  101. /**
  102. * Moved Permanently.
  103. */
  104. static const Status CODE_301;// Moved Permanently
  105. /**
  106. * Moved Temporarily.
  107. */
  108. static const Status CODE_302;// Moved Temporarily
  109. /**
  110. * See Other.
  111. */
  112. static const Status CODE_303;// See Other
  113. /**
  114. * Not Modified.
  115. */
  116. static const Status CODE_304;// Not Modified
  117. /**
  118. * Use Proxy.
  119. */
  120. static const Status CODE_305;// Use Proxy
  121. /**
  122. * Reserved.
  123. */
  124. static const Status CODE_306;// Reserved
  125. /**
  126. * Temporary Redirect.
  127. */
  128. static const Status CODE_307;// Temporary Redirect
  129. /**
  130. * Bad Request.
  131. */
  132. static const Status CODE_400;// Bad Request
  133. /**
  134. * Unauthorized.
  135. */
  136. static const Status CODE_401;// Unauthorized
  137. /**
  138. * Payment Required.
  139. */
  140. static const Status CODE_402;// Payment Required
  141. /**
  142. * Forbidden.
  143. */
  144. static const Status CODE_403;// Forbidden
  145. /**
  146. * Not Found.
  147. */
  148. static const Status CODE_404;// Not Found
  149. /**
  150. * Method Not Allowed.
  151. */
  152. static const Status CODE_405;// Method Not Allowed
  153. /**
  154. * Not Acceptable.
  155. */
  156. static const Status CODE_406;// Not Acceptable
  157. /**
  158. * Proxy Authentication Required.
  159. */
  160. static const Status CODE_407;// Proxy Authentication Required
  161. /**
  162. * Request Timeout.
  163. */
  164. static const Status CODE_408;// Request Timeout
  165. /**
  166. * Conflict.
  167. */
  168. static const Status CODE_409;// Conflict
  169. /**
  170. * Gone
  171. */
  172. static const Status CODE_410;// Gone
  173. /**
  174. * Length Required.
  175. */
  176. static const Status CODE_411;// Length Required
  177. /**
  178. * Precondition Failed.
  179. */
  180. static const Status CODE_412;// Precondition Failed
  181. /**
  182. * Request Entity Too Large.
  183. */
  184. static const Status CODE_413;// Request Entity Too Large
  185. /**
  186. * Request-URI Too Large.
  187. */
  188. static const Status CODE_414;// Request-URI Too Large
  189. /**
  190. * Unsupported Media Type.
  191. */
  192. static const Status CODE_415;// Unsupported Media Type
  193. /**
  194. * Requested Range Not Satisfiable.
  195. */
  196. static const Status CODE_416;// Requested Range Not Satisfiable
  197. /**
  198. * Expectation Failed.
  199. */
  200. static const Status CODE_417;// Expectation Failed
  201. /**
  202. * I'm a Teapot (rfc7168 2.3.3)
  203. */
  204. static const Status CODE_418;// I'm a teapot
  205. /**
  206. * Unprocessable Entity.
  207. */
  208. static const Status CODE_422;// Unprocessable Entity
  209. /**
  210. * Locked.
  211. */
  212. static const Status CODE_423;// Locked
  213. /**
  214. * Failed Dependency.
  215. */
  216. static const Status CODE_424;// Failed Dependency
  217. /**
  218. * Unordered Collection.
  219. */
  220. static const Status CODE_425;// Unordered Collection
  221. /**
  222. * Upgrade Required.
  223. */
  224. static const Status CODE_426;// Upgrade Required
  225. /**
  226. * Precondition Required.
  227. */
  228. static const Status CODE_428;// Precondition Required
  229. /**
  230. * Too Many Requests.
  231. */
  232. static const Status CODE_429;// Too Many Requests
  233. /**
  234. * Request Header Fields Too Large.
  235. */
  236. static const Status CODE_431;// Request Header Fields Too Large
  237. /**
  238. * Requested host unavailable.
  239. */
  240. static const Status CODE_434;// Requested host unavailable
  241. /**
  242. * Close connection withot sending headers.
  243. */
  244. static const Status CODE_444;// Close connection withot sending headers
  245. /**
  246. * Retry With.
  247. */
  248. static const Status CODE_449;// Retry With
  249. /**
  250. * Unavailable For Legal Reasons.
  251. */
  252. static const Status CODE_451;// Unavailable For Legal Reasons
  253. /**
  254. * Internal Server Error.
  255. */
  256. static const Status CODE_500;// Internal Server Error
  257. /**
  258. * Not Implemented.
  259. */
  260. static const Status CODE_501;// Not Implemented
  261. /**
  262. * Bad Gateway.
  263. */
  264. static const Status CODE_502;// Bad Gateway
  265. /**
  266. * Service Unavailable.
  267. */
  268. static const Status CODE_503;// Service Unavailable
  269. /**
  270. * Gateway Timeout.
  271. */
  272. static const Status CODE_504;// Gateway Timeout
  273. /**
  274. * HTTP Version Not Supported.
  275. */
  276. static const Status CODE_505;// HTTP Version Not Supported
  277. /**
  278. * Variant Also Negotiates.
  279. */
  280. static const Status CODE_506;// Variant Also Negotiates
  281. /**
  282. * Insufficient Storage.
  283. */
  284. static const Status CODE_507;// Insufficient Storage
  285. /**
  286. * Loop Detected.
  287. */
  288. static const Status CODE_508;// Loop Detected
  289. /**
  290. * Bandwidth Limit Exceeded.
  291. */
  292. static const Status CODE_509;// Bandwidth Limit Exceeded
  293. /**
  294. * Not Extended.
  295. */
  296. static const Status CODE_510;// Not Extended
  297. /**
  298. * Network Authentication Required.
  299. */
  300. static const Status CODE_511;// Network Authentication Required
  301. /**
  302. * Constructor.
  303. */
  304. Status()
  305. : code(0)
  306. , description(nullptr)
  307. {}
  308. /**
  309. * Constructor.
  310. * @param pCode - status code.
  311. * @param pDesc - description.
  312. */
  313. Status(v_int32 pCode, const char* pDesc)
  314. : code(pCode)
  315. , description(pDesc)
  316. {}
  317. /**
  318. * Status code.
  319. */
  320. v_int32 code;
  321. /**
  322. * Description.
  323. */
  324. const char* description;
  325. bool operator==(const Status& other) const {
  326. return this->code == other.code;
  327. }
  328. bool operator!=(const Status& other) const {
  329. return this->code != other.code;
  330. }
  331. };
  332. /**
  333. * HttpError extends &id:oatpp::web::protocol::ProtocolError;<&l:Status;>.
  334. */
  335. class HttpError : public protocol::ProtocolError<Status> {
  336. private:
  337. Headers m_headers;
  338. public:
  339. /**
  340. * Constructor.
  341. * @param info
  342. * @param message
  343. */
  344. HttpError(const Info& info, const oatpp::String& message)
  345. : protocol::ProtocolError<Status>(info, message)
  346. {}
  347. /**
  348. * Constructor.
  349. * @param status
  350. * @param message
  351. */
  352. HttpError(const Status& status, const oatpp::String& message)
  353. : protocol::ProtocolError<Status>(Info(0, status), message)
  354. {}
  355. /**
  356. * Constructor.
  357. * @param status
  358. * @param message
  359. * @param headers
  360. */
  361. HttpError(const Status& status, const oatpp::String& message, const Headers& headers)
  362. : protocol::ProtocolError<Status>(Info(0, status), message)
  363. , m_headers(headers)
  364. {}
  365. /**
  366. * Get headers
  367. * @return
  368. */
  369. const Headers& getHeaders() const {
  370. return m_headers;
  371. }
  372. };
  373. /**
  374. * Throw &l:HttpError; if assertion failed.
  375. * @param COND - boolean statement. If evaluates to false - throw error.
  376. * @param STATUS - &l:Status;.
  377. * @param MESSAGE - String message.
  378. */
  379. #define OATPP_ASSERT_HTTP(COND, STATUS, MESSAGE) \
  380. if(!(COND)) { throw oatpp::web::protocol::http::HttpError(STATUS, MESSAGE); }
  381. /**
  382. * Collection of HTTP Header constants.
  383. */
  384. class Header {
  385. public:
  386. /**
  387. * Possible values for headers.
  388. */
  389. class Value {
  390. public:
  391. static const char* const CONNECTION_CLOSE;
  392. static const char* const CONNECTION_KEEP_ALIVE;
  393. static const char* const CONNECTION_UPGRADE;
  394. static const char* const SERVER;
  395. static const char* const USER_AGENT;
  396. static const char* const TRANSFER_ENCODING_CHUNKED;
  397. static const char* const CONTENT_TYPE_APPLICATION_JSON;
  398. static const char* const EXPECT_100_CONTINUE;
  399. };
  400. public:
  401. static const char* const ACCEPT; // "Accept"
  402. static const char* const AUTHORIZATION; // "Authorization"
  403. static const char* const WWW_AUTHENTICATE; // "WWW-Authenticate"
  404. static const char* const CONNECTION; // "Connection"
  405. static const char* const TRANSFER_ENCODING; // "Transfer-Encoding"
  406. static const char* const CONTENT_ENCODING; // "Content-Encoding"
  407. static const char* const CONTENT_LENGTH; // "Content-Length"
  408. static const char* const CONTENT_TYPE; // "Content-Type"
  409. static const char* const CONTENT_RANGE; // "Content-Range"
  410. static const char* const RANGE; // "Range"
  411. static const char* const HOST; // "Host"
  412. static const char* const USER_AGENT; // "User-Agent"
  413. static const char* const SERVER; // "Server"
  414. static const char* const UPGRADE; // "Upgrade"
  415. static const char* const CORS_ORIGIN; // Access-Control-Allow-Origin
  416. static const char* const CORS_METHODS; // Access-Control-Allow-Methods
  417. static const char* const CORS_HEADERS; // Access-Control-Allow-Headers
  418. static const char* const CORS_MAX_AGE; // Access-Control-Max-Age
  419. static const char* const ACCEPT_ENCODING; // Accept-Encoding
  420. static const char* const EXPECT; // Expect
  421. };
  422. class Range {
  423. public:
  424. static const char* const UNIT_BYTES;
  425. private:
  426. Range()
  427. : units(nullptr)
  428. {}
  429. public:
  430. Range(const oatpp::String& pUnits,
  431. v_int64 pStart,
  432. v_int64 pEnd)
  433. : units(pUnits)
  434. , start(pStart)
  435. , end(pEnd)
  436. {}
  437. oatpp::String units;
  438. v_int64 start;
  439. v_int64 end;
  440. oatpp::String toString() const;
  441. bool isValid() const {
  442. return units.get() != nullptr;
  443. }
  444. static Range parse(oatpp::parser::Caret& caret);
  445. static Range parse(const oatpp::String& str);
  446. };
  447. class ContentRange {
  448. public:
  449. static const char* const UNIT_BYTES;
  450. private:
  451. ContentRange()
  452. : units(nullptr)
  453. {}
  454. public:
  455. ContentRange(const oatpp::String& pUnits,
  456. v_int64 pStart,
  457. v_int64 pEnd,
  458. v_int64 pSize,
  459. bool pIsSizeKnown)
  460. : units(pUnits)
  461. , start(pStart)
  462. , end(pEnd)
  463. , size(pSize)
  464. , isSizeKnown(pIsSizeKnown)
  465. {}
  466. oatpp::String units;
  467. v_int64 start;
  468. v_int64 end;
  469. v_int64 size;
  470. bool isSizeKnown;
  471. oatpp::String toString() const;
  472. bool isValid() const {
  473. return units.get() != nullptr;
  474. }
  475. static ContentRange parse(oatpp::parser::Caret& caret);
  476. static ContentRange parse(const oatpp::String& str);
  477. };
  478. /**
  479. * Struct representing HTTP request starting line.
  480. * Example request starting line: `GET /path/to/resource/ HTTP/1.1`.
  481. */
  482. struct RequestStartingLine {
  483. /**
  484. * Method as &id:oatpp::data::share::StringKeyLabel;.
  485. */
  486. oatpp::data::share::StringKeyLabel method; // GET, POST ...
  487. /**
  488. * Path as &id:oatpp::data::share::StringKeyLabel;.
  489. */
  490. oatpp::data::share::StringKeyLabel path;
  491. /**
  492. * Protocol as &id:oatpp::data::share::StringKeyLabel;.
  493. */
  494. oatpp::data::share::StringKeyLabel protocol;
  495. };
  496. /**
  497. * Struct representing HTTP response starting line.
  498. * Example response starting line: `HTTP/1.1 200 OK`.
  499. */
  500. struct ResponseStartingLine {
  501. /**
  502. * Protocol as &id:oatpp::data::share::StringKeyLabel;.
  503. */
  504. oatpp::data::share::StringKeyLabel protocol;
  505. /**
  506. * Status code as v_int32.
  507. */
  508. v_int32 statusCode;
  509. /**
  510. * Description as &id:oatpp::data::share::StringKeyLabel;.
  511. */
  512. oatpp::data::share::StringKeyLabel description;
  513. };
  514. /**
  515. * Data contained in the value of one header.
  516. */
  517. struct HeaderValueData {
  518. /**
  519. * value tokens.
  520. */
  521. std::unordered_set<data::share::StringKeyLabelCI> tokens;
  522. /**
  523. * Title params.
  524. */
  525. std::unordered_map<data::share::StringKeyLabelCI, data::share::StringKeyLabel> titleParams;
  526. /**
  527. * Get title parm value by key.
  528. * @param key
  529. * @return
  530. */
  531. oatpp::String getTitleParamValue(const data::share::StringKeyLabelCI& key) const;
  532. };
  533. /**
  534. * Oatpp Http parser.
  535. */
  536. class Parser {
  537. private:
  538. static oatpp::data::share::StringKeyLabelCI parseHeaderNameLabel(const std::shared_ptr<std::string>& headersText,
  539. oatpp::parser::Caret& caret);
  540. public:
  541. /**
  542. * Parse &l:RequestStartingLine;.
  543. * @param line - &l:RequestStartingLine;. Values will be set to line's fields.
  544. * @param headersText - `std::shared_ptr` to `std::string` needed as a "memory handle" for
  545. * &l:RequestStartingLine; fields. See &id:oatpp::data::share::MemoryLabel;.
  546. * @param caret - &id:oatpp::parser::Caret;.
  547. * @param error - out parameter &l:Status;.
  548. */
  549. static void parseRequestStartingLine(RequestStartingLine& line,
  550. const std::shared_ptr<std::string>& headersText,
  551. oatpp::parser::Caret& caret,
  552. Status& error);
  553. /**
  554. * Parse &l:ResponseStartingLine;.
  555. * @param line - &l:ResponseStartingLine;. Values will be set to line's fields.
  556. * @param headersText - `std::shared_ptr` to `std::string` needed as a "memory handle" for
  557. * &l:ResponseStartingLine; fields. See &id:oatpp::data::share::MemoryLabel;.
  558. * @param caret - &id:oatpp::parser::Caret;.
  559. * @param error - out parameter &l:Status;.
  560. */
  561. static void parseResponseStartingLine(ResponseStartingLine& line,
  562. const std::shared_ptr<std::string>& headersText,
  563. oatpp::parser::Caret& caret,
  564. Status& error);
  565. /**
  566. * Parse one header line. Example of the header line:
  567. * `"Content-Type: application/json\r\n"`.
  568. * @param headers - &l:Headers; map to put parsed header to.
  569. * @param headersText - `std::shared_ptr` to `std::string` needed as a "memory handle" for
  570. * &l:Headers; values. See &id:oatpp::data::share::MemoryLabel;.
  571. * @param caret - &id:oatpp::parser::Caret;.
  572. * @param error - out parameter &l:Status;.
  573. */
  574. static void parseOneHeader(Headers& headers,
  575. const std::shared_ptr<std::string>& headersText,
  576. oatpp::parser::Caret& caret,
  577. Status& error);
  578. /**
  579. * Parse HTTP headers to &l:Headers; map.
  580. * @param headers - &l:Headers; map to put parsed headers to.
  581. * @param headersText - `std::shared_ptr` to `std::string` needed as a "memory handle" for
  582. * &l:Headers; values. See &id:oatpp::data::share::MemoryLabel;.
  583. * @param caret - &id:oatpp::parser::Caret;.
  584. * @param error - out parameter &l:Status;.
  585. */
  586. static void parseHeaders(Headers& headers,
  587. const std::shared_ptr<std::string>& headersText,
  588. oatpp::parser::Caret& caret,
  589. Status& error);
  590. /**
  591. * Parse data that is contained in a one header.
  592. * @param data - out. parsed data.
  593. * @param headerValue - header value string.
  594. * @param separator - subvalues separator.
  595. */
  596. static void parseHeaderValueData(HeaderValueData& data, const oatpp::data::share::StringKeyLabel& headerValue, char separator);
  597. };
  598. /**
  599. * Http utils.
  600. */
  601. class Utils {
  602. public:
  603. /**
  604. * Write headers map to stream.
  605. * @param headers
  606. * @param stream
  607. */
  608. static void writeHeaders(const Headers& headers, data::stream::ConsistentOutputStream* stream);
  609. };
  610. }}}}
  611. namespace std {
  612. template<>
  613. struct hash<oatpp::web::protocol::http::Status> {
  614. typedef oatpp::web::protocol::http::Status argument_type;
  615. typedef v_uint64 result_type;
  616. result_type operator()(oatpp::web::protocol::http::Status const& s) const noexcept {
  617. return s.code;
  618. }
  619. };
  620. }
  621. #endif /* oatpp_web_protocol_http_Http_hpp */