19

I'm trying to submit a simple HTTP GET request in WebAssembly. For this purpose, I wrote this program (copied from Emscripten site with slight modifications):

#include <stdio.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/fetch.h>
#include <emscripten.h>
#endif


void downloadSucceeded(emscripten_fetch_t *fetch) {
  printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
  // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
  emscripten_fetch_close(fetch); // Free data associated with the fetch.
}

void downloadFailed(emscripten_fetch_t *fetch) {
  printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
  emscripten_fetch_close(fetch); // Also free data on failure.
}

unsigned int EMSCRIPTEN_KEEPALIVE GetRequest() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
  attr.onsuccess = downloadSucceeded;
  attr.onerror = downloadFailed;
  emscripten_fetch(&attr, "http://google.com");
  return 1;
}

When I compile it using $EMSCRIPTEN/emcc main.c -O1 -s MODULARIZE=1 -s WASM=1 -o main.js --emrun -s FETCH=1 I get the error

ERROR:root:FETCH not yet compatible with wasm (shared.make_fetch_worker is asm.js-specific)

Is there a way to run HTTP requests from WebAssembly? If yes, how can I do it?

Update 1: The following code attempts to send a GET request, but fails due to CORS issues.

#include <stdio.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/fetch.h>
#include <emscripten.h>
#endif

unsigned int EMSCRIPTEN_KEEPALIVE GetRequest() {
  EM_ASM({
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://google.com");
    xhr.send();
  });
  return 1;
}
Glory to Russia
  • 17,289
  • 56
  • 182
  • 325
  • 2
    The answer is much the same as https://stackoverflow.com/questions/52078564/how-can-i-access-the-dom-from-webassembly-text-format. You can import a JS function that knows how to make the request and `call` it from Webassembly – Matt Harrison Aug 31 '18 at 01:50

3 Answers3

11

No, you cannot execute HTTP request from WebAssembly (or access DOM, or any other browser APIs). WebAssembly by itself doesn’t have any access to its host environment, hence it doesn’t have any built in IO capabilities.

You can however export functions from WebAssembly, and import functions from the host environment. This will allow you to make HTTP requests indirectly via the host.

ColinE
  • 68,894
  • 15
  • 164
  • 232
  • Thanks. Re *import functions from the host environment*: Could you point to a documentation of functions for doing HTTP requests? – Glory to Russia Aug 31 '18 at 10:46
  • Unless I misunderstand something, it seems like it might soon be possible to make requests from within WebAssembly itself? https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/ –  May 17 '19 at 18:39
  • @user10898116 that seems to be for running WebAssembly in places other than the browser. I think the question is more about how to submit HTTP requests from WebAssembly running in a browser. It seems that WebAssembly is currently not able to do anything other than pure logic and calculations, without communicating to JavaScript. Other than through the JavaScript interface, I don't think WebAssembly code can actually affect anything, so it cannot communicate over HTTP, save stuff to files, or otherwise effect any real change by itself. – still_dreaming_1 Mar 15 '20 at 21:22
  • @user10898116 actually it does seem WASI was intended to potentially run inside a browser, so you could be right. I don't really know if this is intended to eventually be in all browsers alongside WASM, or much at all about WASI. – still_dreaming_1 Mar 15 '20 at 21:30
8

I recently ran across this issue with esmcripten fixed it in: https://github.com/kripken/emscripten/pull/7010

You should now be able to use FETCH=1 and WASM=1 together.

sbc100
  • 2,619
  • 14
  • 11
1

Unfortunately, there is no way to make a CORS request to Google.com from any website other than Google.com.

From MDN:

For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request HTTP resources from the same origin the application was loaded from, unless the response from the other origin includes the right CORS headers.

Google does not include those headers.

Because JavaScript/WebAssembly runs on the client's machine (not yours) you could do nasty things if this wasn't in place, like make POST requests to www.mybankingwebsite.com/makeTransaction with the client's cookies.

If you want to point the code you have in Update 1 to your own site, or run it on Node.js, it should work fine.

valiano
  • 16,433
  • 7
  • 64
  • 79
Sora2455
  • 744
  • 7
  • 25