summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-03-29 20:58:11 +0200
committerFlorian Dold <florian@dold.me>2023-03-29 20:58:11 +0200
commiteba20fd31342bdbbaba85ee23591b1607b295de5 (patch)
treeece4cb1b03ef2e2384e5a295278e6bf46b0f4484
parentf3799415a97108df72e047437b3a4e40270871bf (diff)
downloadquickjs-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.c61
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);