-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
github-actions[bot] edited this page Sep 13, 2026
·
7 revisions
This page gets a client and a server talking over loopback in five minutes.
[dependencies]
courierust = "1.0.6"The default std feature pulls in the client, server, pool, and gRPC layers (the WebSocket engine is in the protocol core, so courierust_ws is available either way; WebSockets shows the server hook and the client). If you only want the no_std protocol core, see no_std.
Save this as examples/hello.rs:
use courierust::courierust_body::Body;
use courierust::courierust_client::{Client, ClientConfig};
use courierust::courierust_http::request::Request;
use courierust::courierust_http::response::Response;
use courierust::courierust_server::{Server, ServerConfig};
fn main() -> courierust::Result<()> {
// --- server ---
// http2 = true means the same port serves both h2c and HTTP/1.1.
let server_cfg = ServerConfig {
http2: true,
..Default::default()
};
let server = Server::bind_with_config("127.0.0.1:0", server_cfg)?;
let addr = server.local_addr()?;
// serve_background returns a handle; the server keeps running while
// the client below talks to it.
let _handle = server.serve_background(|req: Request<Body>| -> Response<Body> {
let mut resp = Response::with_status(200.into());
resp.headers.insert(
courierust::courierust_http::header::HeaderName::from_lowercase("content-type"),
courierust::courierust_http::header::HeaderValue::from_static("text/plain"),
);
let body = req.body.collect().unwrap_or_default();
resp.body = Body::Bytes(body);
resp
})?;
// --- client ---
let client_cfg = ClientConfig {
http2: true,
..Default::default()
};
let client = Client::with_config(client_cfg);
let resp = client.get(&format!("http://{addr}/hello"))?;
println!("GET -> {} {}", resp.status.as_u16(), resp.body.collect()?.to_str()?);
let resp = client.post(&format!("http://{addr}/echo"), "hello from client")?;
println!("POST -> {} {}", resp.status.as_u16(), resp.body.collect()?.to_str()?);
Ok(())
}Run it:
cargo run --example helloExpected output (address varies):
GET -> 200 hello
POST -> 200 hello from client
-
Server::bind_with_config("127.0.0.1:0", ...)binds an ephemeral port;local_addr()tells you which one. - The handler is a plain
Fn(Request<Body>) -> Response<Body>. It echoes whatever body it received. -
Client::with_configwithhttp2: trueuses cleartext HTTP/2 prior knowledge (h2c), so this example has no TLS by design. HTTPS uses the built-in TLS 1.2 + 1.3 path whenClientConfig::tlsis configured; HTTP/3 uses that TLS path with ALPNh3andClientConfig::http3: true. -
Response::with_status(200.into())builds an empty 200; fill.headersand.bodyas needed.
- HTTP client — timeouts, redirects, priorities, streaming response bodies
- HTTP server — streaming responses, thread count, background serving
-
WebSockets — in-place upgrade,
WsService, client, proxy deployment - gRPC — unary and streaming RPCs over the same stack
- Fingerprints — make the client look like Chrome