Http.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  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. #include "./Http.hpp"
  25. #include "oatpp/core/data/stream/BufferStream.hpp"
  26. #include "oatpp/core/utils/ConversionUtils.hpp"
  27. namespace oatpp { namespace web { namespace protocol { namespace http {
  28. const Status Status::CODE_100(100, "Continue");
  29. const Status Status::CODE_101(101, "Switching");
  30. const Status Status::CODE_102(102, "Processing");
  31. const Status Status::CODE_200(200, "OK");
  32. const Status Status::CODE_201(201, "Created");
  33. const Status Status::CODE_202(202, "Accepted");
  34. const Status Status::CODE_203(203, "Non-Authoritative Information");
  35. const Status Status::CODE_204(204, "No Content");
  36. const Status Status::CODE_205(205, "Reset Content");
  37. const Status Status::CODE_206(206, "Partial Content");
  38. const Status Status::CODE_207(207, "Multi-Status");
  39. const Status Status::CODE_226(226, "IM Used");
  40. const Status Status::CODE_300(300, "Multiple Choices");
  41. const Status Status::CODE_301(301, "Moved Permanently");
  42. const Status Status::CODE_302(302, "Moved Temporarily");
  43. const Status Status::CODE_303(303, "See Other");
  44. const Status Status::CODE_304(304, "Not Modified");
  45. const Status Status::CODE_305(305, "Use Proxy");
  46. const Status Status::CODE_306(306, "Reserved");
  47. const Status Status::CODE_307(307, "Temporary Redirect");
  48. const Status Status::CODE_400(400, "Bad Request");
  49. const Status Status::CODE_401(401, "Unauthorized");
  50. const Status Status::CODE_402(402, "Payment Required");
  51. const Status Status::CODE_403(403, "Forbidden");
  52. const Status Status::CODE_404(404, "Not Found");
  53. const Status Status::CODE_405(405, "Method Not Allowed");
  54. const Status Status::CODE_406(406, "Not Acceptable");
  55. const Status Status::CODE_407(407, "Proxy Authentication Required");
  56. const Status Status::CODE_408(408, "Request Timeout");
  57. const Status Status::CODE_409(409, "Conflict");
  58. const Status Status::CODE_410(410, "Gone");
  59. const Status Status::CODE_411(411, "Length Required");
  60. const Status Status::CODE_412(412, "Precondition Failed");
  61. const Status Status::CODE_413(413, "Request Entity Too Large");
  62. const Status Status::CODE_414(414, "Request-URI Too Large");
  63. const Status Status::CODE_415(415, "Unsupported Media Type");
  64. const Status Status::CODE_416(416, "Requested Range Not Satisfiable");
  65. const Status Status::CODE_417(417, "Expectation Failed");
  66. const Status Status::CODE_418(418, "I'm a Teapot");
  67. const Status Status::CODE_422(422, "Unprocessable Entity");
  68. const Status Status::CODE_423(423, "Locked");
  69. const Status Status::CODE_424(424, "Failed Dependency");
  70. const Status Status::CODE_425(425, "Unordered Collection");
  71. const Status Status::CODE_426(426, "Upgrade Required");
  72. const Status Status::CODE_428(428, "Precondition Required");
  73. const Status Status::CODE_429(429, "Too Many Requests");
  74. const Status Status::CODE_431(431, "Request Header Fields Too Large");
  75. const Status Status::CODE_434(434, "Requested host unavailable");
  76. const Status Status::CODE_444(444, "Close connection withot sending headers");
  77. const Status Status::CODE_449(449, "Retry With");
  78. const Status Status::CODE_451(451, "Unavailable For Legal Reasons");
  79. const Status Status::CODE_500(500, "Internal Server Error");
  80. const Status Status::CODE_501(501, "Not Implemented");
  81. const Status Status::CODE_502(502, "Bad Gateway");
  82. const Status Status::CODE_503(503, "Service Unavailable");
  83. const Status Status::CODE_504(504, "Gateway Timeout");
  84. const Status Status::CODE_505(505, "HTTP Version Not Supported");
  85. const Status Status::CODE_506(506, "Variant Also Negotiates");
  86. const Status Status::CODE_507(507, "Insufficient Storage");
  87. const Status Status::CODE_508(508, "Loop Detected");
  88. const Status Status::CODE_509(509, "Bandwidth Limit Exceeded");
  89. const Status Status::CODE_510(510, "Not Extended");
  90. const Status Status::CODE_511(511, "Network Authentication Required");
  91. const char* const Header::Value::CONNECTION_CLOSE = "close";
  92. const char* const Header::Value::CONNECTION_KEEP_ALIVE = "keep-alive";
  93. const char* const Header::Value::CONNECTION_UPGRADE = "Upgrade";
  94. const char* const Header::Value::SERVER = "oatpp/" OATPP_VERSION;
  95. const char* const Header::Value::USER_AGENT = "oatpp/" OATPP_VERSION;
  96. const char* const Header::Value::TRANSFER_ENCODING_CHUNKED = "chunked";
  97. const char* const Header::Value::CONTENT_TYPE_APPLICATION_JSON = "application/json";
  98. const char* const Header::Value::EXPECT_100_CONTINUE = "100-continue";
  99. const char* const Header::ACCEPT = "Accept";
  100. const char* const Header::AUTHORIZATION = "Authorization";
  101. const char* const Header::WWW_AUTHENTICATE = "WWW-Authenticate";
  102. const char* const Header::CONNECTION = "Connection";
  103. const char* const Header::TRANSFER_ENCODING = "Transfer-Encoding";
  104. const char* const Header::CONTENT_ENCODING = "Content-Encoding";
  105. const char* const Header::CONTENT_LENGTH = "Content-Length";
  106. const char* const Header::CONTENT_TYPE = "Content-Type";
  107. const char* const Header::CONTENT_RANGE = "Content-Range";
  108. const char* const Header::RANGE = "Range";
  109. const char* const Header::HOST = "Host";
  110. const char* const Header::USER_AGENT = "User-Agent";
  111. const char* const Header::SERVER = "Server";
  112. const char* const Header::UPGRADE = "Upgrade";
  113. const char* const Header::CORS_ORIGIN = "Access-Control-Allow-Origin";
  114. const char* const Header::CORS_METHODS = "Access-Control-Allow-Methods";
  115. const char* const Header::CORS_HEADERS = "Access-Control-Allow-Headers";
  116. const char* const Header::CORS_MAX_AGE = "Access-Control-Max-Age";
  117. const char* const Header::ACCEPT_ENCODING = "Accept-Encoding";
  118. const char* const Header::EXPECT = "Expect";
  119. const char* const Range::UNIT_BYTES = "bytes";
  120. const char* const ContentRange::UNIT_BYTES = "bytes";
  121. oatpp::String Range::toString() const {
  122. data::stream::BufferOutputStream stream(256);
  123. stream.writeSimple(units->data(), units->size());
  124. stream.writeSimple("=", 1);
  125. stream.writeAsString(start);
  126. stream.writeSimple("-", 1);
  127. stream.writeAsString(end);
  128. return stream.toString();
  129. }
  130. Range Range::parse(oatpp::parser::Caret& caret) {
  131. auto unitsLabel = caret.putLabel();
  132. if(caret.findChar('=')) {
  133. unitsLabel.end();
  134. caret.inc();
  135. } else {
  136. caret.setError("'=' - expected");
  137. return Range();
  138. }
  139. auto startLabel = caret.putLabel();
  140. if(caret.findChar('-')) {
  141. startLabel.end();
  142. caret.inc();
  143. } else {
  144. caret.setError("'-' - expected");
  145. return Range();
  146. }
  147. auto endLabel = caret.putLabel();
  148. caret.findRN();
  149. endLabel.end();
  150. auto start = oatpp::utils::conversion::strToInt64((const char*) startLabel.getData());
  151. auto end = oatpp::utils::conversion::strToInt64((const char*) endLabel.getData());
  152. return Range(unitsLabel.toString(), start, end);
  153. }
  154. Range Range::parse(const oatpp::String& str) {
  155. oatpp::parser::Caret caret(str);
  156. return parse(caret);
  157. }
  158. oatpp::String ContentRange::toString() const {
  159. data::stream::BufferOutputStream stream(256);
  160. stream.writeSimple(units->data(), units->size());
  161. stream.writeSimple(" ", 1);
  162. stream.writeAsString(start);
  163. stream.writeSimple("-", 1);
  164. stream.writeAsString(end);
  165. stream.writeSimple("/", 1);
  166. if(isSizeKnown) {
  167. stream.writeAsString(size);
  168. } else {
  169. stream.writeSimple("*", 1);
  170. }
  171. return stream.toString();
  172. }
  173. ContentRange ContentRange::parse(oatpp::parser::Caret& caret) {
  174. auto unitsLabel = caret.putLabel();
  175. if(caret.findChar(' ')) {
  176. unitsLabel.end();
  177. caret.inc();
  178. } else {
  179. caret.setError("' ' - expected");
  180. return ContentRange();
  181. }
  182. auto startLabel = caret.putLabel();
  183. if(caret.findChar('-')) {
  184. startLabel.end();
  185. caret.inc();
  186. } else {
  187. caret.setError("'-' - expected");
  188. return ContentRange();
  189. }
  190. auto endLabel = caret.putLabel();
  191. if(caret.findChar('/')) {
  192. endLabel.end();
  193. caret.inc();
  194. } else {
  195. caret.setError("'/' - expected");
  196. return ContentRange();
  197. }
  198. auto sizeLabel = caret.putLabel();
  199. caret.findRN();
  200. sizeLabel.end();
  201. v_int64 start = oatpp::utils::conversion::strToInt64((const char*) startLabel.getData());
  202. v_int64 end = oatpp::utils::conversion::strToInt64((const char*) endLabel.getData());
  203. v_int64 size = 0;
  204. bool isSizeKnown = false;
  205. if(sizeLabel.getData()[0] != '*') {
  206. isSizeKnown = true;
  207. size = oatpp::utils::conversion::strToInt64((const char*) sizeLabel.getData());
  208. }
  209. return ContentRange(unitsLabel.toString(), start, end, size, isSizeKnown);
  210. }
  211. ContentRange ContentRange::parse(const oatpp::String& str) {
  212. oatpp::parser::Caret caret(str);
  213. return parse(caret);
  214. }
  215. oatpp::String HeaderValueData::getTitleParamValue(const data::share::StringKeyLabelCI& key) const {
  216. auto it = titleParams.find(key);
  217. if(it != titleParams.end()) {
  218. return it->second.toString();
  219. }
  220. return nullptr;
  221. }
  222. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  223. // Parser
  224. oatpp::data::share::StringKeyLabelCI Parser::parseHeaderNameLabel(const std::shared_ptr<std::string>& headersText,
  225. oatpp::parser::Caret& caret) {
  226. const char* data = caret.getData();
  227. for(v_buff_size i = caret.getPosition(); i < caret.getDataSize(); i++) {
  228. v_char8 a = data[i];
  229. if(a == ':' || a == ' '){
  230. oatpp::data::share::StringKeyLabelCI label(headersText, &data[caret.getPosition()], i - caret.getPosition());
  231. caret.setPosition(i);
  232. return label;
  233. }
  234. }
  235. return oatpp::data::share::StringKeyLabelCI(nullptr, nullptr, 0);
  236. }
  237. void Parser::parseRequestStartingLine(RequestStartingLine& line,
  238. const std::shared_ptr<std::string>& headersText,
  239. oatpp::parser::Caret& caret,
  240. Status& error) {
  241. auto methodLabel = caret.putLabel();
  242. if(caret.findChar(' ')){
  243. line.method = oatpp::data::share::StringKeyLabel(headersText, methodLabel.getData(), methodLabel.getSize());
  244. caret.inc();
  245. } else {
  246. error = Status::CODE_400;
  247. return;
  248. }
  249. auto pathLabel = caret.putLabel();
  250. if(caret.findChar(' ')){
  251. line.path = oatpp::data::share::StringKeyLabel(headersText, pathLabel.getData(), pathLabel.getSize());
  252. caret.inc();
  253. } else {
  254. error = Status::CODE_400;
  255. return;
  256. }
  257. auto protocolLabel = caret.putLabel();
  258. if(caret.findRN()){
  259. line.protocol = oatpp::data::share::StringKeyLabel(headersText, protocolLabel.getData(), protocolLabel.getSize());
  260. caret.skipRN();
  261. } else {
  262. error = Status::CODE_400;
  263. return;
  264. }
  265. }
  266. void Parser::parseResponseStartingLine(ResponseStartingLine& line,
  267. const std::shared_ptr<std::string>& headersText,
  268. oatpp::parser::Caret& caret,
  269. Status& error) {
  270. auto protocolLabel = caret.putLabel();
  271. if(caret.findChar(' ')){
  272. line.protocol = oatpp::data::share::StringKeyLabel(headersText, protocolLabel.getData(), protocolLabel.getSize());
  273. caret.inc();
  274. } else {
  275. error = Status::CODE_400;
  276. return;
  277. }
  278. line.statusCode = (v_int32)caret.parseInt();
  279. auto descriptionLabel = caret.putLabel();
  280. if(caret.findRN()){
  281. line.description = oatpp::data::share::StringKeyLabel(headersText, descriptionLabel.getData(), descriptionLabel.getSize());
  282. caret.skipRN();
  283. } else {
  284. error = Status::CODE_400;
  285. return;
  286. }
  287. }
  288. void Parser::parseOneHeader(Headers& headers,
  289. const std::shared_ptr<std::string>& headersText,
  290. oatpp::parser::Caret& caret,
  291. Status& error)
  292. {
  293. caret.skipChar(' ');
  294. auto name = parseHeaderNameLabel(headersText, caret);
  295. if(name.getData() != nullptr) {
  296. caret.skipChar(' ');
  297. if(!caret.canContinueAtChar(':', 1)) {
  298. error = Status::CODE_400;
  299. return;
  300. }
  301. caret.skipChar(' ');
  302. v_buff_size valuePos0 = caret.getPosition();
  303. caret.findRN();
  304. headers.put_LockFree(name, oatpp::data::share::StringKeyLabel(headersText, &caret.getData()[valuePos0], caret.getPosition() - valuePos0));
  305. caret.skipRN();
  306. } else {
  307. error = Status::CODE_431;
  308. return;
  309. }
  310. }
  311. void Parser::parseHeaders(Headers& headers,
  312. const std::shared_ptr<std::string>& headersText,
  313. oatpp::parser::Caret& caret,
  314. Status& error)
  315. {
  316. while (!caret.isAtRN()) {
  317. parseOneHeader(headers, headersText, caret, error);
  318. if(error.code != 0) {
  319. return;
  320. }
  321. }
  322. caret.skipRN();
  323. }
  324. void Parser::parseHeaderValueData(HeaderValueData& data, const oatpp::data::share::StringKeyLabel& headerValue, char separator) {
  325. oatpp::parser::Caret caret((const char*) headerValue.getData(), headerValue.getSize());
  326. const char charSet[5] = {' ', '=', separator, '\r', '\n'};
  327. const char charSet2[4] = {' ', separator, '\r', '\n'};
  328. while (caret.canContinue()) {
  329. caret.skipChar(' ');
  330. auto label = caret.putLabel();
  331. auto res = caret.findCharFromSet(charSet, 5);
  332. if (res == '=') {
  333. data::share::StringKeyLabelCI key(headerValue.getMemoryHandle(), label.getData(), label.getSize());
  334. caret.inc();
  335. if (caret.isAtChar('"')) {
  336. label = caret.parseStringEnclosed('"', '"', '\\');
  337. } else if (caret.isAtChar('\'')) {
  338. label = caret.parseStringEnclosed('\'', '\'', '\\');
  339. } else {
  340. label = caret.putLabel();
  341. caret.findCharFromSet(charSet2, 4);
  342. }
  343. data.titleParams[key] = data::share::StringKeyLabel(headerValue.getMemoryHandle(), label.getData(),
  344. label.getSize());
  345. } else {
  346. data.tokens.insert(
  347. data::share::StringKeyLabelCI(headerValue.getMemoryHandle(), label.getData(), label.getSize()));
  348. }
  349. if (caret.isAtCharFromSet("\r\n", 2)) {
  350. break;
  351. } else if (caret.isAtChar(separator)) {
  352. caret.inc();
  353. }
  354. }
  355. }
  356. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  357. // Utils
  358. void Utils::writeHeaders(const Headers& headers, data::stream::ConsistentOutputStream* stream) {
  359. auto& map = headers.getAll_Unsafe();
  360. auto it = map.begin();
  361. while(it != map.end()) {
  362. stream->writeSimple(it->first.getData(), it->first.getSize());
  363. stream->writeSimple(": ", 2);
  364. stream->writeSimple(it->second.getData(), it->second.getSize());
  365. stream->writeSimple("\r\n", 2);
  366. it ++;
  367. }
  368. }
  369. }}}}