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