Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to submit HTTP requests with WebAssembly?

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;
}
like image 601
Dmitrii Pisarenko Avatar asked Aug 30 '18 17:08

Dmitrii Pisarenko


3 Answers

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.

like image 73
ColinE Avatar answered Oct 25 '22 22:10

ColinE


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.

like image 37
sbc100 Avatar answered Oct 25 '22 22:10

sbc100


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.

like image 29
Sora2455 Avatar answered Oct 25 '22 22:10

Sora2455