diff options
author | Florian Dold <florian@dold.me> | 2023-03-29 20:58:11 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-03-29 20:58:11 +0200 |
commit | eba20fd31342bdbbaba85ee23591b1607b295de5 (patch) | |
tree | ece4cb1b03ef2e2384e5a295278e6bf46b0f4484 | |
parent | f3799415a97108df72e047437b3a4e40270871bf (diff) | |
download | quickjs-tart-eba20fd31342bdbbaba85ee23591b1607b295de5.tar.gz quickjs-tart-eba20fd31342bdbbaba85ee23591b1607b295de5.tar.bz2 quickjs-tart-eba20fd31342bdbbaba85ee23591b1607b295de5.zip |
only add certain request headers if client did not provide them
-rw-r--r-- | quickjs/quickjs-libc.c | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c index 025bf91..643557c 100644 --- a/quickjs/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -2117,6 +2117,8 @@ typedef struct { size_t readpos; size_t readlen; CURL *curl; + BOOL client_has_accept_header; + BOOL client_has_content_type_header; } CurlRequestContext; static size_t curl_header_callback(char *buffer, size_t size, @@ -2178,7 +2180,20 @@ int expect_property_str_bool(JSContext *ctx, JSValueConst this_val, const char * return bool_val; } -static int gather_headers(JSContext *ctx, JSValueConst js_headers, struct curl_slist **headers) +BOOL starts_with_ignorecase(const char *str, const char *prefix) +{ + for (int i = 0; i < strlen(prefix); i++) { + if (!str[i]) { + return FALSE; + } + if (tolower(str[i]) != tolower(prefix[i])) { + return FALSE; + } + } + return TRUE; +} + +static int gather_headers(JSContext *ctx, JSValueConst js_headers, CurlRequestContext *req_context) { JSValue length_prop; uint32_t length; @@ -2198,11 +2213,16 @@ static int gather_headers(JSContext *ctx, JSValueConst js_headers, struct curl_s goto exception; } const char *cstr = JS_ToCString(ctx, item); + if (starts_with_ignorecase(cstr, "accept:")) { + req_context->client_has_accept_header = TRUE; + } else if (starts_with_ignorecase(cstr, "content-type:")) { + req_context->client_has_content_type_header = TRUE; + } if (!cstr) { JS_FreeValue(ctx, item); goto exception; } - *headers = curl_slist_append (*headers, cstr); + req_context->headers = curl_slist_append (req_context->headers, cstr); JS_FreeCString(ctx, cstr); JS_FreeValue(ctx, item); } @@ -2338,6 +2358,7 @@ static JSValue js_os_fetchHttp(JSContext *ctx, JSValueConst this_val, } curl_easy_setopt(req_context->curl, CURLOPT_PRIVATE, req_context); curl_easy_setopt(req_context->curl, CURLOPT_URL, req_url); + curl_easy_setopt(req_context->curl, CURLOPT_USERAGENT, "qtart"); curl_easy_setopt(req_context->curl, CURLOPT_CAINFO, "/etc/ssl/certs/ca-certificates.crt"); curl_easy_setopt(req_context->curl, CURLOPT_HEADERFUNCTION, curl_header_callback); curl_easy_setopt(req_context->curl, CURLOPT_HEADERDATA, req_context); @@ -2352,11 +2373,27 @@ static JSValue js_os_fetchHttp(JSContext *ctx, JSValueConst this_val, curl_easy_setopt(req_context->curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(req_context->curl, CURLOPT_SSL_VERIFYHOST, 0); + if (JS_VALUE_GET_TAG(options) == JS_TAG_OBJECT) { + JSValue header_item = JS_GetPropertyStr(ctx, options, "headers"); + if (JS_IsException(header_item)) { + goto exception; + } + if (JS_VALUE_GET_TAG(header_item) == JS_TAG_OBJECT) { + if (0 != gather_headers(ctx, header_item, req_context)) { + JS_FreeValue(ctx, header_item); + goto exception; + } + } + JS_FreeValue(ctx, header_item); + } + method_str = JS_ToCString(ctx, method); if (0 == strcasecmp(method_str, "get")) { curl_easy_setopt(req_context->curl, CURLOPT_HTTPGET, 1L); - req_context->headers = curl_slist_append (req_context->headers, "Accept: application/json"); + if (!req_context->client_has_accept_header) { + req_context->headers = curl_slist_append (req_context->headers, "Accept: application/json"); + } } else if (0 == strcasecmp(method_str, "post")) { JSValue data; uint8_t *data_ptr; @@ -2377,26 +2414,14 @@ static JSValue js_os_fetchHttp(JSContext *ctx, JSValueConst this_val, curl_easy_setopt(req_context->curl, CURLOPT_POST, 1L); curl_easy_setopt(req_context->curl, CURLOPT_READFUNCTION, read_callback); curl_easy_setopt(req_context->curl, CURLOPT_READDATA, req_context); - req_context->headers = curl_slist_append(req_context->headers, "Content-Type: application/json"); + if (!req_context->client_has_content_type_header) { + req_context->headers = curl_slist_append(req_context->headers, "Content-Type: application/json"); + } } else { JS_ThrowTypeError(ctx, "invalid request method"); goto exception; } - if (JS_VALUE_GET_TAG(options) == JS_TAG_OBJECT) { - JSValue header_item = JS_GetPropertyStr(ctx, options, "headers"); - if (JS_IsException(header_item)) { - goto exception; - } - if (JS_VALUE_GET_TAG(header_item) == JS_TAG_OBJECT) { - if (0 != gather_headers(ctx, header_item, &req_context->headers)) { - JS_FreeValue(ctx, header_item); - goto exception; - } - } - JS_FreeValue(ctx, header_item); - } - curl_easy_setopt(req_context->curl, CURLOPT_HTTPHEADER, req_context->headers); mres = curl_multi_add_handle(ts->curlm, req_context->curl); |