MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at mir/inline-method 118 lines 4.3 kB view raw
1#include <compat.h> // IWYU pragma: keep 2 3#include <stdbool.h> 4#include <stdint.h> 5#include <stdio.h> 6#include <stdlib.h> 7#include <string.h> 8 9#include "ant.h" 10#include "errors.h" 11#include "internal.h" 12 13#include "http/http1_parser.h" 14#include "modules/buffer.h" 15#include "modules/http_parser.h" 16 17static ant_value_t http_parser_make_buffer(ant_t *js, const uint8_t *data, size_t len) { 18 ArrayBufferData *ab = create_array_buffer_data(len); 19 if (!ab) return js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 20 if (len > 0 && data) memcpy(ab->data, data, len); 21 return create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, len, "Buffer"); 22} 23 24static ant_value_t http_parser_make_error( 25 ant_t *js, 26 const char *message, 27 const char *code, 28 size_t bytes_parsed 29) { 30 ant_value_t err = js_mkerr_typed(js, JS_ERR_SYNTAX, "%s", message ? message : "Invalid HTTP request"); 31 32 if (!is_err(err)) return err; 33 if (code) js_set(js, err, "code", js_mkstr(js, code, strlen(code))); 34 js_set(js, err, "bytesParsed", js_mknum((double)bytes_parsed)); 35 return err; 36} 37 38static ant_value_t http_parser_raw_headers_array(ant_t *js, const ant_http1_parsed_request_t *parsed) { 39 ant_value_t raw_headers = js_mkarr(js); 40 const ant_http_header_t *hdr = NULL; 41 42 for (hdr = parsed->headers; hdr; hdr = hdr->next) { 43 js_arr_push(js, raw_headers, js_mkstr(js, hdr->name, strlen(hdr->name))); 44 js_arr_push(js, raw_headers, js_mkstr(js, hdr->value, strlen(hdr->value))); 45 } 46 47 return raw_headers; 48} 49 50static ant_value_t js_http_parser_parse_request(ant_t *js, ant_value_t *args, int nargs) { 51 ant_http1_parsed_request_t parsed = {0}; 52 ant_http1_parse_result_t result = ANT_HTTP1_PARSE_INCOMPLETE; 53 ant_value_t input = 0; 54 ant_value_t out = 0; 55 ant_value_t body = 0; 56 ant_value_t version = 0; 57 58 const uint8_t *bytes = NULL; 59 size_t len = 0; 60 61 const char *error_reason = NULL; 62 const char *error_code = NULL; 63 char version_buf[8] = {0}; 64 65 if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "parseRequest requires 1 argument"); 66 input = args[0]; 67 68 if (!buffer_source_get_bytes(js, input, &bytes, &len)) { 69 ant_value_t str_value = js_tostring_val(js, input); 70 const char *str = NULL; 71 72 if (is_err(str_value)) return str_value; 73 str = js_getstr(js, str_value, &len); 74 75 if (!str) return js_mkerr_typed(js, JS_ERR_TYPE, "parseRequest input must be string or buffer-like"); 76 bytes = (const uint8_t *)str; 77 } 78 79 result = ant_http1_parse_request((const char *)bytes, len, &parsed, &error_reason, &error_code); 80 if (result == ANT_HTTP1_PARSE_INCOMPLETE) return js_mknull(); 81 if (result == ANT_HTTP1_PARSE_ERROR) return http_parser_make_error(js, error_reason, error_code, parsed.consumed_len); 82 83 out = js_mkobj(js); 84 body = http_parser_make_buffer(js, parsed.body, parsed.body_len); 85 86 if (is_err(body)) { 87 ant_http1_free_parsed_request(&parsed); 88 return body; 89 } 90 91 snprintf(version_buf, sizeof(version_buf), "%u.%u", parsed.http_major, parsed.http_minor); 92 version = js_mkstr(js, version_buf, strlen(version_buf)); 93 94 js_set(js, out, "method", js_mkstr(js, parsed.method, strlen(parsed.method))); 95 js_set(js, out, "target", js_mkstr(js, parsed.target, strlen(parsed.target))); 96 js_set(js, out, "host", parsed.host ? js_mkstr(js, parsed.host, strlen(parsed.host)) : js_mknull()); 97 js_set(js, out, "contentType", parsed.content_type ? js_mkstr(js, parsed.content_type, strlen(parsed.content_type)) : js_mknull()); 98 js_set(js, out, "rawHeaders", http_parser_raw_headers_array(js, &parsed)); 99 100 js_set(js, out, "body", body); 101 js_set(js, out, "bodyLength", js_mknum((double)parsed.body_len)); 102 js_set(js, out, "contentLength", js_mknum((double)parsed.content_length)); 103 js_set(js, out, "absoluteTarget", js_bool(parsed.absolute_target)); 104 js_set(js, out, "keepAlive", js_bool(parsed.keep_alive)); 105 js_set(js, out, "httpVersionMajor", js_mknum((double)parsed.http_major)); 106 js_set(js, out, "httpVersionMinor", js_mknum((double)parsed.http_minor)); 107 js_set(js, out, "httpVersion", version); 108 js_set(js, out, "consumed", js_mknum((double)parsed.consumed_len)); 109 110 ant_http1_free_parsed_request(&parsed); 111 return out; 112} 113 114ant_value_t internal_http_parser_library(ant_t *js) { 115 ant_value_t lib = js_mkobj(js); 116 js_set(js, lib, "parseRequest", js_mkfun(js_http_parser_parse_request)); 117 return lib; 118}