Skip to content

Commit 2e49a9a

Browse files
authored
Merge pull request #2 from wacker-dev/client
Merge wasi-http-client into waki
2 parents 74d854f + 06de28d commit 2e49a9a

File tree

22 files changed

+902
-141
lines changed

22 files changed

+902
-141
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@ jobs:
1515
- name: Install Rust
1616
uses: dtolnay/rust-toolchain@1.78.0
1717
with:
18+
targets: wasm32-wasi
1819
components: clippy, rustfmt
1920
- name: cargo fmt
2021
run: cargo fmt --all -- --check
2122
- name: cargo clippy
2223
run: cargo clippy --all-targets --all-features -- -D warnings
24+
- name: Install wasmtime
25+
uses: bytecodealliance/actions/wasmtime/setup@v1
26+
with:
27+
github_token: ${{ secrets.GITHUB_TOKEN }}
28+
version: "v21.0.1"
29+
- name: cargo test
30+
run: cargo test

Cargo.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@ resolver = "2"
33
members = [
44
"waki",
55
"waki-macros",
6+
"test-programs",
67
]
78

89
[workspace.package]
9-
version = "0.1.0"
10+
version = "0.2.0"
1011
authors = ["Xinzhao Xu"]
1112
edition = "2021"
1213
categories = ["wasm"]
1314
keywords = ["webassembly", "wasm", "wasi"]
1415
repository = "https://github.com/wacker-dev/waki"
1516
license = "Apache-2.0"
16-
description = "An HTTP library for building Web apps with WASI API"
17+
description = "HTTP client and server library for WASI"
1718
readme = "README.md"
1819

1920
[workspace.dependencies]
20-
waki-macros = { path = "waki-macros", version = "0.1.0" }
21+
waki-macros = { path = "waki-macros", version = "0.2.0" }
22+
23+
anyhow = "1.0.86"
24+
serde = "1.0.201"

README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
# waki
22

3-
An HTTP library for building Web apps with WASI API.
3+
HTTP client and server library for WASI.
4+
5+
Send a request:
6+
7+
```rust
8+
let resp = Client::new()
9+
.post("https://httpbin.org/post")
10+
.connect_timeout(Duration::from_secs(5))
11+
.send()?;
12+
13+
println!("status code: {}", resp.status_code());
14+
```
15+
16+
Writing an HTTP component:
417

518
```rust
6-
use waki::{handler, Request, Response};
19+
use waki::{handler, ErrorCode, Request, Response};
720

821
#[handler]
9-
fn hello(req: Request) -> Response {
10-
Response::new().body(b"Hello, WASI!")
22+
fn hello(req: Request) -> Result<Response, ErrorCode> {
23+
Response::builder().body(b"Hello, WASI!").build()
1124
}
1225
```

test-programs/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "test-programs"
3+
version = "0.0.0"
4+
edition = "2021"
5+
publish = false
6+
7+
[dependencies]
8+
waki = { path = "../waki", features = ["json"] }
9+
serde = { workspace = true, features = ["derive"] }

test-programs/artifacts/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "test-programs-artifacts"
3+
version = "0.0.0"
4+
edition = "2021"
5+
publish = false
6+
7+
[build-dependencies]
8+
anyhow.workspace = true
9+
cargo_metadata = "0.18.1"
10+
wit-component = "0.208.1"
11+
heck = "0.5.0"

test-programs/artifacts/build.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use anyhow::Result;
2+
use cargo_metadata::MetadataCommand;
3+
use heck::*;
4+
use std::path::{Path, PathBuf};
5+
use std::process::Command;
6+
use std::{env, fs};
7+
use wit_component::ComponentEncoder;
8+
9+
fn main() -> Result<()> {
10+
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
11+
12+
println!("cargo::rerun-if-changed=../src");
13+
14+
let status = Command::new("cargo")
15+
.arg("build")
16+
.arg("--package=test-programs")
17+
.arg("--target=wasm32-wasi")
18+
.env("CARGO_TARGET_DIR", &out_dir)
19+
.env("CARGO_PROFILE_DEV_DEBUG", "1")
20+
.status()?;
21+
assert!(status.success());
22+
23+
let meta = MetadataCommand::new().exec()?;
24+
let targets = meta
25+
.packages
26+
.iter()
27+
.find(|p| p.name == "test-programs")
28+
.unwrap()
29+
.targets
30+
.iter()
31+
.filter(|t| t.kind == ["bin"])
32+
.map(|t| &t.name)
33+
.collect::<Vec<_>>();
34+
35+
let mut generated_code = String::new();
36+
37+
for target in targets {
38+
let camel = target.to_shouty_snake_case();
39+
let wasm = out_dir
40+
.join("wasm32-wasi")
41+
.join("debug")
42+
.join(format!("{target}.wasm"));
43+
44+
let path = compile_component(&wasm)?;
45+
generated_code += &format!("pub const {camel}_COMPONENT: &str = {path:?};\n");
46+
}
47+
48+
fs::write(out_dir.join("gen.rs"), generated_code)?;
49+
50+
Ok(())
51+
}
52+
53+
// Compile a component, return the path of the binary
54+
fn compile_component(wasm: &Path) -> Result<PathBuf> {
55+
let module = fs::read(wasm)?;
56+
let component = ComponentEncoder::default()
57+
.module(module.as_slice())?
58+
.validate(true)
59+
.adapter(
60+
"wasi_snapshot_preview1",
61+
include_bytes!("wasi_snapshot_preview1.command.wasm"),
62+
)?
63+
.encode()?;
64+
let out_dir = wasm.parent().unwrap();
65+
let stem = wasm.file_stem().unwrap().to_str().unwrap();
66+
let component_path = out_dir.join(format!("{stem}.component.wasm"));
67+
fs::write(&component_path, component)?;
68+
Ok(component_path)
69+
}

test-programs/artifacts/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include!(concat!(env!("OUT_DIR"), "/gen.rs"));
79.4 KB
Binary file not shown.

test-programs/src/bin/get_chunk.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use waki::Client;
2+
3+
fn main() {
4+
let resp = Client::new()
5+
.get("https://httpbin.org/range/20")
6+
.query(&[("duration", "5"), ("chunk_size", "10")])
7+
.send()
8+
.unwrap();
9+
assert_eq!(resp.status_code(), 200);
10+
11+
while let Some(chunk) = resp.chunk(1024).unwrap() {
12+
assert_eq!(String::from_utf8(chunk).unwrap().len(), 10);
13+
}
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use serde::Deserialize;
2+
use std::collections::HashMap;
3+
use waki::Client;
4+
5+
#[derive(Deserialize)]
6+
struct Data {
7+
args: HashMap<String, String>,
8+
}
9+
10+
fn main() {
11+
let resp = Client::new()
12+
.get("https://httpbin.org/get?a=b")
13+
.headers([("Content-Type", "application/json"), ("Accept", "*/*")])
14+
.send()
15+
.unwrap();
16+
assert_eq!(resp.status_code(), 200);
17+
18+
let data = resp.json::<Data>().unwrap();
19+
assert_eq!(data.args.get("a").unwrap(), "b");
20+
}

0 commit comments

Comments
 (0)