/* * httpclient_web.cpp — emscripten_fetch backend. * * emscripten_fetch is async and fires onsuccess/onerror on the main thread. * We attach a small heap-owned context to userData; the trampolines invoke * the user callback and free the context. * * http_pump() is a no-op because the runtime drives completion delivery. */ #ifdef __EMSCRIPTEN__ #include "httpclient.h" #include #include #include namespace { struct ctx_t { http_callback_t cb; void *user; }; void deliver(emscripten_fetch_t *fetch, int status) { ctx_t *c = static_cast(fetch->userData); http_response_t resp; resp.status = status; resp.body = fetch->data ? fetch->data : ""; resp.len = (size_t)fetch->numBytes; c->cb(&resp, c->user); emscripten_fetch_close(fetch); delete c; } void on_success(emscripten_fetch_t *fetch) { deliver(fetch, (int)fetch->status); } void on_error(emscripten_fetch_t *fetch) { // Distinguish: a non-2xx with body (e.g. 500 + JSON) reports its status; // a true transport failure (no connection, CORS reject) reports 0. int status = (fetch->status >= 100 && fetch->status < 600) ? (int)fetch->status : 0; deliver(fetch, status); } void issue(const char *method, const char *url, const char *body, http_callback_t cb, void *user) { emscripten_fetch_attr_t attr; emscripten_fetch_attr_init(&attr); strncpy(attr.requestMethod, method, sizeof(attr.requestMethod) - 1); attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; attr.onsuccess = on_success; attr.onerror = on_error; static const char *headers[] = { "Content-Type", "application/json", nullptr }; if(body) { attr.requestHeaders = headers; attr.requestData = body; attr.requestDataSize = strlen(body); } auto *c = new ctx_t{cb, user}; attr.userData = c; emscripten_fetch(&attr, url); } } // namespace extern "C" void http_init(void) {} extern "C" void http_shutdown(void) {} extern "C" void http_pump(void) {} extern "C" void http_post_json(const char *url, const char *body, http_callback_t cb, void *user) { if(!cb) return; issue("POST", url, body ? body : "", cb, user); } extern "C" void http_get(const char *url, http_callback_t cb, void *user) { if(!cb) return; issue("GET", url, nullptr, cb, user); } #endif /* __EMSCRIPTEN__ */