From 8aedbcb6b31ceb73f858357aeec071bca5783d47 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Thu, 4 Jan 2024 01:01:11 -0500 Subject: [PATCH] support post requests and json request options --- client/main.c | 45 ++++++++++++++++++++++++++++++++++++++++----- client/main.js | 42 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/client/main.c b/client/main.c index 1f4f6f8..f0dae46 100644 --- a/client/main.c +++ b/client/main.c @@ -6,7 +6,10 @@ #include #include -int write_function(void *data, size_t size, size_t nmemb, void(*data_callback)(char* chunk_ptr, int chunk_size)) { +typedef void(*DataCallback)(char* chunk_ptr, int chunk_size); +typedef void(*EndCallback)(int error); + +int write_function(void *data, size_t size, size_t nmemb, DataCallback data_callback) { long real_size = size * nmemb; char* chunk = malloc(real_size); memcpy(chunk, data, real_size); @@ -15,7 +18,7 @@ int write_function(void *data, size_t size, size_t nmemb, void(*data_callback)(c return real_size; } -void perform_request(const char* url, const char* json_params, void(*data_callback)(char* chunk_ptr, int chunk_size), void(*end_callback)(int error)) { +void perform_request(const char* url, const char* json_params, DataCallback data_callback, EndCallback end_callback, const char* body, int body_length) { printf("downloading %s\n", url); CURL *http_handle; @@ -38,13 +41,44 @@ void perform_request(const char* url, const char* json_params, void(*data_callba //parse json options cJSON* json = cJSON_Parse(json_params); cJSON* item = NULL; + struct curl_slist* headers_list = NULL; + cJSON_ArrayForEach(item, json) { char* key = item->string; - printf("%s\n", key); + + if (strcmp(key, "_libcurl_verbose") == 0) { + curl_easy_setopt(http_handle, CURLOPT_VERBOSE, 1L); + } + + if (strcmp(key, "method") == 0 && cJSON_IsString(item)) { + curl_easy_setopt(http_handle, CURLOPT_CUSTOMREQUEST, item->valuestring); + } + + if (strcmp(key, "headers") == 0 && cJSON_IsObject(item)) { + cJSON* header = NULL; + + cJSON_ArrayForEach(header, item) { + if (!cJSON_IsString(header)) continue; + int header_length = strlen(header->string) + strlen(header->valuestring) + 2; + char* header_str = malloc(header_length+1); + header_str[header_length] = 0; + + sprintf(header_str, "%s: %s", header->string, header->valuestring); + headers_list = curl_slist_append(headers_list, header_str); + free(header_str); + } + + curl_easy_setopt(http_handle, CURLOPT_HTTPHEADER, headers_list); + } } cJSON_Delete(json); - + //add post data if specified + if (body != NULL) { + curl_easy_setopt(http_handle, CURLOPT_POSTFIELDS, body); + curl_easy_setopt(http_handle, CURLOPT_POSTFIELDSIZE, body_length); + } + multi_handle = curl_multi_init(); curl_multi_add_handle(multi_handle, http_handle); @@ -64,7 +98,8 @@ void perform_request(const char* url, const char* json_params, void(*data_callba emscripten_sleep(0); } while(still_running); - + + curl_slist_free_all(headers_list); curl_multi_remove_handle(multi_handle, http_handle); curl_easy_cleanup(http_handle); curl_multi_cleanup(multi_handle); diff --git a/client/main.js b/client/main.js index ff92473..79dea15 100644 --- a/client/main.js +++ b/client/main.js @@ -1,13 +1,20 @@ -const cacert_path = "./out/cacert.peem"; +const cacert_path = "./out/cacert.pem"; const websocket_url = `wss://${location.hostname}/ws`; +function is_str(obj) { + return typeof obj === 'string' || obj instanceof String; +} + function allocate_str(str) { return allocate(intArrayFromString(str), ALLOC_NORMAL); } +function allocate_array(array) { + return allocate(array, ALLOC_NORMAL); +} + //make emscripten shut up about unsupported syscalls -function silence_errs() { - let is_str = obj => typeof obj === 'string' || obj instanceof String; +function silence_errs() { window._err = window.err; window.err = function() { @@ -29,18 +36,25 @@ function silence_errs() { } //low level interface with c code -function perform_request(url, params, js_data_callback, js_end_callback) { +function perform_request(url, params, js_data_callback, js_end_callback, body=null) { let params_str = JSON.stringify(params); let end_callback_ptr; let data_callback_ptr; let url_ptr = allocate_str(url); let params_ptr = allocate_str(params_str); + let body_ptr = null; + let body_length = 0; + if (body) { //assume body is an int8array + body_ptr = allocate_array(body); + body_length = body.length; + } + let end_callback = (error) => { Module.removeFunction(end_callback_ptr); Module.removeFunction(data_callback_ptr); + if (body_ptr) _free(body_ptr); _free(url_ptr); - _free(params_ptr); if (error) console.error("request failed with error code "+error); js_end_callback(error); @@ -54,7 +68,8 @@ function perform_request(url, params, js_data_callback, js_end_callback) { end_callback_ptr = Module.addFunction(end_callback, "vi"); data_callback_ptr = Module.addFunction(data_callback, "vii"); - _perform_request(url_ptr, params_ptr, data_callback_ptr, end_callback_ptr); + _perform_request(url_ptr, params_ptr, data_callback_ptr, end_callback_ptr, body_ptr, body_length); + _free(params_ptr); } function merge_arrays(arrays) { @@ -69,6 +84,17 @@ function merge_arrays(arrays) { } function libcurl_fetch(url, params={}) { + let body = null; + if (params.body) { + if (is_str(params.body)) { + body = new TextEncoder().encode(params.body); + } + else { + body = Uint8Array.from(params); + } + params.body = true; + } + return new Promise((resolve, reject) => { let chunks = []; let data_callback = (new_data) => { @@ -79,13 +105,13 @@ function libcurl_fetch(url, params={}) { let response_str = new TextDecoder().decode(response_data); resolve(response_str); } - perform_request(url, params, data_callback, finish_callback); + perform_request(url, params, data_callback, finish_callback, body); }) } async function main() { silence_errs(); - console.log(await libcurl_fetch("https://ifconfig.me/all")); + console.log(await libcurl_fetch("https://httpbin.org/anything")); } window.onload = () => {