{"id":21659637,"url":"https://github.com/deislabs/wasi-experimental-http","last_synced_at":"2025-07-17T22:32:37.128Z","repository":{"id":37856450,"uuid":"338916090","full_name":"deislabs/wasi-experimental-http","owner":"deislabs","description":"Experimental outbound HTTP support for WebAssembly and WASI","archived":true,"fork":false,"pushed_at":"2023-03-14T17:13:55.000Z","size":239,"stargazers_count":136,"open_issues_count":20,"forks_count":35,"subscribers_count":16,"default_branch":"main","last_synced_at":"2024-11-17T23:04:23.684Z","etag":null,"topics":["wasi","wasmtime","webassembly"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deislabs.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-14T22:33:24.000Z","updated_at":"2024-11-14T03:50:31.000Z","dependencies_parsed_at":"2023-01-20T20:02:48.656Z","dependency_job_id":null,"html_url":"https://github.com/deislabs/wasi-experimental-http","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deislabs%2Fwasi-experimental-http","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deislabs%2Fwasi-experimental-http/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deislabs%2Fwasi-experimental-http/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deislabs%2Fwasi-experimental-http/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deislabs","download_url":"https://codeload.github.com/deislabs/wasi-experimental-http/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226243857,"owners_count":17594456,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["wasi","wasmtime","webassembly"],"created_at":"2024-11-25T09:31:20.050Z","updated_at":"2024-11-25T09:33:06.049Z","avatar_url":"https://github.com/deislabs.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# `wasi-experimental-http`\n\nThis is an experiment intended to provide a _temporary_ workaround until the\nWASI networking API is stable, and is compatible with [Wasmtime v0.26][24] by\nusing the `wasi_experiemental_http_wasmtime` crate. We expect that once [the\nWASI sockets proposal][sockets-wip] gets adopted and implemented in language\ntoolchains, the need for this library will vanish.\n\n### Writing a module that makes an HTTP request\n\nWe use the `wasi-experimental-http` crate (from this repository) and the `http`\ncrate to create an HTTP request from a WebAssembly module, make a host call to\nthe runtime using the request, then get a response back:\n\n```rust\nuse bytes::Bytes;\nuse http;\nuse wasi_experimental_http;\n\n#[no_mangle]\npub extern \"C\" fn _start() {\n    let url = \"https://postman-echo.com/post\".to_string();\n    let req = http::request::Builder::new()\n        .method(http::Method::POST)\n        .uri(\u0026url)\n        .header(\"Content-Type\", \"text/plain\")\n        .header(\"abc\", \"def\");\n    let b = Bytes::from(\"Testing with a request body. Does this actually work?\");\n    let req = req.body(Some(b)).unwrap();\n\n    let res = wasi_experimental_http::request(req).expect(\"cannot make request\");\n    let str = std::str::from_utf8(\u0026res.body_read_all()).unwrap().to_string();\n    println!(\"{:#?}\", res.header_get(\"Content-Type\"));\n    println!(\"{}\", str);\n    println!(\"{:#?}\", res.status_code);\n}\n```\n\nBuild the module using the `wasm32-wasi` target, then follow the next section to\nupdate a Wasmtime runtime with the experimental HTTP support.\n\n### Adding support to a Wasmtime runtime\n\nThe easiest way to add support is by using the\n[Wasmtime linker](https://docs.rs/wasmtime/0.26.0/wasmtime/struct.Linker.html):\n\n```rust\nlet store = Store::default();\nlet mut linker = Linker::new(\u0026store);\nlet wasi = Wasi::new(\u0026store, ctx);\n\n// link the WASI core functions\nwasi.add_to_linker(\u0026mut linker)?;\n\n// link the experimental HTTP support\nlet allowed_hosts = Some(vec![\"https://postman-echo.com\".to_string()]);\nlet max_concurrent_requests = Some(42);\n\nlet http = HttpCtx::new(allowed_domains, max_concurrent_requests)?;\nhttp.add_to_linker(\u0026mut linker)?;\n```\n\nThen, executing the module above will send the HTTP request and write the\nresponse:\n\n```\n{\n    \"content-length\": \"374\",\n    \"connection\": \"keep-alive\",\n    \"set-cookie\": \"sails.Path=/; HttpOnly\",\n    \"vary\": \"Accept-Encoding\",\n    \"content-type\": \"application/json; charset=utf-8\",\n    \"date\": \"Fri, 26 Feb 2021 18:31:03 GMT\",\n    \"etag\": \"W/\\\"176-Ky4OTmr3Xbcl3yNah8w2XIQapGU\\\"\",\n}\n{\"args\":{},\"data\":\"Testing with a request body. Does this actually work?\",\"files\":{},\"form\":{},\"headers\":{\"x-forwarded-proto\":\"https\",\"x-forwarded-port\":\"443\",\"host\":\"postman-echo.com\",\"x-amzn-trace-id\":\"Root=1-60393e67-02d1c8033bcf4f1e74a4523e\",\"content-length\":\"53\",\"content-type\":\"text/plain\",\"abc\":\"def\",\"accept\":\"*/*\"},\"json\":null,\"url\":\"https://postman-echo.com/post\"}\n\"200 OK\"\n```\n\nThe Wasmtime implementation also enables allowed hosts - an optional and\nconfigurable list of domains or hosts that guest modules are allowed to send\nrequests to. If `None` or an empty vector is passed, guest modules are **NOT**\nallowed to make HTTP requests to any server. (Note that the hosts passed MUST\nhave the protocol also specified - i.e. `https://my-domain.com`, or\n`http://192.168.0.1`, and if making requests to a subdomain, the subdomain MUST\nbe in the allowed list. See the the library tests for more examples).\n\nNote that the Wasmtime version currently supported is\n[0.26](https://docs.rs/wasmtime/0.26.0/wasmtime/).\n\n### Sending HTTP requests from AssemblyScript\n\nThis repository also contains an AssemblyScript implementation for sending HTTP\nrequests:\n\n```typescript\n// @ts-ignore\nimport * as wasi from \"as-wasi\";\nimport {\n  Method,\n  RequestBuilder,\n  Response,\n} from \"@deislabs/wasi-experimental-http\";\n\nexport function _start_(): void {\n  let body = String.UTF8.encode(\"testing the body\");\n  let res = new RequestBuilder(\"https://postman-echo.com/post\")\n    .header(\"Content-Type\", \"text/plain\")\n    .method(Method.POST)\n    .body(body)\n    .send();\n  wasi.Console.log(res.status.toString());\n  wasi.Console.log(res.headersGetAll.toString());\n  wasi.Console.log(String.UTF8.decode(res.bodyReadAll().buffer));\n}\n```\n\n### Testing using the `wasmtime-http` binary\n\nThis project also adds a convenience binary for testing modules with HTTP\nsupport, `wasmtime-http` - a simple program that mimics the `wasmtime run`\ncommand, but also adds support for sending HTTP requests.\n\n````\n➜ cargo run --bin wasmtime-http -- --help\nwasmtime-http 0.1.0\n\nUSAGE:\n    wasmtime-http [OPTIONS] \u003cmodule\u003e [--] [ARGS]...\n\nFLAGS:\n    -h, --help       Prints help information\n    -V, --version    Prints version information\n\nOPTIONS:\n    -a, --allowed-host \u003callowed-hosts\u003e...    Host the guest module is allowed to make outbound HTTP requests to\n    -i, --invoke \u003cinvoke\u003e                    The name of the function to run [default: _start]\n    -c, --concurrency \u003cmax-concurrency\u003e      The maximum number of concurrent requests a module can make to allowed\n                                             hosts\n    -e, --env \u003cNAME=VAL\u003e...                  Pass an environment variable to the program\n\nARGS:\n    \u003cmodule\u003e     The path of the WebAssembly module to run\n    \u003cARGS\u003e...    The arguments to pass to the module```\n````\n\n### Known limitations\n\n- there is no support for streaming HTTP responses, which this means guest\n  modules have to wait until the entire body has been written by the runtime\n  before reading it.\n- request and response bodies are [`Bytes`](https://docs.rs/bytes/1.0.1/bytes/).\n- the current WITX definitions are experimental, and currently only used to\n  generate guest bindings.\n- this library does not aim to add support for running HTTP servers in\n  WebAssembly.\n\n### Code of Conduct\n\nThis project has adopted the\n[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).\n\nFor more information see the\n[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or\ncontact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any\nadditional questions or comments.\n\n[24]: https://github.com/bytecodealliance/wasmtime/releases/tag/v0.26.0\n[sockets-wip]: https://github.com/WebAssembly/WASI/pull/312\n\n```\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeislabs%2Fwasi-experimental-http","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeislabs%2Fwasi-experimental-http","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeislabs%2Fwasi-experimental-http/lists"}