(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   | 
|||
| 
 Silverlight / WPF revived in WASM form  | 
using System;
using System.Net.Http;
HttpClient client = new HttpClient();
string uri = "https://httpbin.org/anything";
string responseText = await client.GetStringAsync(uri);
Console.WriteLine("text: " + responseText); | 
 Browser  | 
  | 
|||
using System;
using RestSharp;
var client = new RestClient();
var req = new RestRequest("http://httpbin.org/anything");
var res = await client.ExecuteGetAsync(req);
Console.WriteLine("text: " + res.Content); | 
 wrapper around
.NET's   | 
|||||
| 
 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   | 
||||
using System;
using System.Net.Http;
HttpClient client = new HttpClient();
string uri = "https://httpbin.org/anything";
string txt = await client.GetStringAsync(uri);
Console.WriteLine("text: " + txt); | 
Browser | 
 Using
.NET's   | 
| 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:requests/requests.dart';
final resp = await Requests.get(
  'https://httpbin.org/anything');
print('body: ${resp.content()}'); | 
 Browser with Wasm-GC support enabled1  | 
 Wrapper over package:http.  | 
||||
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   | 
||||
import 'dart:js_interop';
@JS()
external JSPromise<Response> fetch(JSString _);
extension type Response(JSObject _)
 implements JSObject {
  @JS()
  external JSPromise<JSString> text();
}
final Response resp = await fetch(
  'https://httpbin.org/anything'.toJS).toDart;
final txt = await resp.text().toDart;
print('body: ${txt}'); | 
 Browser with Wasm-GC support enabled1, Node.js, Bun, and Deno.  | 
 Direct JS   | 
||||
| 
 SDK for writing Cloudflare Workers in Dart aka cf_workers.dart  | 
import 'package:http/http.dart';
import 'package:cf_workers/cf_workers.dart';
import 'package:cf_workers/http.dart';
Future<void> main() {
  return Workers((JSRequest req) async {
    return fetch(Request('GET', Uri.parse(
      'https://httpbin.org/anything')).toJS);
  }).serve();
} | 
 JS   | 
| Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request | 
|---|---|---|---|---|---|---|
| 
 Common Expression Language  | 
// two custom functions
println(httpget('https://httpbin.org/anything')) | 
 Using
Golang's   | 
||||
// two custom functions
println(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 | 
|---|---|---|---|---|---|---|
: 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 | 
|---|---|---|---|---|---|---|
:- use_module(library(wasm)).?- js_eval("const xhr=new XMLHttpRequest(); xhr.open('GET','https://httpbin.org/anything',false); xhr.send(); xhr.responseText;", Txt), format("~s", [Txt]). | 
 <--  | 
  | 
 Browser  | 
 Manual JS   | 
||
fetch('https://httpbin.org/anything', text, Out). | 
 <--  | 
  | 
 Browser and Node  | 
|||
js_eval("return fetch('https://httpbin.org/anything').then(r => r.text());", Txt). | 
 Example code works in Playground  | 
 Browser and Node  | 
 Manual invoking of JS   | 
| Product / Implementation | TLDR: Usage | TLDR: Example code | Doc | Online demo | WASM Runtime | Internals: method to do real request | 
|---|---|---|---|---|---|---|
% custom predicate
httpget("https://httpbin.org/anything", RespTxt). | 
 Using
Golang's   | 
| 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   | 
||||
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 | 
|---|---|---|---|---|---|---|
go does { get https://httpbin.org/anything |print } | 
 Browser  | 
 Using
Golang's   | 
| 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.  | 
||||
use quad_net::http_request::RequestBuilder;
let mut request = RequestBuilder::new(
  "https://httpbin.org/anything").send();
loop {
  if let Some(data) = request.try_recv() {
    info!("Done! {}", data.unwrap());
  }
  next_frame().await;
} | 
 Browser  | 
|||||
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 | 
|---|---|---|---|---|---|---|
| 
 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  | 
|||||
| 
 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  | 
|||||
| 
 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  | 
|||||
| 
 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  
  | 
||
import ("io"; "log"; "net/http"
 _ "github.com/ydnar/wasi-http-go/wasihttp"
)
req, _ := http.NewRequest("GET",
  "https://httpbin.org/anything", http.NoBody)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
log.Println(string(body)) | 
 Runtime supporting wasip2-http (only Wasmtime at the moment)  | 
|||||
| 
 f.k.a. stealthrocket/net  | 
import ( 	"fmt" ; "io" ; "net/http"
  _ "github.com/dispatchrun/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 | 
|---|---|---|---|---|---|---|
| 
 Spin SDK for Prolog  | 
:- use_module(library(spin)).
http_fetch("https://httpbin.org/anything", Resp, []),
write(Resp), nl. | 
 Invoking   | 
| 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.  | 
||||
| 
 new gen of wasi-http-client  | 
use waki::Client;
let res = Client::new()
  .get("https://httpbin.org/anything")
  .send().unwrap();
let body = String::from_utf8(
  res.body().unwrap()).unwrap();
println!("body:{}", body); | 
 Wasmtime version 17 and above  | 
||||
| 
 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   | 
||||
  | 
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.  |