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.

add ant:internal helpers for http

+443 -17
+1 -1
.github/actions/build-project/action.yml
··· 145 145 MSYS2_PATH=$(cygpath "$RUNNER_TEMP/msys64/clang64/bin") 146 146 export PATH="$MSYS2_PATH:$PATH" 147 147 fi 148 - ${{ inputs.strip }} build/${{ inputs.binary_name }} 148 + ${{ inputs.strip }} --strip-unneeded build/${{ inputs.binary_name }} 149 149 150 150 - name: Bundle Windows DLLs 151 151 if: runner.os == 'Windows'
+5 -1
include/http/http1_parser.h
··· 15 15 uint8_t *body; 16 16 size_t body_len; 17 17 size_t content_length; 18 + size_t consumed_len; 19 + uint8_t http_major; 20 + uint8_t http_minor; 18 21 bool absolute_target; 19 22 bool keep_alive; 20 23 } ant_http1_parsed_request_t; ··· 29 32 const char *data, 30 33 size_t len, 31 34 ant_http1_parsed_request_t *out, 32 - const char **error_reason 35 + const char **error_reason, 36 + const char **error_code 33 37 ); 34 38 35 39 void ant_http1_free_parsed_request(ant_http1_parsed_request_t *req);
+4 -2
include/http/http1_writer.h
··· 33 33 const char *status_text, 34 34 const char *content_type, 35 35 const uint8_t *body, 36 - size_t body_len 36 + size_t body_len, 37 + bool keep_alive 37 38 ); 38 39 39 40 bool ant_http1_write_response_head( ··· 42 43 const char *status_text, 43 44 ant_value_t headers, 44 45 bool body_is_stream, 45 - size_t body_size 46 + size_t body_size, 47 + bool keep_alive 46 48 ); 47 49 48 50 bool ant_http1_write_final_chunk(ant_http1_buffer_t *buf);
+8
include/modules/http_parser.h
··· 1 + #ifndef ANT_INTERNAL_HTTP_PARSER_MODULE_H 2 + #define ANT_INTERNAL_HTTP_PARSER_MODULE_H 3 + 4 + #include "types.h" 5 + 6 + ant_value_t internal_http_parser_library(ant_t *js); 7 + 8 + #endif
+8
include/modules/http_writer.h
··· 1 + #ifndef ANT_INTERNAL_HTTP_WRITER_MODULE_H 2 + #define ANT_INTERNAL_HTTP_WRITER_MODULE_H 3 + 4 + #include "types.h" 5 + 6 + ant_value_t internal_http_writer_library(ant_t *js); 7 + 8 + #endif
+16 -4
src/http/http1_parser.c
··· 15 15 ant_http1_buffer_t header_field; 16 16 ant_http1_buffer_t header_value; 17 17 ant_http1_buffer_t body; 18 + ant_http_header_t **header_tail; 18 19 bool message_complete; 19 20 } parser_ctx_t; 20 21 ··· 47 48 return false; 48 49 } 49 50 50 - hdr->next = ctx->req.headers; 51 - ctx->req.headers = hdr; 51 + *ctx->header_tail = hdr; 52 + ctx->header_tail = &hdr->next; 52 53 53 54 if (strcasecmp(hdr->name, "host") == 0) { 54 55 free(ctx->req.host); ··· 111 112 const char *data, 112 113 size_t len, 113 114 ant_http1_parsed_request_t *out, 114 - const char **error_reason 115 + const char **error_reason, 116 + const char **error_code 115 117 ) { 116 118 llhttp_t parser; 117 119 llhttp_settings_t settings; ··· 119 121 parser_ctx_t ctx = {0}; 120 122 121 123 if (error_reason) *error_reason = NULL; 124 + if (error_code) *error_code = NULL; 125 + 122 126 memset(out, 0, sizeof(*out)); 127 + ctx.header_tail = &ctx.req.headers; 123 128 124 129 ant_http1_buffer_init(&ctx.method); 125 130 ant_http1_buffer_init(&ctx.target); ··· 138 143 139 144 llhttp_init(&parser, HTTP_REQUEST, &settings); 140 145 parser.data = &ctx; 146 + 141 147 err = llhttp_execute(&parser, data, len); 148 + if (llhttp_get_error_pos(&parser)) out->consumed_len = (size_t)(llhttp_get_error_pos(&parser) - data); 142 149 143 150 if (err != HPE_OK && err != HPE_PAUSED) { 144 151 if (error_reason) *error_reason = llhttp_get_error_reason(&parser); 152 + if (error_code) *error_code = llhttp_errno_name(err); 145 153 parser_ctx_free(&ctx); 146 154 return ANT_HTTP1_PARSE_ERROR; 147 155 } ··· 160 168 } 161 169 162 170 ctx.req.absolute_target = 163 - strncmp(ctx.req.target, "http://", 7) == 0 || 171 + strncmp(ctx.req.target, "http://", 7) == 0 || 164 172 strncmp(ctx.req.target, "https://", 8) == 0; 173 + 165 174 ctx.req.keep_alive = llhttp_should_keep_alive(&parser) == 1; 175 + ctx.req.http_major = parser.http_major; 176 + ctx.req.http_minor = parser.http_minor; 166 177 167 178 *out = ctx.req; 168 179 memset(&ctx.req, 0, sizeof(ctx.req)); 169 180 parser_ctx_free(&ctx); 181 + 170 182 return ANT_HTTP1_PARSE_OK; 171 183 } 172 184
+10 -5
src/http/http1_writer.c
··· 155 155 const char *status_text, 156 156 const char *content_type, 157 157 const uint8_t *body, 158 - size_t body_len 158 + size_t body_len, 159 + bool keep_alive 159 160 ) { 160 161 ant_http1_buffer_appendf(buf, "HTTP/1.1 %d %s\r\n", status, status_text 161 162 ? status_text ··· 168 169 ); 169 170 170 171 ant_http1_buffer_appendf(buf, "Content-Length: %zu\r\n", body_len); 171 - ant_http1_buffer_append_cstr(buf, "Connection: close\r\n\r\n"); 172 + ant_http1_buffer_append_cstr(buf, keep_alive 173 + ? "Connection: keep-alive\r\n\r\n" 174 + : "Connection: close\r\n\r\n" 175 + ); 176 + 172 177 if (body_len > 0) ant_http1_buffer_append(buf, body, body_len); 173 - 174 178 return !buf->failed; 175 179 } 176 180 ··· 180 184 const char *status_text, 181 185 ant_value_t headers, 182 186 bool body_is_stream, 183 - size_t body_size 187 + size_t body_size, 188 + bool keep_alive 184 189 ) { 185 190 response_header_ctx_t ctx = { .buf = buf }; 186 191 ··· 192 197 headers_for_each(headers, ant_http1_append_response_header, &ctx); 193 198 if (body_is_stream) ant_http1_buffer_append_cstr(buf, "Transfer-Encoding: chunked\r\n"); 194 199 else ant_http1_buffer_appendf(buf, "Content-Length: %zu\r\n", body_size); 195 - ant_http1_buffer_append_cstr(buf, "Connection: close\r\n\r\n"); 200 + ant_http1_buffer_append_cstr(buf, keep_alive ? "Connection: keep-alive\r\n\r\n" : "Connection: close\r\n\r\n"); 196 201 197 202 return !buf->failed; 198 203 }
+5
src/main.c
··· 70 70 #include "modules/util.h" 71 71 #include "modules/async_hooks.h" 72 72 #include "modules/net.h" 73 + #include "modules/http_parser.h" 74 + #include "modules/http_writer.h" 73 75 #include "modules/dns.h" 74 76 #include "modules/assert.h" 75 77 #include "modules/domexception.h" ··· 610 612 ant_register_library(shell_library, "ant:shell", NULL); 611 613 ant_register_library(ffi_library, "ant:ffi", NULL); 612 614 ant_register_library(lmdb_library, "ant:lmdb", NULL); 615 + 616 + ant_register_library(internal_http_parser_library, "ant:internal/http_parser", NULL); 617 + ant_register_library(internal_http_writer_library, "ant:internal/http_writer", NULL); 613 618 614 619 ant_standard_library("util", util_library); 615 620 ant_standard_library("net", net_library);
+10 -1
src/modules/buffer.c
··· 2122 2122 } 2123 2123 2124 2124 ant_value_t buffer_library(ant_t *js) { 2125 - return js_get(js, js_glob(js), "Buffer"); 2125 + ant_value_t glob = js_glob(js); 2126 + ant_value_t lib = js_mkobj(js); 2127 + 2128 + js_set(js, lib, "Buffer", js_get(js, glob, "Buffer")); 2129 + js_set(js, lib, "Blob", js_get(js, glob, "Blob")); 2130 + js_set(js, lib, "File", js_get(js, glob, "File")); 2131 + js_set(js, lib, "atob", js_get(js, glob, "atob")); 2132 + js_set(js, lib, "btoa", js_get(js, glob, "btoa")); 2133 + 2134 + return lib; 2126 2135 } 2127 2136 2128 2137 void init_buffer_module() {
+118
src/modules/http_parser.c
··· 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 + 17 + static 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 + 24 + static 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 + 38 + static 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 + 50 + static 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 + 114 + ant_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 + }
+255
src/modules/http_writer.c
··· 1 + #include <compat.h> // IWYU pragma: keep 2 + 3 + #include <stdbool.h> 4 + #include <stdint.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <strings.h> 8 + 9 + #include "ant.h" 10 + #include "errors.h" 11 + #include "internal.h" 12 + 13 + #include "http/http1_writer.h" 14 + #include "modules/buffer.h" 15 + #include "modules/http_writer.h" 16 + 17 + static ant_value_t http_writer_make_buffer_value(ant_t *js, ant_http1_buffer_t *buf) { 18 + ant_value_t out = 0; 19 + char *data = NULL; 20 + size_t len = 0; 21 + ArrayBufferData *ab = NULL; 22 + 23 + data = ant_http1_buffer_take(buf, &len); 24 + ab = create_array_buffer_data(len); 25 + if (!ab) { 26 + free(data); 27 + return js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 28 + } 29 + 30 + if (len > 0 && data) memcpy(ab->data, data, len); 31 + free(data); 32 + out = create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, len, "Buffer"); 33 + return out; 34 + } 35 + 36 + static bool http_writer_append_raw_headers( 37 + ant_t *js, 38 + ant_http1_buffer_t *buf, 39 + ant_value_t raw_headers, 40 + ant_value_t *error_out 41 + ) { 42 + ant_offset_t len = 0; 43 + 44 + if (error_out) *error_out = js_mkundef(); 45 + if (vtype(raw_headers) == T_UNDEF || vtype(raw_headers) == T_NULL) return true; 46 + if (vtype(raw_headers) != T_ARR) { 47 + if (error_out) *error_out = js_mkerr_typed(js, JS_ERR_TYPE, "rawHeaders must be an array"); 48 + return false; 49 + } 50 + 51 + len = js_arr_len(js, raw_headers); 52 + if ((len & 1) != 0) { 53 + if (error_out) *error_out = js_mkerr_typed(js, JS_ERR_TYPE, "rawHeaders must contain name/value pairs"); 54 + return false; 55 + } 56 + 57 + for (ant_offset_t i = 0; i < len; i += 2) { 58 + ant_value_t name_value = js_tostring_val(js, js_arr_get(js, raw_headers, i)); 59 + ant_value_t header_value = js_tostring_val(js, js_arr_get(js, raw_headers, i + 1)); 60 + const char *name = NULL; 61 + const char *value = NULL; 62 + size_t name_len = 0; 63 + size_t value_len = 0; 64 + 65 + if (is_err(name_value)) { 66 + if (error_out) *error_out = name_value; 67 + return false; 68 + } 69 + if (is_err(header_value)) { 70 + if (error_out) *error_out = header_value; 71 + return false; 72 + } 73 + 74 + name = js_getstr(js, name_value, &name_len); 75 + value = js_getstr(js, header_value, &value_len); 76 + if (!name || !value) { 77 + if (error_out) *error_out = js_mkerr_typed(js, JS_ERR_TYPE, "Invalid raw header entry"); 78 + return false; 79 + } 80 + 81 + if (strcasecmp(name, "connection") == 0) continue; 82 + if (strcasecmp(name, "content-length") == 0) continue; 83 + if (strcasecmp(name, "transfer-encoding") == 0) continue; 84 + if (!ant_http1_buffer_appendf(buf, "%s: %s\r\n", name, value)) break; 85 + } 86 + 87 + if (buf->failed && error_out && vtype(*error_out) == T_UNDEF) 88 + *error_out = js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 89 + return !buf->failed; 90 + } 91 + 92 + static bool http_writer_parse_bytes( 93 + ant_t *js, 94 + ant_value_t value, 95 + const uint8_t **bytes_out, 96 + size_t *len_out, 97 + ant_value_t *error_out 98 + ) { 99 + ant_value_t str_value = 0; 100 + const char *str = NULL; 101 + size_t len = 0; 102 + 103 + if (error_out) *error_out = js_mkundef(); 104 + if (bytes_out) *bytes_out = NULL; 105 + if (len_out) *len_out = 0; 106 + 107 + if (vtype(value) == T_UNDEF || vtype(value) == T_NULL) return true; 108 + if (buffer_source_get_bytes(js, value, bytes_out, len_out)) return true; 109 + 110 + str_value = js_tostring_val(js, value); 111 + if (is_err(str_value)) { 112 + if (error_out) *error_out = str_value; 113 + return false; 114 + } 115 + 116 + str = js_getstr(js, str_value, &len); 117 + if (!str) { 118 + if (error_out) *error_out = js_mkerr_typed(js, JS_ERR_TYPE, "Invalid HTTP body chunk"); 119 + return false; 120 + } 121 + 122 + if (bytes_out) *bytes_out = (const uint8_t *)str; 123 + if (len_out) *len_out = len; 124 + return true; 125 + } 126 + 127 + static ant_value_t js_http_writer_default_status_text(ant_t *js, ant_value_t *args, int nargs) { 128 + int status = nargs > 0 ? (int)js_getnum(args[0]) : 200; 129 + const char *text = ant_http1_default_status_text(status); 130 + return js_mkstr(js, text, strlen(text)); 131 + } 132 + 133 + static ant_value_t js_http_writer_write_chunk(ant_t *js, ant_value_t *args, int nargs) { 134 + ant_http1_buffer_t buf; 135 + const uint8_t *bytes = NULL; 136 + size_t len = 0; 137 + ant_value_t error = js_mkundef(); 138 + 139 + ant_http1_buffer_init(&buf); 140 + if (!http_writer_parse_bytes(js, nargs > 0 ? args[0] : js_mkundef(), &bytes, &len, &error)) return error; 141 + if (!ant_http1_write_chunk(&buf, bytes, len)) { 142 + ant_http1_buffer_free(&buf); 143 + return js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 144 + } 145 + 146 + return http_writer_make_buffer_value(js, &buf); 147 + } 148 + 149 + static ant_value_t js_http_writer_write_final_chunk(ant_t *js, ant_value_t *args, int nargs) { 150 + ant_http1_buffer_t buf; 151 + 152 + ant_http1_buffer_init(&buf); 153 + if (!ant_http1_write_final_chunk(&buf)) { 154 + ant_http1_buffer_free(&buf); 155 + return js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 156 + } 157 + 158 + return http_writer_make_buffer_value(js, &buf); 159 + } 160 + 161 + static ant_value_t js_http_writer_write_basic_response(ant_t *js, ant_value_t *args, int nargs) { 162 + ant_http1_buffer_t buf; 163 + ant_value_t error = js_mkundef(); 164 + const uint8_t *body = NULL; 165 + 166 + size_t body_len = 0; 167 + int status = nargs > 0 ? (int)js_getnum(args[0]) : 200; 168 + 169 + const char *status_text = NULL; 170 + const char *content_type = NULL; 171 + bool keep_alive = false; 172 + 173 + if (nargs > 1 && vtype(args[1]) != T_UNDEF && vtype(args[1]) != T_NULL) { 174 + ant_value_t status_text_value = js_tostring_val(js, args[1]); 175 + if (is_err(status_text_value)) return status_text_value; 176 + status_text = js_getstr(js, status_text_value, NULL); 177 + } 178 + 179 + if (nargs > 2 && vtype(args[2]) != T_UNDEF && vtype(args[2]) != T_NULL) { 180 + ant_value_t content_type_value = js_tostring_val(js, args[2]); 181 + if (is_err(content_type_value)) return content_type_value; 182 + content_type = js_getstr(js, content_type_value, NULL); 183 + } 184 + 185 + if (!http_writer_parse_bytes(js, nargs > 3 ? args[3] : js_mkundef(), &body, &body_len, &error)) return error; 186 + keep_alive = nargs > 4 && js_truthy(js, args[4]); 187 + 188 + ant_http1_buffer_init(&buf); 189 + if (!ant_http1_write_basic_response(&buf, status, status_text, content_type, body, body_len, keep_alive)) { 190 + ant_http1_buffer_free(&buf); 191 + return js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 192 + } 193 + 194 + return http_writer_make_buffer_value(js, &buf); 195 + } 196 + 197 + static ant_value_t js_http_writer_write_head(ant_t *js, ant_value_t *args, int nargs) { 198 + ant_http1_buffer_t buf; 199 + ant_value_t error = js_mkundef(); 200 + 201 + int status = nargs > 0 ? (int)js_getnum(args[0]) : 200; 202 + const char *status_text = NULL; 203 + ant_value_t raw_headers = js_mkundef(); 204 + 205 + bool body_is_stream = false; 206 + size_t body_size = 0; 207 + bool keep_alive = false; 208 + int index = 1; 209 + 210 + if (nargs > index && vtype(args[index]) != T_UNDEF && vtype(args[index]) != T_NULL && vtype(args[index]) != T_ARR) { 211 + ant_value_t status_text_value = js_tostring_val(js, args[index]); 212 + if (is_err(status_text_value)) return status_text_value; 213 + status_text = js_getstr(js, status_text_value, NULL); 214 + index++; 215 + } 216 + 217 + if (nargs > index) raw_headers = args[index++]; 218 + if (nargs > index) body_is_stream = js_truthy(js, args[index++]); 219 + if (nargs > index) body_size = (size_t)js_getnum(args[index++]); 220 + if (nargs > index) keep_alive = js_truthy(js, args[index++]); 221 + 222 + ant_http1_buffer_init(&buf); 223 + if (!ant_http1_buffer_appendf(&buf, "HTTP/1.1 %d %s\r\n", status, status_text ? status_text : ant_http1_default_status_text(status))) { 224 + ant_http1_buffer_free(&buf); 225 + return js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 226 + } 227 + 228 + if (!http_writer_append_raw_headers(js, &buf, raw_headers, &error)) { 229 + ant_http1_buffer_free(&buf); 230 + return error; 231 + } 232 + 233 + if (body_is_stream) ant_http1_buffer_append_cstr(&buf, "Transfer-Encoding: chunked\r\n"); 234 + else ant_http1_buffer_appendf(&buf, "Content-Length: %zu\r\n", body_size); 235 + ant_http1_buffer_append_cstr(&buf, keep_alive ? "Connection: keep-alive\r\n\r\n" : "Connection: close\r\n\r\n"); 236 + 237 + if (buf.failed) { 238 + ant_http1_buffer_free(&buf); 239 + return js_mkerr_typed(js, JS_ERR_TYPE, "Out of memory"); 240 + } 241 + 242 + return http_writer_make_buffer_value(js, &buf); 243 + } 244 + 245 + ant_value_t internal_http_writer_library(ant_t *js) { 246 + ant_value_t lib = js_mkobj(js); 247 + 248 + js_set(js, lib, "defaultStatusText", js_mkfun(js_http_writer_default_status_text)); 249 + js_set(js, lib, "writeHead", js_mkfun(js_http_writer_write_head)); 250 + js_set(js, lib, "writeBasicResponse", js_mkfun(js_http_writer_write_basic_response)); 251 + js_set(js, lib, "writeChunk", js_mkfun(js_http_writer_write_chunk)); 252 + js_set(js, lib, "writeFinalChunk", js_mkfun(js_http_writer_write_final_chunk)); 253 + 254 + return lib; 255 + }
+3 -3
src/modules/server.c
··· 318 318 size_t out_len = 0; 319 319 320 320 ant_http1_buffer_init(&buf); 321 - if (!ant_http1_write_basic_response(&buf, status, status_text, content_type, body, body_len)) { 321 + if (!ant_http1_write_basic_response(&buf, status, status_text, content_type, body, body_len, false)) { 322 322 ant_http1_buffer_free(&buf); 323 323 ant_conn_close(conn); 324 324 return; ··· 378 378 status_text = (resp->status_text && resp->status_text[0]) ? resp->status_text : ant_http1_default_status_text(resp->status); 379 379 380 380 ant_http1_buffer_init(&buf); 381 - if (!ant_http1_write_response_head(&buf, resp->status, status_text, headers, body_is_stream, resp->body_size)) { 381 + if (!ant_http1_write_response_head(&buf, resp->status, status_text, headers, body_is_stream, resp->body_size, false)) { 382 382 ant_http1_buffer_free(&buf); 383 383 ant_conn_close(req->conn); 384 384 return; ··· 716 716 ant_http1_parse_result_t parse_result = ANT_HTTP1_PARSE_INCOMPLETE; 717 717 if (!conn) return; 718 718 719 - parse_result = ant_http1_parse_request(ant_conn_buffer(conn), ant_conn_buffer_len(conn), &parsed, NULL); 719 + parse_result = ant_http1_parse_request(ant_conn_buffer(conn), ant_conn_buffer_len(conn), &parsed, NULL, NULL); 720 720 if (parse_result == ANT_HTTP1_PARSE_ERROR) { 721 721 ant_http1_free_parsed_request(&parsed); 722 722 server_send_text_response(conn, 400, "Bad Request", "Bad Request");