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}