(Wannabe-awesome) list of approaches (recipes, frameworks, http client libraries, etc) to send outbound HTTP(S) requests from inside WebAssembly.
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
L : aliased Listener;
xhr : Web.XHR.Requests.XML_Http_Request;
overriding procedure Handle_Event
(Self : in out Listener; Event : in out Web.DOM.Events.Event'Class)
is
use type Web.XHR.Requests.State;
begin
if xhr.Get_Ready_State = Web.XHR.Requests.DONE then
WASM.Console.Log (xhr.Get_Response_Text);
end if;
end Handle_Event;
procedure Initialize_Example is
begin
xhr := Web.XHR.Requests.Constructors.New_XML_Http_Request;
xhr.Open ("GET", "https://httpbin.org/anything");
xhr.Send ("");
xhr.Add_Event_Listener ("readystatechange", L'Access);
end Initialize_Example; |
Browser |
Manual JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import { fetch } from "as-fetch/assembly";
export { responseHandler } from "as-fetch/assembly";
fetch("https://httpbin.org/anything", {
method: "GET",
mode: "no-cors",
headers: [],
body: null,
}).then((resp) => {
const text = resp.text();
}); |
Browser, Node.js, and Deno |
JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
DIM res AS STRING
' Custom function
res = HTTPGET("https://httpbin.org/anything")
PRINT res |
Type |
Browser |
||||
REM Custom function
res$ = HTTPGET ("https://httpbin.org/anything")
PRINT res$ |
Uses
Golang's |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
# custom function
print(httpget('https://httpbin.org/anything')) |
Browser |
JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
@using System.Net.Http.Json
@inject HttpClient HttpClient
@code {
var data = await HttpClient.GetFromJsonAsync<JsonElement>(
"https://httpbin.org/anything");
} |
Demo by JasonWatmore Demo source |
Browser, also native server-side |
JS |
|||
Standard library |
using System;
using System.Net.Http;
HttpClient client = new HttpClient();
string uri = "https://httpbin.org/anything";
string responseText = await client.GetStringAsync(uri);
Console.WriteLine("body: " + responseText); |
JS |
||||
// Uno Platform's own way
// Deprecated since .NET 6,
// use 'System.Net.Http.HttpClient' and 'HttpHandler' instead
// See https://github.com/unoplatform/uno/issues/9665
using System.Net.Http;
using (var handler = new Uno.UI.Wasm.WasmHttpHandler())
using (var client = new HttpClient(handler))
{
var request = new HttpRequestMessage(HttpMethod.Get,
new Uri("https://httpbin.org/anything"));
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
} |
Browser |
JS Interop invokes the TS
wrapper for |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
#include <emscripten/fetch.h>
void requestOnSuccess(emscripten_fetch_t *fetch)
{
char dat[fetch->numBytes + 1];
memcpy(dat, fetch->data, fetch->numBytes);
dat[fetch->numBytes] = '\0';
printf("data: %s \n", dat);
emscripten_fetch_close(fetch);
}
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
attr.onsuccess = requestOnSuccess;
emscripten_fetch(&attr, "https://httpbin.org/anything"); |
Browser |
JS |
||||
#include <xxhr/xxhr.hpp>
using namespace xxhr;
GET( "https://httpbin.org/anything"s,
on_response = [](auto res) { std::cout << res.text; }
); |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
require "js"
class XMLHttpRequest < JS::Reference
@[JS::Method]
def self.new : self
<<-js
return new XMLHttpRequest();
js
end
js_getter responseText : String
js_method send
js_method open(method : String, url : String, async : Int32)
end
req = XMLHttpRequest.new
req.open("GET", "https://httpbin.org/anything", 0)
req.send
JS.console.log req.response_text |
Browser, Node.js, and Deno |
Manual JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import 'package:dio/dio.dart';
final dio = Dio();
Response response = await dio.get(
'https://httpbin.org/anything');
print(response); |
Browser with Wasm-GC support enabled1 |
JS |
||||
import 'package:fetch_api/fetch_api.dart';
final resp = await fetch(
'https://httpbin.org/anything');
final txt = await resp.text();
print('${txt}'); |
JS |
|||||
import 'package:fetch_client/fetch_client.dart';
final client = FetchClient(
mode: RequestMode.cors);
final uri = Uri.parse(
'https://httpbin.org/anything');
final resp = await client.get(uri);
print('${resp.body}');
client.close(); |
Extends the
|
|||||
import 'package:http/http.dart' as http;
final resp = await http.get(
Uri.parse('https://httpbin.org/anything'));
print('${resp.body}'); |
Browser with Wasm-GC support enabled1 |
JS |
||||
import 'package:web/web.dart' as web;
final resp = await web.window.fetch(
'https://httpbin.org/anything'.toJS).toDart;
final txt = await resp.text().toDart;
print('${txt}'); |
Browser with Wasm-GC support enabled1 |
Direct |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
: URL$ S" https://httpbin.org/anything" ;
( custom word )
URL$ HTTPGET |
JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import "net/http"
resp, err := http.Get("https://httpbin.org/anything") |
Browser and Node.js |
|||||
Save 4 MB of wasm binary size |
import "marwan.io/wasm-fetch"
resp, err := fetch.Fetch("https://httpbin.org/anything",
&fetch.Opts{})
if err == nil {
println(string(resp.Body))
} |
Browser and Node.js |
Direct JS |
|||
import "github.com/Nigel2392/requester"
var client = requester.NewAPIClient()
client.Get("https://httpbin.org/anything").Do(
func(response *http.Response) {
body, err := io.ReadAll(response.Body)
if err == nil {
fmt.Println(string(body))
}
}
) |
Browser and maybe Node.js |
Uses
Golang's |
||||
SPA framework |
import (
"github.com/realPy/hogosuru"
"github.com/realPy/hogosuru/base/fetch"
"github.com/realPy/hogosuru/base/promise"
"github.com/realPy/hogosuru/base/response"
)
f, err := fetch.New("https://httpbin.org/anything", nil)
f.Then(func(r response.Response) *promise.Promise {
txtpromise, _ := f.Then(
func(r response.Response) *promise.Promise {
if prm, err := r.Text(); hogosuru.AssertErr(err) {
return &prm
}
return nil
}, nil)
txtpromise.Then(func(i interface{}) *promise.Promise {
fmt.Println(i.(string))
return nil
}, nil)
return nil
}, nil) |
Browser |
Manual low-level JS |
|||
UI library |
import "io"
import "log"
import "net/http"
go func() {
resp, _ := http.Get(action.Url)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
log.Println(string(body))
}() |
Browser |
Has no built-in solutions, just directly invoking
Golang's |
|||
UI library |
import "io"
import "log"
import "net/http"
resp, _ := http.Get("https://httpbin.org/anything")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
log.Println(string(body)) |
Possible with Dev Container |
Browser |
Has no built-in solutions, just directly invoking Golang's |
||
It's VM / interpreter |
import (
"fmt"; "io"; "net/http"
)
resp, _ := http.Get("https://httpbin.org/anything")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body)) |
Directly invoking
Golang's |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
var http = import("net/http")
var ioutil = import("io/ioutil")
var url = "https://httpbin.org/anything"
res, _ = http.DefaultClient.Get(url)
b, _ = ioutil.ReadAll(res.Body)
println(toString(b))
res.Body.Close() |
Browser and maybe Node |
Directly invoking
Golang's |
||||
url := "https://httpbin.org/anything"
resp := fetch(url)
print(resp.text()) |
Browser and maybe Node |
Using
Golang's |
||||
for Tengo |
fmt := import("fmt")
http := import("httpclient")
resp := http.request("https://httpbin.org/anything", "GET")
fmt.print(is_error(resp) ? resp : resp.body) |
Using
Golang's |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
transpile JVM bytecode to Wasm |
import de.mirkosertic.bytecoder.api.web.*;
final Window win = Window.window();
final Console con = Console.console();
win.fetch("https://httpbin.org/anything").then(
new Promise.Handler<Response>() {
@Override
public void handleObject(final Response resp) {
resp.text().then(new StringPromise.Handler() {
@Override
public void handleString(final String text) {
con.log(text);
}
});
}
}); |
Browser, Node.js, and Deno |
Possible, but why?
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
Requires server-side counterpart |
libcurl.set_websocket(
'wss://your-wisp-proxy.yoursite.tld/');
let res = await libcurl.fetch(
'https://httpbin.org/anything');
console.log(await res.text()); |
Browser |
Tunneling TCP to WebSocket using protocols "wisp" or "wsproxy" . |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
// Host function
const txt = await fetch('https://httpbin.org/anything');
console.log(txt); |
JS |
|||||
const fn = async () => {
// Host function
const res = await fetch(
'https://httpbin.org/anything');
return res.text();
}
export default await fn(); |
Wrapper over quickjs-emscripten,
uses host function |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
// custom object
http.get('https://httpbin.org/anything'); |
Browser |
Using
.NET's |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
const res = httpget('https://httpbin.org/anything');
console.log(res); |
Using
Golang's |
|||||
fetch('https://httpbin.org/anything')
.then(function(res) {
return res.text();
}).then(function(txt) {
console.log(txt);
exitloop();
}); |
Injecting a custom function into JS.
That func uses the goproxy as HTTP client,
which is a wrapper for Golang's |
|||||
const res = httpget('https://httpbin.org/anything');
console.log(res); |
Using
Golang's |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
still Alpha |
import kotlinx.browser.window
window.fetch("https://httpbin.org/anything").then {
if (it.ok) {
it.text().then {
println(it)
null
}
}
null
} |
Browser with Wasm-GC and Wasm-Exception-Handling support enabled1, Node v21 and above, Deno v1.38 and above. |
Direct |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
# custom function
(print (httpget `https://httpbin.org/anything`)) |
Browser and maybe Node |
JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
local resp = fetch('https://httpbin.org/anything'):await()
local text = resp:text():await()
print(text) |
Direct |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
local http = require('http')
local res, err = http.request('GET',
'https://httpbin.org/anything', {
headers={
['User-Agent']='gluahttp/wasm'
}
})
print(res.body) |
Browser and maybe Node |
Using
Golang's |
||||
local http = require('http')
local client = http.client()
local req = http.request('GET',
'https://httpbin.org/anything')
local res, err = client:do_request(req)
print(res.body) |
Browser and maybe Node |
Using
Golang's |
||||
erdian718/lmodhttpclient aka ofunc/lmodhttpclient |
local io = require('io')
local httpclient = require('http/client')
local res = httpclient.get(
'https://httpbin.org/anything')
io.copy(res, io.stdout)
res:close() |
Browser and maybe Node |
Using
Golang's |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
local http = require 'pluto:http'
http.request('https://httpbin.org/anything')
|> print |
Browser and maybe Node. |
JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
Fork of PIB |
$url = 'https://httpbin.org/anything';
$window = new Vrzno();
$window->fetch($url)
->then(function($res) { return $res->text(); })
->then(var_dump(...)); |
|
Browser, Bun, Deno, Node, and CloudFlare Workers. |
Manual JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
function httpGet(url: ShortString; Var str_out:
ShortString): ShortString; external 'js';
var out_str : ShortString;
begin
out_str:= DupeString( ' ' , 255 );
httpGet('https://httpbin.org/anything', out_str);
writeln(out_str);
end. |
Browser and maybe Node |
Direct |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
use WebPerl qw/js js_new sub_once/;
my $xhr = js_new('XMLHttpRequest');
$xhr->addEventListener('load', sub_once {
print 'Done: '.$xhr->{responseText};
});
$xhr->open('GET', 'https://httpbin.org/anything', 0);
$xhr->send(); |
Browser, Node.js, and Deno |
Manual JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
from browser import fetch
fetch('https://httpbin.org/anything').then(
lambda resp: print((resp))) |
Browser, Node.js, and maybe Deno | |||||
from pyodide.http import pyfetch
response = await pyfetch("https://httpbin.org/anything") Also note that the pyodide-http is bundled in Pyodide. |
Browser, Node.js, and maybe Deno | |||||
# needs `await micropip.install(['pyodide-http', 'requests'])`
import pyodide_http
pyodide_http.patch_all()
import requests
response = requests.get("https://httpbin.org/anything") |
|
Browser and maybe Node.js |
JS |
|||
Since 2.2.0 |
import micropip
await micropip.install('urllib3')
import urllib3
res = urllib3.request('GET', 'https://httpbin.org/anything')
print(res.data.decode('utf-8')) # using requests
import micropip
await micropip.install('requests')
import requests
res = requests.get('https://httpbin.org/anything')
print(res.text) |
Browser only (yet) |
JS |
|||
import httpclient
print(httpclient.Get('https://httpbin.org/anything')) |
Using
Golang's |
|||||
from pyodide.http import pyfetch, FetchResponse
import asyncio
async def req() -> FetchResponse:
response = await pyfetch("https://httpbin.org/anything")
print(await response.string())
asyncio.ensure_future(req()) |
Browser | |||||
response = requests.get("https://httpbin.org/anything") |
Browser |
Employs koenvo/pyodide-http. Also direct |
||||
# using Pandas
import pyodide_http; pyodide_http.patch_all()
import pandas as pd
data = pd.read_json('https://httpbin.org/json')
data # using js.fetch
from js import fetch
res = await fetch('https://httpbin.org/anything')
text = await res.text()
print(text) # using requests
import micropip; await micropip.install(['requests'])
import pyodide_http; pyodide_http.patch_all()
import requests
res = requests.get("https://httpbin.org/anything")
print(res.text) |
Browser |
Employing |
||||
For pyjs |
import requests
r = requests.get('https://httpbin.org/anything')
result = r.text
print(result) |
Browser |
Direct |
|||
import js
fetch = JS('fetch')
response = fetch('https://httpbin.org/anything').wait()
text = response.text().wait()
print(text) |
Browser and Node.js |
Direct |
||||
a port of Streamlit to Wasm |
from pyodide.http import pyfetch
import streamlit as st
response = await pyfetch("https://httpbin.org/anything")
body = await response.string()
st.write(body) |
Browser | ||||
lightweight Python 3.x |
# custom module
import http
print(http.get('https://httpbin.org/anything')) |
Browser |
JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
It's compiler |
from javascript import Object, asynchronous, JSON
@asynchronous
def send_request(url):
fetch = Object('fetch')
res = fetch.call(url).wait()
text = res['text'].call().wait()
print(text)
return text
def target(*args): return main, None
def main(argv):
send_request('https://httpbin.org/anything')
return 0
if __name__ == '__main__':
import sys
main(sys.argv) |
Browser, Node.js, and Deno |
Direct |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
df <- read.csv("https://httpbin.org/anything")
print(df)
// All works: read.table() variants, download.file(), scan(), url(), etc |
Browser and Node |
Implemented |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
require 'js'
resp = JS.global.fetch('https://httpbin.org/anything').await
puts resp.text.await |
Direct JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
let window = web_sys::window().unwrap();
let resp_val = JsFuture::from(
window.fetch_with_str("https://httpbin.org/anything")).await?; |
Prints to browser console, source |
|||||
let mut resp = Fetch::Url(
"https://httpbin.org/anything"
.parse().unwrap(),
)
.send().await?;
let txt = resp.text().await?; |
JS |
|||||
let request = ehttp::Request::get("https://httpbin.org/anything");
ehttp::fetch(request, move |result: ehttp::Result<ehttp::Response>| {
println!("Text: {:?}", result.unwrap().text());
}); |
Browser, Node.js, and Deno.
Also native |
JS |
||||
let uri = Uri::from_static("https://httpbin.org/anything");
let req = Request::get(uri).body(None).unwrap();
let client = web_sys::window();
let resp = client.issue(req).await.unwrap();
println!("{}", resp.body()); |
Browser, Node.js, and Deno.
Also native |
JS |
||||
use http_client::HttpClient;
use http_types::{Method, Request};
use http_client::wasm::WasmClient as Client;
let client = Client::new();
let req = Request::new(Method::Get, "https://httpbin.org/anything");
client.send(req).await.unwrap();
dbg!(client); |
Browser, Node.js, and Deno Also native (and others). |
JS |
||||
use gloo_net::http::Request;
let resp = Request::get("https://httpbin.org/anything").send()
.await.unwrap(); |
Browser, Node.js, and Deno |
JS |
||||
// uses reqwest
let txt = reqwest::get("https://httpbin.org/anything")
.await?.text().await?;
log::info!("text: {}", txt); |
Browser |
Has no built-in solutions, just uses any suitable 3rd-party lib, such as: reqwest. |
||||
// uses reqwasm or gloo_net for CSR
use leptos_dom::logging::console_log;
let txt = reqwasm::http::Request::get(
"https://httpbin.org/anything")
.send().await?.text().await?;
console_log(txt.as_str()); |
Browser Also server-side rendering (SSR) |
Has no built-in solutions, just uses any suitable 3rd-party lib, such as: reqwest, gloo_net, reqwasm. |
||||
use localghost::prelude::*;
use localghost::{log, net};
let res = net::Request::get(
"https://httpbin.org/anything").send().await?;
log::info!("text: {:?}", res.body_string().await?); |
Browser and maybe Node |
JS |
||||
use zoon::{println, *};
let txt = reqwest::get("https://httpbin.org/anything")
.await?
.error_for_status()?
.text()
.await?;
println!("text: {}", txt); |
Browser |
Has no built-in solutions, just uses any suitable 3rd-party lib, such as: reqwest. |
||||
let txt = reqwest::get("https://httpbin.org/anything")
.await?.text().await?;
println!("Text: {:?}", txt); |
Browser, Node.js, and Deno
Also native |
JS |
||||
use reqwasm::http::Request;
let resp = Request::get("https://httpbin.org/anything").send()
.await.unwrap(); |
Browser, Node.js, and Deno | |||||
use sauron::dom::{Http, spawn_local};
spawn_local(async move {
let txt = Http::fetch_text(
"https://httpbin.org/anything").await.unwrap();
log::trace!("{}", txt);
}); |
Browser
Also server-side rendering (SSR) |
JS |
||||
use seed::{prelude::*, *};
let response = fetch("https://httpbin.org/anything").await?;
let body = response.text().await?; |
Browser, Node.js, and Deno |
JS |
||||
let mut resp = surf::get("https://httpbin.org/anything").await?;
println!("{}", resp.body_string().await?); |
Browser, Node.js, and Deno
Also native |
Uses http-rs/http-client as WASM backend |
||||
// uses reqwasm
use reqwasm::http::Request;
let url = "https://httpbin.org/anything";
let res = Request::get(&url).send().await?;
let txt = res.text().await?;
log::info!("{}", txt); |
Browser |
Has no built-in solutions, just uses any suitable 3rd-party lib, such as: reqwasm. |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
let req = http::get(
"https://httpbin.org/anything").await?;
let txt = req.text().await?;
println(txt); |
Browser |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
# custom function
print(httpget('https://httpbin.org/anything')) |
Using
Golang's |
|||||
res = http.get('https://httpbin.org/anything')
print(res.body) |
Using
Golang's |
|||||
"Starlark's missing stdlib" |
load('http.star', 'http')
res = http.get('https://httpbin.org/anything')
print(res.body()) |
Using
Golang's |
||||
# custom function
print(httpget('https://httpbin.org/anything')) |
Using
Golang's |
|||||
Maintained fork of Starlight |
# custom function
print(httpget('https://httpbin.org/anything')) |
Using
Golang's |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import JavaScriptEventLoop
import JavaScriptKit
JavaScriptEventLoop.installGlobalExecutor()
let fetch = JSObject.global.fetch.function!
let resp = try! await JSPromise(
fetch("https://httpbin.org/anything").object!)!.value
let text = try! await JSPromise(resp.text().object!)!.value
print(text) |
Browser, Node.js, and Deno |
Direct |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
# custom command
puts [httpget "https://httpbin.org/anything"] |
Uses
Golang's |
|||||
set func_ptr_number 2
puts [::wacl::jscall $func_ptr_number "string" "string" "https://httpbin.org/anything"] Needs a JavaScript-side function registered using wacl.onReady(function (interpreter) {
const wrappedFuncName = interpreter.jswrap(function (ptrUrl) {
const url = interpreter.ptr2str(ptrUrl);
const xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send();
return interpreter.str2ptr(xhr.responseText);
}, 'string', 'string');
}); |
Browser |
Manual JS |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
Local request := New HttpRequest
request.ReadyStateChanged = Lambda()
If request.ReadyState = ReadyState.Done Then
Print "Body: " + request.ResponseText
End
End
request.Open("GET", "https://httpbin.org/anything")
request.Send() |
Browser |
JS |
Standalone and server-side runtimes (mostly WASI and WASI-Socket-enabled), incl containers, FaaS, Edge Computing, etc
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import {
Method, RequestBuilder, Response
} from "@deislabs/wasi-experimental-http";
import { Console } from "as-wasi/assembly";
let resp = new RequestBuilder("https://httpbin.org/anything")
.header("User-Agent", "wasm32-wasi-http")
.method(Method.GET)
.send();
let text = String.UTF8.decode(resp.bodyReadAll().buffer);
Console.log(text); |
Dev Container created by brendandburns |
Wasmtime with integrated |
Importing npm package which calls imported host function implemented in wasi-experimental-http-wasmtime Wasmtime's WASI module. |
|||
// Identical to wasi-experimental-http currently
// Needs `npm i https://github.com/brendandburns/wasi-http-ts`
import {
Method, RequestBuilder
} from "@brendandburns/wasi-http-ts";
import { Console } from "as-wasi/assembly";
let resp = new RequestBuilder("https://httpbin.org/anything")
.header("User-Agent", "wasm32-wasi-http")
.method(Method.GET)
.send();
let text = String.UTF8.decode(resp.bodyReadAll().buffer);
Console.log(text); |
<-- |
Readme from dev-wasm-ts |
Possible with Dev Container created by brendandburns |
Wasmtime with integrated |
Using client lib which calls imported host function implemented in wasi-experimental-http-wasmtime Wasmtime's WASI module. |
|
implementations: |
import { Console } from "as-wasi/assembly";
import { request } from "./request";
export function cabi_realloc(a: usize, b: usize,
c: usize, len: usize): usize {
return heap.alloc(len);
}
let response = request("GET", "https://httpbin.org/anything", null,
[{ name: "User-Agent", value: "wasi-http" }]);
Console.log(response.Body); |
Dev Container by brendandburns |
|
|
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
using Extism;
var req = new HttpRequest(
"https://httpbin.org/anything")
{
Method = HttpMethod.GET
};
var res = Pdk.SendRequest(req);
Pdk.SetOutput(res.Body); |
Calling
C-level-imported
runtime's host function
exported for plugins,
which makes actual request using |
|||||
using Fermyon.Spin.Sdk;
using System.Net;
var req = new HttpRequest { Url = "https://httpbin.org/anything" };
var resp = HttpOutbound.Send(req); |
C level
binding to |
|||||
using Wasi.Http;
var client = new HttpClient(new WasiHttpHandler());
var result = await client.GetAsync("https://httpbin.org/anything",
System.Threading.CancellationToken.None);
var content = await result.Content.ReadAsStringAsync();
Console.WriteLine(content); |
Dev Container created by brendandburns |
Wasmtime with integrated |
Calling imported via C level bindings the host function implemented in wasi-experimental-http-wasmtime Wasmtime's WASI module. |
|||
implementations: |
// *Still* identical to wasi-experimental-http's code.
using Wasi.Http;
var client = new HttpClient(new WasiHttpHandler());
var result = await client.GetAsync("https://httpbin.org/anything",
System.Threading.CancellationToken.None);
var content = await result.Content.ReadAsStringAsync();
Console.WriteLine(content); |
Dev Container by brendandburns |
|
Sequence: .Net -> C -> WASI Calling
imported
C-level
Mono binding
which calls
generated
(by
|
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
#define EXTISM_IMPLEMENTATION
#include "extism-pdk.h"
#include <stdint.h>
#include <string.h>
int32_t EXTISM_EXPORTED_FUNCTION(httpget) {
const char *r = "{\"url\": \"https://httpbin.org/anything\"}";
ExtismHandle req = extism_alloc_buf_from_sz(r);
ExtismHandle res = extism_http_request(req, 0);
extism_output_set_from_handle(res, 0, extism_length(res));
return 0;
} |
Calling
C-level-imported
runtime's host function
exported for plugins,
which makes actual request using |
|||||
// no SSL support yet
std::array<char, 4096> buf{};
fetchIO *io = fetchGetURL("http://httpbin.org/anything", "4");
int nbytes = fetchIO_read(io, buf.data(), buf.size());
fetchIO_close(io);
std::cout << buf.data() << std::endl; |
Raw socket write using WasmEdge Socket SDK for C/C++, which imports Wasmedge's implementation of WASI Socket |
|||||
#include "req.h"
#include <string.h>
#include <stdio.h>
const char* url = "https://httpbin.org/anything";
const char* headers = "User-agent: wasm32-wasi-http";
size_t length = 1024 * 1024;
char* buffer = (char*) malloc(length);
uint16_t code;
ResponseHandle handle;
HttpError err = req(url, strlen(url), "GET", 3, headers,
strlen(headers), "", 0, &code, &handle);
size_t written;
err = bodyRead(handle, buffer, length, &written);
close(handle);
printf("%s\n", buffer);
free(buffer); |
Dev Container created by brendandburns |
Wasmtime with integrated |
Calling imported host function implemented in wasi-experimental-http-wasmtime Wasmtime's WASI module. |
|||
implementations: |
// snippet, expand it for full code
types_outgoing_request_t request = types_new_outgoing_request(
&method, &path, &query, &scheme, &domain, headers);
response = default_outgoing_http_handle(request, NULL);
types_future_incoming_response_get(response, &result);
types_incoming_response_consume(result.val.ok, &stream);
streams_read(stream, len, &body_res, &err); #include "proxy.h" // Generated by wit-bindgen
// from https://github.com/WebAssembly/wasi-http/tree/main/wit
#include <stdio.h>
void http_handle(uint32_t arg, uint32_t arg0) {}
int main() {
types_headers_t headers = types_new_fields(NULL);
types_method_t method = {.tag = TYPES_METHOD_GET};
types_scheme_t scheme = {.tag = TYPES_SCHEME_HTTPS};
proxy_string_t path, domain, query;
proxy_string_set(&domain, "httpbin.org");
proxy_string_set(&path, "/anything");
proxy_string_set(&query, "");
types_outgoing_request_t request = types_new_outgoing_request(
&method, &path, &query, &scheme, &domain, headers);
types_future_incoming_response_t response;
response = default_outgoing_http_handle(request, NULL);
proxy_result_incoming_response_error_t result;
types_future_incoming_response_get(response, &result);
types_incoming_stream_t stream;
types_incoming_response_consume(result.val.ok, &stream);
int32_t len = 16 * 1024;
proxy_tuple2_list_u8_bool_t body_res;
streams_stream_error_t err;
streams_read(stream, len, &body_res, &err);
printf("Response body: %s\n", body_res.f0.ptr);
proxy_tuple2_list_u8_bool_free(&body_res);
types_drop_outgoing_request(request);
streams_drop_input_stream(stream);
types_drop_incoming_response(result.val.ok);
return 0;
} |
Dev Container by brendandburns |
|
Calling
a function generated
by
|
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import (
hf "github.com/bots-garden/capsule/capsulemodule/hostfunctions"
)
res, err := hf.Http("https://httpbin.org/anything", "GET", nil, "") |
||||||
import "github.com/extism/go-pdk"
req := pdk.NewHTTPRequest("GET", "https://httpbin.org/anything")
resp := req.Send()
pdk.OutputMemory(resp.Memory()) |
Extism uses Wasmtime |
Calling
C-level-imported
runtime's host function
exported for plugins,
which makes actual request using |
||||
hostFunctions := protobufs.NewHostFunctions()
resp, err := hostFunctions.HttpGet(ctx,
&protobufs.HttpGetRequest{Url: "https://httpbin.org/anything"}) |
go-plugin uses wazero |
Invoking the |
||||
import (
spinhttp "github.com/fermyon/spin/sdk/go/http"
)
resp, err := spinhttp.Get("https://httpbin.org/anything") |
C level
binding to |
|||||
response, err := Request(
"https://httpbin.org/anything", "GET",
"User-agent: wasm32-wasi-http", "")
defer response.Close()
body, err := response.Body()
if err == nil {
println(string(body))
} |
Dev Container created by brendandburns |
Wasmtime with integrated |
Calling imported host function implemented in wasi-experimental-http-wasmtime Wasmtime's WASI module. |
|||
implementations: |
import (
"io/ioutil"
"net/http"
wasiclient "github.com/dev-wasm/dev-wasm-go/client"
)
client := http.Client{
Transport: wasiclient.WasiRoundTripper{},
}
response, err := client.Get("https://httpbin.org/anything")
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err == nil {
println(string(body))
} |
Dev Container by brendandburns needs plenty of RAM to compile (~4G), so may cause OOM on 2-core instance |
|
Sequence: Go -> C -> WASI Calling
a method
generated
by
|
||
Use |
import ( "fmt" ; "io" ; "net/http"
_ "github.com/stealthrocket/net/http"
)
response, err := http.Get("http://httpbin.org/anything")
if err != nil {
fmt.Println(err)
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err == nil {
fmt.Println(string(body))
} |
Hotpatching on module import |
||||
import (
"log"; "net/http"
"github.com/vmware-labs/wasm-workers-server/kits/go/worker"
)
req, _ := http.NewRequest(http.MethodGet,
"https://httpbin.org/anything", nil)
res, _ := worker.SendHttpRequest(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
log.Println(string(body)) |
Calling to Go-wrapped, to C-wrapped, to C-level imported host function which makes request using reqwest. |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
module Main where
import Extism.PDK
import Extism.PDK.HTTP
https_get = do
let url = "https://httpbin.org/anything"
let req = newRequest url
resp <- sendRequest req Nothing
outputMemory (memory resp)
foreign export ccall "https_get" https_get :: IO ()
main = https_get |
Extism uses Wasmtime |
Calling
imported
runtime's host function
exported for plugins,
which makes actual request using |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
Uses forked TeaVM as compiler. |
import wit_wasi_outbound_http.WasiOutboundHttp.*;
Result<Response, HttpError> result =
WasiOutboundHttp.request(
new Request(Method.GET, "https://httpbin.org/anything",
new ArrayList<>(), new ArrayList<>(), null));
Response resp = result.getOk();
String body = new String(resp.body, UTF_8); |
Direct invocation of imported Spin's host function. |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import { fetch } from 'http'
const res = await fetch('https://httpbin.org/anything')
print(await res.text()) |
Distinguished by URL scheme
raw socket write
to
(1) |
|||||
function https_get() {
let resp = Http.request(
{
url: 'https://httpbin.org/anything',
method: 'GET',
headers: { 'User-Agent': 'extism_pdk' }
},
null
);
Host.outputString(resp.body);
}
module.exports = { https_get } |
Extism uses Wasmtime |
|
||||
const resp = await fetch('https://httpbin.org/anything');
const decoder = new TextDecoder('utf-8');
const body = decoder.decode(await resp.arrayBuffer()); |
Invocation of bound JS SDK function, which calls via Rust Spin SDK Spin's host function. |
|||||
const resp = await fetch('https://httpbin.org/anything');
const body = await resp.text(); |
Invocation of bound JS SDK function, which calls via Rust Spin SDK Spin's host function. |
|||||
const resp = await fetch('https://httpbin.org/anything');
const txt = await resp.text();
console.log(txt); |
Calling
bound to JS
|
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
Extism Plug-in Development Kit (PDK) for MoonBit Experimental |
pub fn https_get() -> Int {
let req : Unit = @http.new_request(
@http.Method::GET,
"https://httpbin.org/anything",
)
let resp : Unit = req.send()
resp.output()
return 0
} |
Calling
imported
runtime's host function
exported for plugins,
which makes actual request using |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
import poll_loop
from proxy.imports.types import (
SchemeHttps, OutgoingRequest )
req = OutgoingRequest(Fields.from_list([]))
req.set_scheme(SchemeHttps())
req.set_authority('httpbin.org')
req.set_path_with_query('/anything')
resp = await poll_loop.send(req)
stream = poll_loop.Stream(resp.consume())
buf = b''
while True:
chunk = await stream.next()
if chunk is None:
break
else:
buf += chunk
print(buf.decode('utf-8')) |
Wasmtime version 15.0, maybe incl. Spin. |
Genetaring Python bindings to wasi-http based on wit files under the scenes during |
||||
import extism
@extism.plugin_fn
def httpget():
res = extism.Http.request(
'https://httpbin.org/anything')
extism.output_str(res.data_str()) |
|
|||||
from spin_http import Request, http_send
response = http_send(
Request('GET',
'https://httpbin.org/anything',
{}, None))
print(str(response.body, 'utf-8')) |
A Python |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
use extism_pdk::*;
#[plugin_fn]
pub fn https_get(_: ()) -> FnResult<Memory> {
let req = HttpRequest::new("https://httpbin.org/anything");
let resp = http::request::<()>(&req, None)?;
Ok(resp.into_memory())
} |
Possible with Dev Container by brendandburns |
Calling
C-level-imported
runtime's host function
exported for plugins,
which makes actual request using |
||||
use http_req::request;
let mut writer = Vec::new();
let res = request::get("https://httpbin.org/anything",
&mut writer).unwrap();
println!("body: {}", String::from_utf8_lossy(&writer)); |
Writes to
|
|||||
let mut res = spin_sdk::http::send(
http::Request::builder()
.method("GET")
.uri("https://httpbin.org/anything")
.body(None)?,
)?; |
Calling imported Spin's host function. |
|||||
as part of Any code based on WasmEdge's forks of tokio-rs or mio is expected to work in Wasmedge runtime |
let res = reqwest::get("https://httpbin.org/anything").await?;
let body = res.text().await?;
println!("text: {}", body); |
Wrapping internal stream with WasmEdgeTls, which is built on top of WasmEdge's implementation of WASI Socket. |
||||
use http;
use wasi_experimental_http;
let req = http::request::Builder::new()
.uri("https://httpbin.org/anything").body(None).unwrap();
let resp = wasi_experimental_http::request(req);
let data = std::str::from_utf8(&resp.body_read_all().unwrap())
.unwrap().to_string();
println!("{}", data); |
Wasmtime with integrated |
Calling imported Wasmtime's host function. The actual request is here. |
||||
implementations: |
let headers = types::new_fields(&[("User-agent", "WASI-HTTP")]);
let request = types::new_outgoing_request(
types::MethodParam::Get, "/anything", "",
Some(types::SchemeParam::Https), "httpbin.org", headers,
);
let future_response = default_outgoing_http::handle(request, None);
types::drop_outgoing_request(request);
let response = types::future_incoming_response_get(future_response)
.ok_or_else(|| anyhow!("response is available immediately"))?
.map_err(|err| anyhow!("response error: {err:?}"))?;
types::drop_future_incoming_response(future_response);
let stream = types::incoming_response_consume(response)
.map_err(|()| anyhow!("response has no body stream"))?;
let mut body = Vec::new();
let mut is_eof = false;
while !is_eof {
let (mut chunk, stream_at_end) = streams::read(stream, u64::MAX)?;
is_eof = stream_at_end;
body.append(&mut chunk);
}
streams::drop_input_stream(stream);
types::drop_incoming_response(response);
println!("body: {}", str::from_utf8(&body).unwrap()); |
Possible with Dev Container by brendandburns |
|
Rust code
generated
(by
|
||
let req = Request::builder()
.uri("https://httpbin.org/anything")
.body(String::new()).unwrap();
let res = bindings::send_http_request(req).unwrap();
let data = res.body();
let txt = String::from_utf8_lossy(&data);
println!("text: {txt}"); |
Calling imported host function which makes request using reqwest. |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
var req = Http.newRequest(Method.GET,
"https://httpbin.org/anything");
def res = req.send(null);
res.output(); |
Calling
C-level-imported
runtime's host function
exported for plugins,
which makes actual request using |
Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request |
---|---|---|---|---|---|---|
const std = @import("std");
const extism_pdk = @import("extism-pdk");
const allocator = std.heap.wasm_allocator;
export fn https_get() i32 {
const plugin = extism_pdk.Plugin.init(allocator);
var req = extism_pdk.http.HttpRequest.init(allocator, "GET",
"https://httpbin.org/anything");
defer req.deinit();
req.setHeader("User-Agent", "extism_pdk") catch unreachable;
const resp = plugin.request(req, null) catch unreachable;
defer resp.deinit();
plugin.outputMemory(resp.memory);
return 0;
} |
Extism uses Wasmtime |
Calling
imported
runtime's host function
exported for plugins,
which makes actual request using |
||||
Unofficial |
const spin = @import("spin");
const req = spin.http.Request{ .method = .GET,
.url = "https://httpbin.org/anything" };
const res = spin.http.send(req) catch unreachable; |
Calling to C-level import of Spin's host function. |
||||
var gp_all = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gp_all.allocator();
var status: u16 = 0;
var handle: u32 = 0;
_ = request("https://httpbin.org/anything", "GET", "", "", &status, &handle);
defer _ = close(@bitCast(i32, handle));
var headers_buffer = try allocator.alloc(u8, 1024);
var header_len: u32 = 0;
_ = header(handle, "content-length", headers_buffer, &header_len);
const length = try std.fmt.parseInt(u32, headers_buffer[0..header_len], 10);
var buffer = try allocator.alloc(u8, length + 1);
defer allocator.free(buffer);
var written: u32 = 0;
_ = body_read(handle, &buffer[0], @bitCast(i32, buffer.len), &written);
try std.io.getStdOut().writer().print("{s}\n", .{buffer[0..written]}); |
Dev Container by brendandburns |
Wasmtime with integrated |
Calling imported Wasmtime's host function. The actual request is here. |