http.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/common/hash_table.h>
  6. #include <aws/compression/compression.h>
  7. #include <aws/http/private/hpack.h>
  8. #include <aws/http/private/http_impl.h>
  9. #include <aws/http/status_code.h>
  10. #include <aws/io/logging.h>
  11. #include <ctype.h>
  12. #define AWS_DEFINE_ERROR_INFO_HTTP(CODE, STR) [(CODE)-0x0800] = AWS_DEFINE_ERROR_INFO(CODE, STR, "aws-c-http")
  13. /* clang-format off */
  14. static struct aws_error_info s_errors[] = {
  15. AWS_DEFINE_ERROR_INFO_HTTP(
  16. AWS_ERROR_HTTP_UNKNOWN,
  17. "Encountered an unknown error."),
  18. AWS_DEFINE_ERROR_INFO_HTTP(
  19. AWS_ERROR_HTTP_HEADER_NOT_FOUND,
  20. "The specified header was not found"),
  21. AWS_DEFINE_ERROR_INFO_HTTP(
  22. AWS_ERROR_HTTP_INVALID_HEADER_FIELD,
  23. "Invalid header field, including a forbidden header field."),
  24. AWS_DEFINE_ERROR_INFO_HTTP(
  25. AWS_ERROR_HTTP_INVALID_HEADER_NAME,
  26. "Invalid header name."),
  27. AWS_DEFINE_ERROR_INFO_HTTP(
  28. AWS_ERROR_HTTP_INVALID_HEADER_VALUE,
  29. "Invalid header value."),
  30. AWS_DEFINE_ERROR_INFO_HTTP(
  31. AWS_ERROR_HTTP_INVALID_METHOD,
  32. "Method is invalid."),
  33. AWS_DEFINE_ERROR_INFO_HTTP(
  34. AWS_ERROR_HTTP_INVALID_PATH,
  35. "Path is invalid."),
  36. AWS_DEFINE_ERROR_INFO_HTTP(
  37. AWS_ERROR_HTTP_INVALID_STATUS_CODE,
  38. "Status code is invalid."),
  39. AWS_DEFINE_ERROR_INFO_HTTP(
  40. AWS_ERROR_HTTP_MISSING_BODY_STREAM,
  41. "Given the provided headers (ex: Content-Length), a body is expected."),
  42. AWS_DEFINE_ERROR_INFO_HTTP(
  43. AWS_ERROR_HTTP_INVALID_BODY_STREAM,
  44. "A body stream provided, but the message does not allow body (ex: response for HEAD Request and 304 response)"),
  45. AWS_DEFINE_ERROR_INFO_HTTP(
  46. AWS_ERROR_HTTP_CONNECTION_CLOSED,
  47. "The connection has closed or is closing."),
  48. AWS_DEFINE_ERROR_INFO_HTTP(
  49. AWS_ERROR_HTTP_SWITCHED_PROTOCOLS,
  50. "The connection has switched protocols."),
  51. AWS_DEFINE_ERROR_INFO_HTTP(
  52. AWS_ERROR_HTTP_UNSUPPORTED_PROTOCOL,
  53. "An unsupported protocol was encountered."),
  54. AWS_DEFINE_ERROR_INFO_HTTP(
  55. AWS_ERROR_HTTP_REACTION_REQUIRED,
  56. "A necessary function was not invoked from a user callback."),
  57. AWS_DEFINE_ERROR_INFO_HTTP(
  58. AWS_ERROR_HTTP_DATA_NOT_AVAILABLE,
  59. "This data is not yet available."),
  60. AWS_DEFINE_ERROR_INFO_HTTP(
  61. AWS_ERROR_HTTP_OUTGOING_STREAM_LENGTH_INCORRECT,
  62. "Amount of data streamed out does not match the previously declared length."),
  63. AWS_DEFINE_ERROR_INFO_HTTP(
  64. AWS_ERROR_HTTP_CALLBACK_FAILURE,
  65. "A callback has reported failure."),
  66. AWS_DEFINE_ERROR_INFO_HTTP(
  67. AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE,
  68. "Failed to upgrade HTTP connection to Websocket."),
  69. AWS_DEFINE_ERROR_INFO_HTTP(
  70. AWS_ERROR_HTTP_WEBSOCKET_CLOSE_FRAME_SENT,
  71. "Websocket has sent CLOSE frame, no more data will be sent."),
  72. AWS_DEFINE_ERROR_INFO_HTTP(
  73. AWS_ERROR_HTTP_WEBSOCKET_IS_MIDCHANNEL_HANDLER,
  74. "Operation cannot be performed because websocket has been converted to a midchannel handler."),
  75. AWS_DEFINE_ERROR_INFO_HTTP(
  76. AWS_ERROR_HTTP_CONNECTION_MANAGER_INVALID_STATE_FOR_ACQUIRE,
  77. "Acquire called after the connection manager's ref count has reached zero"),
  78. AWS_DEFINE_ERROR_INFO_HTTP(
  79. AWS_ERROR_HTTP_CONNECTION_MANAGER_VENDED_CONNECTION_UNDERFLOW,
  80. "Release called when the connection manager's vended connection count was zero"),
  81. AWS_DEFINE_ERROR_INFO_HTTP(
  82. AWS_ERROR_HTTP_SERVER_CLOSED,
  83. "The http server is closed, no more connections will be accepted"),
  84. AWS_DEFINE_ERROR_INFO_HTTP(
  85. AWS_ERROR_HTTP_PROXY_CONNECT_FAILED,
  86. "Proxy-based connection establishment failed because the CONNECT call failed"),
  87. AWS_DEFINE_ERROR_INFO_HTTP(
  88. AWS_ERROR_HTTP_CONNECTION_MANAGER_SHUTTING_DOWN,
  89. "Connection acquisition failed because connection manager is shutting down"),
  90. AWS_DEFINE_ERROR_INFO_HTTP(
  91. AWS_ERROR_HTTP_CHANNEL_THROUGHPUT_FAILURE,
  92. "Http connection channel shut down due to failure to meet throughput minimum"),
  93. AWS_DEFINE_ERROR_INFO_HTTP(
  94. AWS_ERROR_HTTP_PROTOCOL_ERROR,
  95. "Protocol rules violated by peer"),
  96. AWS_DEFINE_ERROR_INFO_HTTP(
  97. AWS_ERROR_HTTP_STREAM_IDS_EXHAUSTED,
  98. "Connection exhausted all possible HTTP-stream IDs. Establish a new connection for new streams."),
  99. AWS_DEFINE_ERROR_INFO_HTTP(
  100. AWS_ERROR_HTTP_GOAWAY_RECEIVED,
  101. "Peer sent GOAWAY to initiate connection shutdown. Establish a new connection to retry the HTTP-streams."),
  102. AWS_DEFINE_ERROR_INFO_HTTP(
  103. AWS_ERROR_HTTP_RST_STREAM_RECEIVED,
  104. "Peer sent RST_STREAM to terminate HTTP-stream."),
  105. AWS_DEFINE_ERROR_INFO_HTTP(
  106. AWS_ERROR_HTTP_RST_STREAM_SENT,
  107. "RST_STREAM has sent from local implementation and HTTP-stream has been terminated."),
  108. AWS_DEFINE_ERROR_INFO_HTTP(
  109. AWS_ERROR_HTTP_STREAM_NOT_ACTIVATED,
  110. "HTTP-stream must be activated before use."),
  111. AWS_DEFINE_ERROR_INFO_HTTP(
  112. AWS_ERROR_HTTP_STREAM_HAS_COMPLETED,
  113. "HTTP-stream has completed, action cannot be performed."),
  114. AWS_DEFINE_ERROR_INFO_HTTP(
  115. AWS_ERROR_HTTP_PROXY_STRATEGY_NTLM_CHALLENGE_TOKEN_MISSING,
  116. "NTLM Proxy strategy was initiated without a challenge token"),
  117. AWS_DEFINE_ERROR_INFO_HTTP(
  118. AWS_ERROR_HTTP_PROXY_STRATEGY_TOKEN_RETRIEVAL_FAILURE,
  119. "Failure in user code while retrieving proxy auth token"),
  120. AWS_DEFINE_ERROR_INFO_HTTP(
  121. AWS_ERROR_HTTP_PROXY_CONNECT_FAILED_RETRYABLE,
  122. "Proxy connection attempt failed but the negotiation could be continued on a new connection"),
  123. AWS_DEFINE_ERROR_INFO_HTTP(
  124. AWS_ERROR_HTTP_PROTOCOL_SWITCH_FAILURE,
  125. "Internal state failure prevent connection from switching protocols"),
  126. AWS_DEFINE_ERROR_INFO_HTTP(
  127. AWS_ERROR_HTTP_MAX_CONCURRENT_STREAMS_EXCEEDED,
  128. "Max concurrent stream reached"),
  129. AWS_DEFINE_ERROR_INFO_HTTP(
  130. AWS_ERROR_HTTP_STREAM_MANAGER_SHUTTING_DOWN,
  131. "Stream acquisition failed because stream manager is shutting down"),
  132. AWS_DEFINE_ERROR_INFO_HTTP(
  133. AWS_ERROR_HTTP_STREAM_MANAGER_CONNECTION_ACQUIRE_FAILURE,
  134. "Stream acquisition failed because stream manager failed to acquire a connection"),
  135. AWS_DEFINE_ERROR_INFO_HTTP(
  136. AWS_ERROR_HTTP_STREAM_MANAGER_UNEXPECTED_HTTP_VERSION,
  137. "Stream acquisition failed because stream manager got an unexpected version of HTTP connection"),
  138. AWS_DEFINE_ERROR_INFO_HTTP(
  139. AWS_ERROR_HTTP_WEBSOCKET_PROTOCOL_ERROR,
  140. "Websocket protocol rules violated by peer"),
  141. AWS_DEFINE_ERROR_INFO_HTTP(
  142. AWS_ERROR_HTTP_MANUAL_WRITE_NOT_ENABLED,
  143. "Manual write failed because manual writes are not enabled."),
  144. AWS_DEFINE_ERROR_INFO_HTTP(
  145. AWS_ERROR_HTTP_MANUAL_WRITE_HAS_COMPLETED,
  146. "Manual write failed because manual writes are already completed."),
  147. };
  148. /* clang-format on */
  149. static struct aws_error_info_list s_error_list = {
  150. .error_list = s_errors,
  151. .count = AWS_ARRAY_SIZE(s_errors),
  152. };
  153. static struct aws_log_subject_info s_log_subject_infos[] = {
  154. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_GENERAL, "http", "Misc HTTP logging"),
  155. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_CONNECTION, "http-connection", "HTTP client or server connection"),
  156. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_ENCODER, "http-encoder", "HTTP data encoder"),
  157. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_DECODER, "http-decoder", "HTTP data decoder"),
  158. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_SERVER, "http-server", "HTTP server socket listening for incoming connections"),
  159. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_STREAM, "http-stream", "HTTP request-response exchange"),
  160. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_CONNECTION_MANAGER, "connection-manager", "HTTP connection manager"),
  161. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_STREAM_MANAGER, "http2-stream-manager", "HTTP/2 stream manager"),
  162. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_WEBSOCKET, "websocket", "Websocket"),
  163. DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_WEBSOCKET_SETUP, "websocket-setup", "Websocket setup"),
  164. DEFINE_LOG_SUBJECT_INFO(
  165. AWS_LS_HTTP_PROXY_NEGOTIATION,
  166. "proxy-negotiation",
  167. "Negotiating an http connection with a proxy server"),
  168. };
  169. static struct aws_log_subject_info_list s_log_subject_list = {
  170. .subject_list = s_log_subject_infos,
  171. .count = AWS_ARRAY_SIZE(s_log_subject_infos),
  172. };
  173. struct aws_enum_value {
  174. struct aws_allocator *allocator;
  175. int value;
  176. };
  177. static void s_destroy_enum_value(void *value) {
  178. struct aws_enum_value *enum_value = value;
  179. aws_mem_release(enum_value->allocator, enum_value);
  180. }
  181. /**
  182. * Given array of aws_byte_cursors, init hashtable where...
  183. * Key is aws_byte_cursor* (pointing into cursor from array) and comparisons are case-insensitive.
  184. * Value is the array index cast to a void*.
  185. */
  186. static void s_init_str_to_enum_hash_table(
  187. struct aws_hash_table *table,
  188. struct aws_allocator *alloc,
  189. struct aws_byte_cursor *str_array,
  190. int start_index,
  191. int end_index,
  192. bool ignore_case) {
  193. int err = aws_hash_table_init(
  194. table,
  195. alloc,
  196. end_index - start_index,
  197. ignore_case ? aws_hash_byte_cursor_ptr_ignore_case : aws_hash_byte_cursor_ptr,
  198. (aws_hash_callback_eq_fn *)(ignore_case ? aws_byte_cursor_eq_ignore_case : aws_byte_cursor_eq),
  199. NULL,
  200. s_destroy_enum_value);
  201. AWS_FATAL_ASSERT(!err);
  202. for (int i = start_index; i < end_index; ++i) {
  203. int was_created = 0;
  204. struct aws_enum_value *enum_value = aws_mem_calloc(alloc, 1, sizeof(struct aws_enum_value));
  205. AWS_FATAL_ASSERT(enum_value);
  206. enum_value->allocator = alloc;
  207. enum_value->value = i;
  208. AWS_FATAL_ASSERT(str_array[i].ptr && "Missing enum string");
  209. err = aws_hash_table_put(table, &str_array[i], (void *)enum_value, &was_created);
  210. AWS_FATAL_ASSERT(!err && was_created);
  211. }
  212. }
  213. /**
  214. * Given key, get value from table initialized by s_init_str_to_enum_hash_table().
  215. * Returns -1 if key not found.
  216. */
  217. static int s_find_in_str_to_enum_hash_table(const struct aws_hash_table *table, struct aws_byte_cursor *key) {
  218. struct aws_hash_element *elem;
  219. aws_hash_table_find(table, key, &elem);
  220. if (elem) {
  221. struct aws_enum_value *enum_value = elem->value;
  222. return enum_value->value;
  223. }
  224. return -1;
  225. }
  226. /* METHODS */
  227. static struct aws_hash_table s_method_str_to_enum; /* for string -> enum lookup */
  228. static struct aws_byte_cursor s_method_enum_to_str[AWS_HTTP_METHOD_COUNT]; /* for enum -> string lookup */
  229. static void s_methods_init(struct aws_allocator *alloc) {
  230. s_method_enum_to_str[AWS_HTTP_METHOD_GET] = aws_http_method_get;
  231. s_method_enum_to_str[AWS_HTTP_METHOD_HEAD] = aws_http_method_head;
  232. s_method_enum_to_str[AWS_HTTP_METHOD_CONNECT] = aws_http_method_connect;
  233. s_init_str_to_enum_hash_table(
  234. &s_method_str_to_enum,
  235. alloc,
  236. s_method_enum_to_str,
  237. AWS_HTTP_METHOD_UNKNOWN + 1,
  238. AWS_HTTP_METHOD_COUNT,
  239. false /* DO NOT ignore case of method */);
  240. }
  241. static void s_methods_clean_up(void) {
  242. aws_hash_table_clean_up(&s_method_str_to_enum);
  243. }
  244. enum aws_http_method aws_http_str_to_method(struct aws_byte_cursor cursor) {
  245. int method = s_find_in_str_to_enum_hash_table(&s_method_str_to_enum, &cursor);
  246. if (method >= 0) {
  247. return (enum aws_http_method)method;
  248. }
  249. return AWS_HTTP_METHOD_UNKNOWN;
  250. }
  251. /* VERSIONS */
  252. static struct aws_byte_cursor s_version_enum_to_str[AWS_HTTP_HEADER_COUNT]; /* for enum -> string lookup */
  253. static void s_versions_init(struct aws_allocator *alloc) {
  254. (void)alloc;
  255. s_version_enum_to_str[AWS_HTTP_VERSION_UNKNOWN] = aws_byte_cursor_from_c_str("Unknown");
  256. s_version_enum_to_str[AWS_HTTP_VERSION_1_0] = aws_byte_cursor_from_c_str("HTTP/1.0");
  257. s_version_enum_to_str[AWS_HTTP_VERSION_1_1] = aws_byte_cursor_from_c_str("HTTP/1.1");
  258. s_version_enum_to_str[AWS_HTTP_VERSION_2] = aws_byte_cursor_from_c_str("HTTP/2");
  259. }
  260. static void s_versions_clean_up(void) {}
  261. struct aws_byte_cursor aws_http_version_to_str(enum aws_http_version version) {
  262. if ((int)version < AWS_HTTP_VERSION_UNKNOWN || (int)version >= AWS_HTTP_VERSION_COUNT) {
  263. version = AWS_HTTP_VERSION_UNKNOWN;
  264. }
  265. return s_version_enum_to_str[version];
  266. }
  267. /* HEADERS */
  268. static struct aws_hash_table s_header_str_to_enum; /* for case-insensitive string -> enum lookup */
  269. static struct aws_hash_table s_lowercase_header_str_to_enum; /* for case-sensitive string -> enum lookup */
  270. static struct aws_byte_cursor s_header_enum_to_str[AWS_HTTP_HEADER_COUNT]; /* for enum -> string lookup */
  271. static void s_headers_init(struct aws_allocator *alloc) {
  272. s_header_enum_to_str[AWS_HTTP_HEADER_METHOD] = aws_byte_cursor_from_c_str(":method");
  273. s_header_enum_to_str[AWS_HTTP_HEADER_SCHEME] = aws_byte_cursor_from_c_str(":scheme");
  274. s_header_enum_to_str[AWS_HTTP_HEADER_AUTHORITY] = aws_byte_cursor_from_c_str(":authority");
  275. s_header_enum_to_str[AWS_HTTP_HEADER_PATH] = aws_byte_cursor_from_c_str(":path");
  276. s_header_enum_to_str[AWS_HTTP_HEADER_STATUS] = aws_byte_cursor_from_c_str(":status");
  277. s_header_enum_to_str[AWS_HTTP_HEADER_COOKIE] = aws_byte_cursor_from_c_str("cookie");
  278. s_header_enum_to_str[AWS_HTTP_HEADER_SET_COOKIE] = aws_byte_cursor_from_c_str("set-cookie");
  279. s_header_enum_to_str[AWS_HTTP_HEADER_HOST] = aws_byte_cursor_from_c_str("host");
  280. s_header_enum_to_str[AWS_HTTP_HEADER_CONNECTION] = aws_byte_cursor_from_c_str("connection");
  281. s_header_enum_to_str[AWS_HTTP_HEADER_CONTENT_LENGTH] = aws_byte_cursor_from_c_str("content-length");
  282. s_header_enum_to_str[AWS_HTTP_HEADER_EXPECT] = aws_byte_cursor_from_c_str("expect");
  283. s_header_enum_to_str[AWS_HTTP_HEADER_TRANSFER_ENCODING] = aws_byte_cursor_from_c_str("transfer-encoding");
  284. s_header_enum_to_str[AWS_HTTP_HEADER_CACHE_CONTROL] = aws_byte_cursor_from_c_str("cache-control");
  285. s_header_enum_to_str[AWS_HTTP_HEADER_MAX_FORWARDS] = aws_byte_cursor_from_c_str("max-forwards");
  286. s_header_enum_to_str[AWS_HTTP_HEADER_PRAGMA] = aws_byte_cursor_from_c_str("pragma");
  287. s_header_enum_to_str[AWS_HTTP_HEADER_RANGE] = aws_byte_cursor_from_c_str("range");
  288. s_header_enum_to_str[AWS_HTTP_HEADER_TE] = aws_byte_cursor_from_c_str("te");
  289. s_header_enum_to_str[AWS_HTTP_HEADER_CONTENT_ENCODING] = aws_byte_cursor_from_c_str("content-encoding");
  290. s_header_enum_to_str[AWS_HTTP_HEADER_CONTENT_TYPE] = aws_byte_cursor_from_c_str("content-type");
  291. s_header_enum_to_str[AWS_HTTP_HEADER_CONTENT_RANGE] = aws_byte_cursor_from_c_str("content-range");
  292. s_header_enum_to_str[AWS_HTTP_HEADER_TRAILER] = aws_byte_cursor_from_c_str("trailer");
  293. s_header_enum_to_str[AWS_HTTP_HEADER_WWW_AUTHENTICATE] = aws_byte_cursor_from_c_str("www-authenticate");
  294. s_header_enum_to_str[AWS_HTTP_HEADER_AUTHORIZATION] = aws_byte_cursor_from_c_str("authorization");
  295. s_header_enum_to_str[AWS_HTTP_HEADER_PROXY_AUTHENTICATE] = aws_byte_cursor_from_c_str("proxy-authenticate");
  296. s_header_enum_to_str[AWS_HTTP_HEADER_PROXY_AUTHORIZATION] = aws_byte_cursor_from_c_str("proxy-authorization");
  297. s_header_enum_to_str[AWS_HTTP_HEADER_AGE] = aws_byte_cursor_from_c_str("age");
  298. s_header_enum_to_str[AWS_HTTP_HEADER_EXPIRES] = aws_byte_cursor_from_c_str("expires");
  299. s_header_enum_to_str[AWS_HTTP_HEADER_DATE] = aws_byte_cursor_from_c_str("date");
  300. s_header_enum_to_str[AWS_HTTP_HEADER_LOCATION] = aws_byte_cursor_from_c_str("location");
  301. s_header_enum_to_str[AWS_HTTP_HEADER_RETRY_AFTER] = aws_byte_cursor_from_c_str("retry-after");
  302. s_header_enum_to_str[AWS_HTTP_HEADER_VARY] = aws_byte_cursor_from_c_str("vary");
  303. s_header_enum_to_str[AWS_HTTP_HEADER_WARNING] = aws_byte_cursor_from_c_str("warning");
  304. s_header_enum_to_str[AWS_HTTP_HEADER_UPGRADE] = aws_byte_cursor_from_c_str("upgrade");
  305. s_header_enum_to_str[AWS_HTTP_HEADER_KEEP_ALIVE] = aws_byte_cursor_from_c_str("keep-alive");
  306. s_header_enum_to_str[AWS_HTTP_HEADER_PROXY_CONNECTION] = aws_byte_cursor_from_c_str("proxy-connection");
  307. s_init_str_to_enum_hash_table(
  308. &s_header_str_to_enum,
  309. alloc,
  310. s_header_enum_to_str,
  311. AWS_HTTP_HEADER_UNKNOWN + 1,
  312. AWS_HTTP_HEADER_COUNT,
  313. true /* ignore case */);
  314. s_init_str_to_enum_hash_table(
  315. &s_lowercase_header_str_to_enum,
  316. alloc,
  317. s_header_enum_to_str,
  318. AWS_HTTP_HEADER_UNKNOWN + 1,
  319. AWS_HTTP_HEADER_COUNT,
  320. false /* ignore case */);
  321. }
  322. static void s_headers_clean_up(void) {
  323. aws_hash_table_clean_up(&s_header_str_to_enum);
  324. aws_hash_table_clean_up(&s_lowercase_header_str_to_enum);
  325. }
  326. enum aws_http_header_name aws_http_str_to_header_name(struct aws_byte_cursor cursor) {
  327. int header = s_find_in_str_to_enum_hash_table(&s_header_str_to_enum, &cursor);
  328. if (header >= 0) {
  329. return (enum aws_http_header_name)header;
  330. }
  331. return AWS_HTTP_HEADER_UNKNOWN;
  332. }
  333. enum aws_http_header_name aws_http_lowercase_str_to_header_name(struct aws_byte_cursor cursor) {
  334. int header = s_find_in_str_to_enum_hash_table(&s_lowercase_header_str_to_enum, &cursor);
  335. if (header >= 0) {
  336. return (enum aws_http_header_name)header;
  337. }
  338. return AWS_HTTP_HEADER_UNKNOWN;
  339. }
  340. /* STATUS */
  341. const char *aws_http_status_text(int status_code) {
  342. /**
  343. * Data from Internet Assigned Numbers Authority (IANA):
  344. * https://www.iana.org/assignments/http-status-codes/http-status-codes.txt
  345. */
  346. switch (status_code) {
  347. case AWS_HTTP_STATUS_CODE_100_CONTINUE:
  348. return "Continue";
  349. case AWS_HTTP_STATUS_CODE_101_SWITCHING_PROTOCOLS:
  350. return "Switching Protocols";
  351. case AWS_HTTP_STATUS_CODE_102_PROCESSING:
  352. return "Processing";
  353. case AWS_HTTP_STATUS_CODE_103_EARLY_HINTS:
  354. return "Early Hints";
  355. case AWS_HTTP_STATUS_CODE_200_OK:
  356. return "OK";
  357. case AWS_HTTP_STATUS_CODE_201_CREATED:
  358. return "Created";
  359. case AWS_HTTP_STATUS_CODE_202_ACCEPTED:
  360. return "Accepted";
  361. case AWS_HTTP_STATUS_CODE_203_NON_AUTHORITATIVE_INFORMATION:
  362. return "Non-Authoritative Information";
  363. case AWS_HTTP_STATUS_CODE_204_NO_CONTENT:
  364. return "No Content";
  365. case AWS_HTTP_STATUS_CODE_205_RESET_CONTENT:
  366. return "Reset Content";
  367. case AWS_HTTP_STATUS_CODE_206_PARTIAL_CONTENT:
  368. return "Partial Content";
  369. case AWS_HTTP_STATUS_CODE_207_MULTI_STATUS:
  370. return "Multi-Status";
  371. case AWS_HTTP_STATUS_CODE_208_ALREADY_REPORTED:
  372. return "Already Reported";
  373. case AWS_HTTP_STATUS_CODE_226_IM_USED:
  374. return "IM Used";
  375. case AWS_HTTP_STATUS_CODE_300_MULTIPLE_CHOICES:
  376. return "Multiple Choices";
  377. case AWS_HTTP_STATUS_CODE_301_MOVED_PERMANENTLY:
  378. return "Moved Permanently";
  379. case AWS_HTTP_STATUS_CODE_302_FOUND:
  380. return "Found";
  381. case AWS_HTTP_STATUS_CODE_303_SEE_OTHER:
  382. return "See Other";
  383. case AWS_HTTP_STATUS_CODE_304_NOT_MODIFIED:
  384. return "Not Modified";
  385. case AWS_HTTP_STATUS_CODE_305_USE_PROXY:
  386. return "Use Proxy";
  387. case AWS_HTTP_STATUS_CODE_307_TEMPORARY_REDIRECT:
  388. return "Temporary Redirect";
  389. case AWS_HTTP_STATUS_CODE_308_PERMANENT_REDIRECT:
  390. return "Permanent Redirect";
  391. case AWS_HTTP_STATUS_CODE_400_BAD_REQUEST:
  392. return "Bad Request";
  393. case AWS_HTTP_STATUS_CODE_401_UNAUTHORIZED:
  394. return "Unauthorized";
  395. case AWS_HTTP_STATUS_CODE_402_PAYMENT_REQUIRED:
  396. return "Payment Required";
  397. case AWS_HTTP_STATUS_CODE_403_FORBIDDEN:
  398. return "Forbidden";
  399. case AWS_HTTP_STATUS_CODE_404_NOT_FOUND:
  400. return "Not Found";
  401. case AWS_HTTP_STATUS_CODE_405_METHOD_NOT_ALLOWED:
  402. return "Method Not Allowed";
  403. case AWS_HTTP_STATUS_CODE_406_NOT_ACCEPTABLE:
  404. return "Not Acceptable";
  405. case AWS_HTTP_STATUS_CODE_407_PROXY_AUTHENTICATION_REQUIRED:
  406. return "Proxy Authentication Required";
  407. case AWS_HTTP_STATUS_CODE_408_REQUEST_TIMEOUT:
  408. return "Request Timeout";
  409. case AWS_HTTP_STATUS_CODE_409_CONFLICT:
  410. return "Conflict";
  411. case AWS_HTTP_STATUS_CODE_410_GONE:
  412. return "Gone";
  413. case AWS_HTTP_STATUS_CODE_411_LENGTH_REQUIRED:
  414. return "Length Required";
  415. case AWS_HTTP_STATUS_CODE_412_PRECONDITION_FAILED:
  416. return "Precondition Failed";
  417. case AWS_HTTP_STATUS_CODE_413_REQUEST_ENTITY_TOO_LARGE:
  418. return "Payload Too Large";
  419. case AWS_HTTP_STATUS_CODE_414_REQUEST_URI_TOO_LONG:
  420. return "URI Too Long";
  421. case AWS_HTTP_STATUS_CODE_415_UNSUPPORTED_MEDIA_TYPE:
  422. return "Unsupported Media Type";
  423. case AWS_HTTP_STATUS_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE:
  424. return "Range Not Satisfiable";
  425. case AWS_HTTP_STATUS_CODE_417_EXPECTATION_FAILED:
  426. return "Expectation Failed";
  427. case AWS_HTTP_STATUS_CODE_421_MISDIRECTED_REQUEST:
  428. return "Misdirected Request";
  429. case AWS_HTTP_STATUS_CODE_422_UNPROCESSABLE_ENTITY:
  430. return "Unprocessable Entity";
  431. case AWS_HTTP_STATUS_CODE_423_LOCKED:
  432. return "Locked";
  433. case AWS_HTTP_STATUS_CODE_424_FAILED_DEPENDENCY:
  434. return "Failed Dependency";
  435. case AWS_HTTP_STATUS_CODE_425_TOO_EARLY:
  436. return "Too Early";
  437. case AWS_HTTP_STATUS_CODE_426_UPGRADE_REQUIRED:
  438. return "Upgrade Required";
  439. case AWS_HTTP_STATUS_CODE_428_PRECONDITION_REQUIRED:
  440. return "Precondition Required";
  441. case AWS_HTTP_STATUS_CODE_429_TOO_MANY_REQUESTS:
  442. return "Too Many Requests";
  443. case AWS_HTTP_STATUS_CODE_431_REQUEST_HEADER_FIELDS_TOO_LARGE:
  444. return "Request Header Fields Too Large";
  445. case AWS_HTTP_STATUS_CODE_451_UNAVAILABLE_FOR_LEGAL_REASON:
  446. return "Unavailable For Legal Reasons";
  447. case AWS_HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR:
  448. return "Internal Server Error";
  449. case AWS_HTTP_STATUS_CODE_501_NOT_IMPLEMENTED:
  450. return "Not Implemented";
  451. case AWS_HTTP_STATUS_CODE_502_BAD_GATEWAY:
  452. return "Bad Gateway";
  453. case AWS_HTTP_STATUS_CODE_503_SERVICE_UNAVAILABLE:
  454. return "Service Unavailable";
  455. case AWS_HTTP_STATUS_CODE_504_GATEWAY_TIMEOUT:
  456. return "Gateway Timeout";
  457. case AWS_HTTP_STATUS_CODE_505_HTTP_VERSION_NOT_SUPPORTED:
  458. return "HTTP Version Not Supported";
  459. case AWS_HTTP_STATUS_CODE_506_VARIANT_ALSO_NEGOTIATES:
  460. return "Variant Also Negotiates";
  461. case AWS_HTTP_STATUS_CODE_507_INSUFFICIENT_STORAGE:
  462. return "Insufficient Storage";
  463. case AWS_HTTP_STATUS_CODE_508_LOOP_DETECTED:
  464. return "Loop Detected";
  465. case AWS_HTTP_STATUS_CODE_510_NOT_EXTENDED:
  466. return "Not Extended";
  467. case AWS_HTTP_STATUS_CODE_511_NETWORK_AUTHENTICATION_REQUIRED:
  468. return "Network Authentication Required";
  469. default:
  470. return "";
  471. }
  472. }
  473. static bool s_library_initialized = false;
  474. void aws_http_library_init(struct aws_allocator *alloc) {
  475. if (s_library_initialized) {
  476. return;
  477. }
  478. s_library_initialized = true;
  479. aws_io_library_init(alloc);
  480. aws_compression_library_init(alloc);
  481. aws_register_error_info(&s_error_list);
  482. aws_register_log_subject_info_list(&s_log_subject_list);
  483. s_methods_init(alloc);
  484. s_headers_init(alloc);
  485. s_versions_init(alloc);
  486. aws_hpack_static_table_init(alloc);
  487. }
  488. void aws_http_library_clean_up(void) {
  489. if (!s_library_initialized) {
  490. return;
  491. }
  492. s_library_initialized = false;
  493. aws_thread_join_all_managed();
  494. aws_unregister_error_info(&s_error_list);
  495. aws_unregister_log_subject_info_list(&s_log_subject_list);
  496. s_methods_clean_up();
  497. s_headers_clean_up();
  498. s_versions_clean_up();
  499. aws_hpack_static_table_clean_up();
  500. aws_compression_library_clean_up();
  501. aws_io_library_clean_up();
  502. }
  503. void aws_http_fatal_assert_library_initialized() {
  504. if (!s_library_initialized) {
  505. AWS_LOGF_FATAL(
  506. AWS_LS_HTTP_GENERAL,
  507. "aws_http_library_init() must be called before using any functionality in aws-c-http.");
  508. AWS_FATAL_ASSERT(s_library_initialized);
  509. }
  510. }
  511. const struct aws_byte_cursor aws_http_method_get = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET");
  512. const struct aws_byte_cursor aws_http_method_head = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("HEAD");
  513. const struct aws_byte_cursor aws_http_method_post = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("POST");
  514. const struct aws_byte_cursor aws_http_method_put = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("PUT");
  515. const struct aws_byte_cursor aws_http_method_delete = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("DELETE");
  516. const struct aws_byte_cursor aws_http_method_connect = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("CONNECT");
  517. const struct aws_byte_cursor aws_http_method_options = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("OPTIONS");
  518. const struct aws_byte_cursor aws_http_header_method = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":method");
  519. const struct aws_byte_cursor aws_http_header_scheme = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":scheme");
  520. const struct aws_byte_cursor aws_http_header_authority = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":authority");
  521. const struct aws_byte_cursor aws_http_header_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":path");
  522. const struct aws_byte_cursor aws_http_header_status = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":status");
  523. const struct aws_byte_cursor aws_http_scheme_http = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("http");
  524. const struct aws_byte_cursor aws_http_scheme_https = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("https");