Merge pull request #1339 from fibonacci1729/rust-sdk-http-router
feat(sdk): add HTTP router for Rust SDK
This commit is contained in:
commit
8d0b6c7737
|
@ -4248,6 +4248,16 @@ version = "1.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
|
||||
|
||||
[[package]]
|
||||
name = "routefinder"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94f8f99b10dedd317514253dda1fa7c14e344aac96e1f78149a64879ce282aca"
|
||||
dependencies = [
|
||||
"smartcow",
|
||||
"smartstring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rpassword"
|
||||
version = "7.2.0"
|
||||
|
@ -4804,6 +4814,26 @@ version = "1.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "smartcow"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "656fcb1c1fca8c4655372134ce87d8afdf5ec5949ebabe8d314be0141d8b5da2"
|
||||
dependencies = [
|
||||
"smartstring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smartstring"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"static_assertions",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.9"
|
||||
|
@ -5158,6 +5188,7 @@ dependencies = [
|
|||
"bytes",
|
||||
"form_urlencoded",
|
||||
"http",
|
||||
"routefinder",
|
||||
"spin-macro",
|
||||
"thiserror",
|
||||
"wit-bindgen-rust",
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = "wasm32-wasi"
|
|
@ -0,0 +1 @@
|
|||
target/
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "http-rust-router"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = [ "cdylib" ]
|
||||
|
||||
[dependencies]
|
||||
# Useful crate to handle errors.
|
||||
anyhow = "1"
|
||||
# Crate to simplify working with bytes.
|
||||
bytes = "1"
|
||||
# General-purpose crate with common HTTP types.
|
||||
http = "0.2"
|
||||
# The Spin SDK.
|
||||
spin-sdk = { path = "../../sdk/rust" }
|
||||
# Crate that generates Rust Wasm bindings from a WebAssembly interface.
|
||||
wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "cb871cfa1ee460b51eb1d144b175b9aab9c50aba" }
|
||||
|
||||
[workspace]
|
|
@ -0,0 +1,16 @@
|
|||
spin_manifest_version = "1"
|
||||
authors = ["Fermyon Engineering <engineering@fermyon.com>"]
|
||||
description = "An application that demonstrates HTTP routing."
|
||||
name = "spin-rust-router"
|
||||
trigger = { type = "http", base = "/" }
|
||||
version = "1.0.0"
|
||||
|
||||
[[component]]
|
||||
id = "route"
|
||||
source = "target/wasm32-wasi/release/http_rust_router.wasm"
|
||||
description = "A component that internally routes HTTP requests."
|
||||
[component.trigger]
|
||||
route = "/..."
|
||||
[component.build]
|
||||
command = "cargo build --target wasm32-wasi --release"
|
||||
watch = ["src/**/*.rs", "Cargo.toml", "spin.toml"]
|
|
@ -0,0 +1,39 @@
|
|||
use anyhow::Result;
|
||||
use spin_sdk::{
|
||||
http_component,
|
||||
http_router,
|
||||
http::{
|
||||
Request,
|
||||
Response,
|
||||
Params,
|
||||
},
|
||||
};
|
||||
|
||||
#[http_component]
|
||||
fn handle_route(req: Request) -> anyhow::Result<Response> {
|
||||
let router = http_router! {
|
||||
GET "/hello/:planet" => api::hello_planet,
|
||||
_ "/*" => |_req, params| {
|
||||
let capture = params.wildcard().unwrap_or_default();
|
||||
Ok(http::Response::builder()
|
||||
.status(http::StatusCode::OK)
|
||||
.body(Some(format!("{capture}").into()))
|
||||
.unwrap())
|
||||
}
|
||||
};
|
||||
router.handle(req)
|
||||
}
|
||||
|
||||
mod api {
|
||||
use super::*;
|
||||
|
||||
// /hello/:planet
|
||||
pub fn hello_planet(_req: Request, params: Params) -> anyhow::Result<Response> {
|
||||
let planet = params.get("planet").expect("PLANET");
|
||||
|
||||
Ok(http::Response::builder()
|
||||
.status(http::StatusCode::OK)
|
||||
.body(Some(format!("{planet}").into()))
|
||||
.unwrap())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = "wasm32-wasi"
|
|
@ -0,0 +1 @@
|
|||
target/
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "http-rust-router"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = [ "cdylib" ]
|
||||
|
||||
[dependencies]
|
||||
# Useful crate to handle errors.
|
||||
anyhow = "1"
|
||||
# Crate to simplify working with bytes.
|
||||
bytes = "1"
|
||||
# General-purpose crate with common HTTP types.
|
||||
http = "0.2"
|
||||
# The Spin SDK.
|
||||
spin-sdk = { path = "../../sdk/rust" }
|
||||
# Crate that generates Rust Wasm bindings from a WebAssembly interface.
|
||||
wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "cb871cfa1ee460b51eb1d144b175b9aab9c50aba" }
|
||||
|
||||
[workspace]
|
|
@ -0,0 +1,16 @@
|
|||
spin_manifest_version = "1"
|
||||
authors = ["Fermyon Engineering <engineering@fermyon.com>"]
|
||||
description = "An application that demonstrates HTTP routing."
|
||||
name = "spin-rust-router"
|
||||
trigger = { type = "http", base = "/" }
|
||||
version = "1.0.0"
|
||||
|
||||
[[component]]
|
||||
id = "route"
|
||||
source = "target/wasm32-wasi/release/http_rust_router.wasm"
|
||||
description = "A component that internally routes HTTP requests."
|
||||
[component.trigger]
|
||||
route = "/..."
|
||||
[component.build]
|
||||
command = "cargo build --target wasm32-wasi --release"
|
||||
watch = ["src/**/*.rs", "Cargo.toml", "spin.toml"]
|
|
@ -0,0 +1,40 @@
|
|||
use anyhow::Result;
|
||||
use spin_sdk::{
|
||||
http_component,
|
||||
http::{
|
||||
Request,
|
||||
Response,
|
||||
Router,
|
||||
Params,
|
||||
},
|
||||
};
|
||||
|
||||
/// A Spin HTTP component that internally routes requests.
|
||||
#[http_component]
|
||||
fn handle_route(req: Request) -> Result<Response> {
|
||||
let mut router = Router::new();
|
||||
router.get("/hello/:planet", api::hello_planet);
|
||||
router.any("/*", api::echo_wildcard);
|
||||
router.handle(req)
|
||||
}
|
||||
|
||||
mod api {
|
||||
use super::*;
|
||||
|
||||
// /hello/:planet
|
||||
pub fn hello_planet(_req: Request, params: Params) -> Result<Response> {
|
||||
let planet = params.get("planet").expect("PLANET");
|
||||
|
||||
Ok(http::Response::builder()
|
||||
.status(http::StatusCode::OK)
|
||||
.body(Some(format!("{planet}").into()))?)
|
||||
}
|
||||
|
||||
// /*
|
||||
pub fn echo_wildcard(_req: Request, params: Params) -> Result<Response> {
|
||||
let capture = params.wildcard().unwrap_or_default();
|
||||
Ok(http::Response::builder()
|
||||
.status(http::StatusCode::OK)
|
||||
.body(Some(format!("{capture}").into()))?)
|
||||
}
|
||||
}
|
|
@ -12,10 +12,11 @@ name = "spin_sdk"
|
|||
anyhow = "1"
|
||||
bytes = "1"
|
||||
form_urlencoded = "1.0"
|
||||
http = "0.2"
|
||||
http_types = { package = "http", version = "0.2" }
|
||||
spin-macro = { path = "macro" }
|
||||
thiserror = "1.0.37"
|
||||
wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "cb871cfa1ee460b51eb1d144b175b9aab9c50aba" }
|
||||
routefinder = "0.5.3"
|
||||
|
||||
[features]
|
||||
default = [ "export-sdk-language" ]
|
||||
|
|
|
@ -0,0 +1,347 @@
|
|||
use super::{Request, Response, Result};
|
||||
use routefinder::{Captures, Router as MethodRouter};
|
||||
use std::collections::HashMap;
|
||||
|
||||
type Handler = dyn Fn(Request, Params) -> Result<Response>;
|
||||
|
||||
/// Route parameters extracted from a URI that match a route pattern.
|
||||
pub type Params = Captures<'static, 'static>;
|
||||
|
||||
/// The Spin SDK HTTP router.
|
||||
pub struct Router {
|
||||
methods_map: HashMap<http_types::Method, MethodRouter<Box<Handler>>>,
|
||||
any_methods: MethodRouter<Box<Handler>>,
|
||||
}
|
||||
|
||||
impl Default for Router {
|
||||
fn default() -> Router {
|
||||
Router::new()
|
||||
}
|
||||
}
|
||||
|
||||
struct RouteMatch<'a> {
|
||||
params: Captures<'static, 'static>,
|
||||
handler: &'a Handler,
|
||||
}
|
||||
|
||||
impl Router {
|
||||
/// Dispatches a request to the appropriate handler along with the URI parameters.
|
||||
pub fn handle(&self, request: Request) -> Result<Response> {
|
||||
let method = request.method().to_owned();
|
||||
let path = request.uri().path().to_owned();
|
||||
let RouteMatch { params, handler } = self.find(&path, method);
|
||||
handler(request, params)
|
||||
}
|
||||
|
||||
fn find(&self, path: &str, method: http_types::Method) -> RouteMatch<'_> {
|
||||
let best_match = self
|
||||
.methods_map
|
||||
.get(&method)
|
||||
.and_then(|r| r.best_match(path));
|
||||
|
||||
if let Some(m) = best_match {
|
||||
let params = m.captures().into_owned();
|
||||
let handler = m.handler();
|
||||
return RouteMatch { handler, params };
|
||||
}
|
||||
|
||||
let best_match = self.any_methods.best_match(path);
|
||||
|
||||
match best_match {
|
||||
Some(m) => {
|
||||
let params = m.captures().into_owned();
|
||||
let handler = m.handler();
|
||||
RouteMatch { handler, params }
|
||||
}
|
||||
None if method == http_types::Method::HEAD => {
|
||||
// If it is a HTTP HEAD request then check if there is a callback in the methods map
|
||||
// if not then fallback to the behavior of HTTP GET else proceed as usual
|
||||
self.find(path, http_types::Method::GET)
|
||||
}
|
||||
None => {
|
||||
// Handle the failure case where no match could be resolved.
|
||||
self.fail(path, method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to handle the case where a best match couldn't be resolved.
|
||||
fn fail(&self, path: &str, method: http_types::Method) -> RouteMatch<'_> {
|
||||
// First, filter all routers to determine if the path can match but the provided method is not allowed.
|
||||
let is_method_not_allowed = self
|
||||
.methods_map
|
||||
.iter()
|
||||
.filter(|(k, _)| **k != method)
|
||||
.any(|(_, r)| r.best_match(path).is_some());
|
||||
|
||||
if is_method_not_allowed {
|
||||
// If this `path` can be handled by a callback registered with a different HTTP method
|
||||
// should return 405 Method Not Allowed
|
||||
RouteMatch {
|
||||
handler: &method_not_allowed,
|
||||
params: Captures::default(),
|
||||
}
|
||||
} else {
|
||||
// ... Otherwise, nothing matched so 404.
|
||||
RouteMatch {
|
||||
handler: ¬_found,
|
||||
params: Captures::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a handler at the path for all methods.
|
||||
pub fn any<F>(&mut self, path: &str, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.any_methods.add(path, Box::new(handler)).unwrap();
|
||||
}
|
||||
|
||||
/// Register a handler at the path for the specified HTTP method.
|
||||
pub fn add<F>(&mut self, path: &str, method: http_types::Method, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.methods_map
|
||||
.entry(method)
|
||||
.or_insert_with(MethodRouter::new)
|
||||
.add(path, Box::new(handler))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Register a handler at the path for the HTTP GET method.
|
||||
pub fn get<F>(&mut self, path: &str, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.add(path, http_types::Method::GET, handler)
|
||||
}
|
||||
|
||||
/// Register a handler at the path for the HTTP HEAD method.
|
||||
pub fn head<F>(&mut self, path: &str, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.add(path, http_types::Method::HEAD, handler)
|
||||
}
|
||||
|
||||
/// Register a handler at the path for the HTTP POST method.
|
||||
pub fn post<F>(&mut self, path: &str, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.add(path, http_types::Method::POST, handler)
|
||||
}
|
||||
|
||||
/// Register a handler at the path for the HTTP DELETE method.
|
||||
pub fn delete<F>(&mut self, path: &str, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.add(path, http_types::Method::DELETE, handler)
|
||||
}
|
||||
|
||||
/// Register a handler at the path for the HTTP PUT method.
|
||||
pub fn put<F>(&mut self, path: &str, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.add(path, http_types::Method::PUT, handler)
|
||||
}
|
||||
|
||||
/// Register a handler at the path for the HTTP PATCH method.
|
||||
pub fn patch<F>(&mut self, path: &str, handler: F)
|
||||
where
|
||||
F: Fn(Request, Params) -> Result<Response> + 'static,
|
||||
{
|
||||
self.add(path, http_types::Method::PATCH, handler)
|
||||
}
|
||||
|
||||
/// Construct a new Router.
|
||||
pub fn new() -> Self {
|
||||
Router {
|
||||
methods_map: HashMap::default(),
|
||||
any_methods: MethodRouter::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn not_found(_req: Request, _params: Params) -> Result<Response> {
|
||||
Ok(http_types::Response::builder()
|
||||
.status(http_types::StatusCode::NOT_FOUND)
|
||||
.body(None)
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
fn method_not_allowed(_req: Request, _params: Params) -> Result<Response> {
|
||||
Ok(http_types::Response::builder()
|
||||
.status(http_types::StatusCode::METHOD_NOT_ALLOWED)
|
||||
.body(None)
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
/// A macro to help with constructing a Router from a stream of tokens.
|
||||
#[macro_export]
|
||||
macro_rules! http_router {
|
||||
($($method:tt $path:literal => $h:expr),*) => {
|
||||
{
|
||||
let mut router = spin_sdk::http::Router::new();
|
||||
$(
|
||||
spin_sdk::http_router!(@build router $method $path => $h);
|
||||
)*
|
||||
router
|
||||
}
|
||||
};
|
||||
(@build $r:ident HEAD $path:literal => $h:expr) => {
|
||||
$r.head($path, $h);
|
||||
};
|
||||
(@build $r:ident GET $path:literal => $h:expr) => {
|
||||
$r.get($path, $h);
|
||||
};
|
||||
(@build $r:ident PUT $path:literal => $h:expr) => {
|
||||
$r.put($path, $h);
|
||||
};
|
||||
(@build $r:ident POST $path:literal => $h:expr) => {
|
||||
$r.post($path, $h);
|
||||
};
|
||||
(@build $r:ident PATCH $path:literal => $h:expr) => {
|
||||
$r.patch($path, $h);
|
||||
};
|
||||
(@build $r:ident DELETE $path:literal => $h:expr) => {
|
||||
$r.delete($path, $h);
|
||||
};
|
||||
(@build $r:ident _ $path:literal => $h:expr) => {
|
||||
$r.any($path, $h);
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn make_request(method: http_types::Method, path: &str) -> Request {
|
||||
http_types::Request::builder()
|
||||
.method(method)
|
||||
.uri(path)
|
||||
.body(None)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn echo_param(req: Request, params: Params) -> Result<Response> {
|
||||
match params.get("x") {
|
||||
Some(path) => Ok(http_types::Response::builder()
|
||||
.status(http_types::StatusCode::OK)
|
||||
.body(Some(path.to_string().into()))?),
|
||||
None => not_found(req, params),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_not_allowed() {
|
||||
let mut router = Router::default();
|
||||
router.get("/:x", echo_param);
|
||||
|
||||
let req = make_request(http_types::Method::POST, "/foobar");
|
||||
let res = router.handle(req).unwrap();
|
||||
assert_eq!(res.status(), http_types::StatusCode::METHOD_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_found() {
|
||||
fn h1(_req: Request, _params: Params) -> Result<Response> {
|
||||
Ok(http_types::Response::builder().status(200).body(None)?)
|
||||
}
|
||||
|
||||
let mut router = Router::default();
|
||||
router.get("/h1/:param", h1);
|
||||
|
||||
let req = make_request(http_types::Method::GET, "/h1/");
|
||||
let res = router.handle(req).unwrap();
|
||||
assert_eq!(res.status(), http_types::StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_param() {
|
||||
fn multiply(_req: Request, params: Params) -> Result<Response> {
|
||||
let x: i64 = params.get("x").unwrap().parse()?;
|
||||
let y: i64 = params.get("y").unwrap().parse()?;
|
||||
Ok(http_types::Response::builder()
|
||||
.status(http_types::StatusCode::OK)
|
||||
.body(Some(format!("{result}", result = x * y).into()))?)
|
||||
}
|
||||
|
||||
let mut router = Router::default();
|
||||
router.get("/multiply/:x/:y", multiply);
|
||||
|
||||
let req = make_request(http_types::Method::GET, "/multiply/2/4");
|
||||
let res = router.handle(req).unwrap();
|
||||
|
||||
assert_eq!(res.into_body().unwrap(), "8".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_param() {
|
||||
let mut router = Router::default();
|
||||
router.get("/:x", echo_param);
|
||||
|
||||
let req = make_request(http_types::Method::GET, "/y");
|
||||
let res = router.handle(req).unwrap();
|
||||
|
||||
assert_eq!(res.into_body().unwrap(), "y".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wildcard() {
|
||||
fn echo_wildcard(req: Request, params: Params) -> Result<Response> {
|
||||
match params.wildcard() {
|
||||
Some(path) => Ok(http_types::Response::builder()
|
||||
.status(http_types::StatusCode::OK)
|
||||
.body(Some(path.to_string().into()))?),
|
||||
None => not_found(req, params),
|
||||
}
|
||||
}
|
||||
|
||||
let mut router = Router::default();
|
||||
router.get("/*", echo_wildcard);
|
||||
|
||||
let req = make_request(http_types::Method::GET, "/foo/bar");
|
||||
let res = router.handle(req).unwrap();
|
||||
assert_eq!(res.status(), http_types::StatusCode::OK);
|
||||
assert_eq!(res.into_body().unwrap(), "foo/bar".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wildcard_last_segment() {
|
||||
let mut router = Router::default();
|
||||
router.get("/:x/*", echo_param);
|
||||
|
||||
let req = make_request(http_types::Method::GET, "/foo/bar");
|
||||
let res = router.handle(req).unwrap();
|
||||
assert_eq!(res.into_body().unwrap(), "foo".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ambiguous_wildcard_vs_star() {
|
||||
fn h1(_req: Request, _params: Params) -> Result<Response> {
|
||||
Ok(http_types::Response::builder()
|
||||
.status(http_types::StatusCode::OK)
|
||||
.body(Some("one/two".into()))?)
|
||||
}
|
||||
|
||||
fn h2(_req: Request, _params: Params) -> Result<Response> {
|
||||
Ok(http_types::Response::builder()
|
||||
.status(http_types::StatusCode::OK)
|
||||
.body(Some("posts/*".into()))?)
|
||||
}
|
||||
|
||||
let mut router = Router::default();
|
||||
router.get("/:one/:two", h1);
|
||||
router.get("/posts/*", h2);
|
||||
|
||||
let req = make_request(http_types::Method::GET, "/posts/2");
|
||||
let res = router.handle(req).unwrap();
|
||||
|
||||
assert_eq!(res.into_body().unwrap(), "posts/*".to_string());
|
||||
}
|
||||
}
|
|
@ -28,23 +28,27 @@ pub mod http {
|
|||
use anyhow::Result;
|
||||
|
||||
/// The Spin HTTP request.
|
||||
pub type Request = http::Request<Option<bytes::Bytes>>;
|
||||
pub type Request = http_types::Request<Option<bytes::Bytes>>;
|
||||
|
||||
/// The Spin HTTP response.
|
||||
pub type Response = http::Response<Option<bytes::Bytes>>;
|
||||
pub type Response = http_types::Response<Option<bytes::Bytes>>;
|
||||
|
||||
pub use crate::outbound_http::send_request as send;
|
||||
|
||||
/// Exports HTTP Router items.
|
||||
pub use router::*;
|
||||
mod router;
|
||||
|
||||
/// Helper function to return a 404 Not Found response.
|
||||
pub fn not_found() -> Result<Response> {
|
||||
Ok(http::Response::builder()
|
||||
Ok(http_types::Response::builder()
|
||||
.status(404)
|
||||
.body(Some("Not Found".into()))?)
|
||||
}
|
||||
|
||||
/// Helper function to return a 500 Internal Server Error response.
|
||||
pub fn internal_server_error() -> Result<Response> {
|
||||
Ok(http::Response::builder()
|
||||
Ok(http_types::Response::builder()
|
||||
.status(500)
|
||||
.body(Some("Internal Server Error".into()))?)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use http::{header::HeaderName, HeaderValue};
|
||||
use http_types::{header::HeaderName, HeaderValue};
|
||||
|
||||
use super::http::{Request, Response};
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub fn send_request(req: Request) -> Result<Response> {
|
|||
body,
|
||||
} = wasi_outbound_http::request(out_req)?;
|
||||
|
||||
let resp_builder = http::response::Builder::new().status(status);
|
||||
let resp_builder = http_types::response::Builder::new().status(status);
|
||||
let resp_builder = headers
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
@ -64,11 +64,11 @@ fn try_header_to_strs<'k, 'v>(
|
|||
))
|
||||
}
|
||||
|
||||
impl TryFrom<http::Method> for wasi_outbound_http::Method {
|
||||
impl TryFrom<http_types::Method> for wasi_outbound_http::Method {
|
||||
type Error = OutboundHttpError;
|
||||
|
||||
fn try_from(method: http::Method) -> Result<Self> {
|
||||
use http::Method;
|
||||
fn try_from(method: http_types::Method) -> Result<Self> {
|
||||
use http_types::Method;
|
||||
use wasi_outbound_http::Method::*;
|
||||
Ok(match method {
|
||||
Method::GET => Get,
|
||||
|
|
|
@ -19,6 +19,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -130,6 +136,36 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "routefinder"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94f8f99b10dedd317514253dda1fa7c14e344aac96e1f78149a64879ce282aca"
|
||||
dependencies = [
|
||||
"smartcow",
|
||||
"smartstring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smartcow"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "656fcb1c1fca8c4655372134ce87d8afdf5ec5949ebabe8d314be0141d8b5da2"
|
||||
dependencies = [
|
||||
"smartstring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smartstring"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"static_assertions",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin-macro"
|
||||
version = "0.1.0"
|
||||
|
@ -151,11 +187,18 @@ dependencies = [
|
|||
"bytes",
|
||||
"form_urlencoded",
|
||||
"http",
|
||||
"routefinder",
|
||||
"spin-macro",
|
||||
"thiserror",
|
||||
"wit-bindgen-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.85"
|
||||
|
|
|
@ -19,6 +19,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -126,6 +132,16 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "routefinder"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94f8f99b10dedd317514253dda1fa7c14e344aac96e1f78149a64879ce282aca"
|
||||
dependencies = [
|
||||
"smartcow",
|
||||
"smartstring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple-spin-rust"
|
||||
version = "0.1.0"
|
||||
|
@ -137,6 +153,26 @@ dependencies = [
|
|||
"wit-bindgen-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smartcow"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "656fcb1c1fca8c4655372134ce87d8afdf5ec5949ebabe8d314be0141d8b5da2"
|
||||
dependencies = [
|
||||
"smartstring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smartstring"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"static_assertions",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin-macro"
|
||||
version = "0.1.0"
|
||||
|
@ -158,11 +194,18 @@ dependencies = [
|
|||
"bytes",
|
||||
"form_urlencoded",
|
||||
"http",
|
||||
"routefinder",
|
||||
"spin-macro",
|
||||
"thiserror",
|
||||
"wit-bindgen-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.85"
|
||||
|
|
Loading…
Reference in New Issue