使用WebAssembly能否提交HTTP请求?

19

我正在尝试在WebAssembly中提交一个简单的HTTP GET请求。 为此,我编写了这个程序(从 Emscripten网站 复制并稍作修改):

#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;
}

当我使用$EMSCRIPTEN/emcc main.c -O1 -s MODULARIZE=1 -s WASM=1 -o main.js --emrun -s FETCH=1编译它时,我会得到错误信息。

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

有没有一种方法可以从WebAssembly运行HTTP请求? 如果有,我该怎么做?

更新1:以下代码尝试发送一个GET请求,但由于CORS问题而失败。

#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;
}

2
答案与 https://dev59.com/yq7la4cB1Zd3GeqPVwIB 大致相同。您可以导入一个知道如何发出请求的 JS 函数,并从 Webassembly 中“调用”它。 - Matt Harrison
3个回答

11

不,你不能从WebAssembly执行HTTP请求(或访问DOM或任何其他浏览器API)。WebAssembly本身没有访问其主机环境的权限,因此它没有任何内置的IO功能。

但是,您可以从WebAssembly导出函数,并从主机环境导入函数。这将允许您通过主机间接地进行HTTP请求。


谢谢。关于从宿主环境导入函数:你能否指出一份进行HTTP请求的函数文档? - Glory to Russia
除非我误解了什么,否则似乎很快就可以从WebAssembly本身发出请求了?https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/ - user10898116
@user10898116,这似乎是用于在浏览器以外的地方运行WebAssembly。我认为问题更多地涉及如何从在浏览器中运行的WebAssembly提交HTTP请求。目前似乎WebAssembly除了进行纯逻辑和计算之外,无法进行其他任何操作,而且必须通过与JavaScript的通信来实现。除了通过JavaScript接口之外,我认为WebAssembly代码实际上不能影响任何东西,因此它不能通过自身进行HTTP通信、保存文件或以其他方式对任何真正的变化产生影响。 - still_dreaming_1
实际上,WASI似乎是旨在潜在地在浏览器内运行,因此你可能是正确的。我不太清楚这是否打算最终与WASM一起出现在所有浏览器中,或者关于WASI的更多信息。 - still_dreaming_1

8

如果我将Emscripten SDK安装到Windows 10的Ubuntu子系统中,我该如何更新它? - Glory to Russia

1

很遗憾,无论是从任何网站还是其他网站,都没有办法向Google.com发起CORS请求。

来自MDN:

出于安全原因,浏览器限制了从脚本中发起的跨源HTTP请求。例如,XMLHttpRequest和Fetch API遵循同源策略。这意味着使用这些API的Web应用程序只能从加载该应用程序的相同来源请求HTTP资源,除非来自其他来源的响应包括正确的CORS标头。

Google不包括这些标头。

由于JavaScript / WebAssembly在客户端机器上运行(而不是您的机器),如果没有这个功能,您可能会做一些令人讨厌的事情,比如使用客户端的cookie向www.mybankingwebsite.com/makeTransaction发起POST请求。

如果您想将Update 1中的代码指向自己的网站或在Node.js上运行它,那么它应该可以正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接