wasmcloud_actor_http_server/
lib.rs

1#![doc(html_logo_url = "https://avatars2.githubusercontent.com/u/52050279?s=200&v=4")]
2//! # HTTP Server wasmCloud Actor Interface
3//!
4//! This crate provides wasmCloud actors with an interface to the HTTP Server capability provider. Actors using this
5//! interface must have the claim `wasmcloud:httpserver` in order to have permission to handle requests, and they
6//! must have an active, configured binding to an HTTP Server capability provider.
7//!
8//! The HTTP Server provider is one-way, and only delivers messages to actors. Actors cannot make host calls
9//! to this provider. To make outbound http requests, actors will need to use a `wasmcloud:httpclient` provider.
10//!
11//! # Example:
12//! ```
13//! use wasmcloud_actor_http_server as http;
14//! use wasmcloud_actor_core as actor;
15//! use wapc_guest::HandlerResult;
16//! use http::{Request, Response, Handlers, Method};
17//!
18//! #[actor::init]
19//! fn init() {
20//!     http::Handlers::register_handle_request(req_handler);
21//! }
22//!
23//! fn req_handler(req: http::Request) -> HandlerResult<http::Response> {
24//!     let method = req.method();
25//!     let segments = req.path_segments();
26//!
27//!     match (method, &*segments)  {
28//!         (Method::Get, &["v0", "users", id]) => get_user(id),
29//!         (Method::Put, &["v1", "users", id]) => update_user(id, &req.body),
30//!         _ => Ok(http::Response::not_found())
31//!     }
32//! }
33//!
34//! fn get_user(id: &str) -> HandlerResult<http::Response> {
35//!     Ok(http::Response::ok())
36//! }
37//! fn update_user(id: &str, body: &[u8]) -> HandlerResult<http::Response> {
38//!     Ok(http::Response::ok())
39//! }
40//! ```
41
42pub mod generated;
43mod route;
44use serde::Serialize;
45use std::collections::HashMap;
46
47pub use route::Method;
48
49#[cfg(feature = "guest")]
50pub use generated::Handlers;
51pub use generated::{deserialize, serialize, Request, Response};
52
53use std::str::FromStr;
54
55impl Request {
56    pub fn path_segments(&self) -> Vec<&str> {
57        self.path.split('/').skip(1).collect::<Vec<_>>()
58    }
59
60    pub fn method(&self) -> Method {
61        Method::from_str(&self.method).unwrap()
62    }
63}
64
65impl Response {
66    /// Creates a response with a given status code and serializes the given payload as JSON
67    pub fn json<T>(payload: T, status_code: u32, status: &str) -> Response
68    where
69        T: Serialize,
70    {
71        Response {
72            body: serde_json::to_string(&payload).unwrap().into_bytes(),
73            header: HashMap::new(),
74            status: status.to_string(),
75            status_code,
76        }
77    }
78
79    /// Handy shortcut for creating a 404/Not Found response
80    pub fn not_found() -> Response {
81        Response {
82            status: "Not Found".to_string(),
83            status_code: 404,
84            ..Default::default()
85        }
86    }
87
88    /// Useful shortcut for creating a 200/OK response
89    pub fn ok() -> Response {
90        Response {
91            status: "OK".to_string(),
92            status_code: 200,
93            ..Default::default()
94        }
95    }
96
97    /// Useful shortcut for creating a 500/Internal Server Error response
98    pub fn internal_server_error(msg: &str) -> Response {
99        Response {
100            status: "Internal Server Error".to_string(),
101            status_code: 500,
102            body: msg.to_string().as_bytes().into(),
103            ..Default::default()
104        }
105    }
106
107    /// Shortcut for creating a 400/Bad Request response
108    pub fn bad_request() -> Response {
109        Response {
110            status: "Bad Request".to_string(),
111            status_code: 400,
112            ..Default::default()
113        }
114    }
115}
116
117#[cfg(test)]
118#[cfg(feature = "guest")]
119mod test {
120    extern crate wapc_guest;
121    use crate::{Handlers, Request, Response};
122    use wapc_guest::HandlerResult;
123    #[test]
124    fn it_works() {
125        Handlers::register_handle_request(hr);
126        assert!(true);
127    }
128
129    fn hr(_req: Request) -> HandlerResult<Response> {
130        Ok(Response::ok())
131    }
132}