//! This module integrates the [cloudevents-sdk](https://docs.rs/cloudevents-sdk) with [Axum web service framework](https://docs.rs/axum/) //! to easily send and receive CloudEvents. //! //! To deserialize an HTTP request as CloudEvent //! //! To echo events: //! //! ``` //! use axum_lib as axum; //! use axum::{ //! routing::{get, post}, //! Router, //! }; //! use cloudevents::Event; //! use http::StatusCode; //! //! fn app() -> Router { //! Router::new() //! .route("/", get(|| async { "hello from cloudevents server" })) //! .route( //! "/", //! post(|event: Event| async move { //! println!("received cloudevent {}", &event); //! (StatusCode::OK, event) //! }), //! ) //! } //! //! ``` //! //! To create event inside request handlers and send them as responses: //! //! ``` //! use axum_lib as axum; //! use axum::{ //! routing::{get, post}, //! Router, //! }; //! use cloudevents::{Event, EventBuilder, EventBuilderV10}; //! use http::StatusCode; //! use serde_json::json; //! //! fn app() -> Router { //! Router::new() //! .route("/", get(|| async { "hello from cloudevents server" })) //! .route( //! "/", //! post(|| async move { //! let event = EventBuilderV10::new() //! .id("1") //! .source("url://example_response/") //! .ty("example.ce") //! .data( //! mime::APPLICATION_JSON.to_string(), //! json!({ //! "name": "John Doe", //! "age": 43, //! "phones": [ //! "+44 1234567", //! "+44 2345678" //! ] //! }), //! ) //! .build() //! .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?; //! //! Ok::(event) //! }), //! ) //! } //! //! ``` pub mod extract; pub mod response; #[cfg(test)] mod tests { use axum_lib as axum; use axum::{ body::Body, http::{self, Request, StatusCode}, routing::{get, post}, Router, }; use chrono::Utc; use serde_json::json; use tower::ServiceExt; // for `app.oneshot()` use crate::Event; fn echo_app() -> Router { Router::new() .route("/", get(|| async { "hello from cloudevents server" })) .route( "/", post(|event: Event| async move { println!("received cloudevent {}", &event); (StatusCode::OK, event) }), ) } #[tokio::test] async fn axum_mod_test() { let app = echo_app(); let time = Utc::now(); let j = json!({"hello": "world"}); let request = Request::builder() .method(http::Method::POST) .header("ce-specversion", "1.0") .header("ce-id", "0001") .header("ce-type", "example.test") .header("ce-source", "http://localhost/") .header("ce-someint", "10") .header("ce-time", time.to_rfc3339()) .header("content-type", "application/json") .body(Body::from(serde_json::to_vec(&j).unwrap())) .unwrap(); let resp = app.oneshot(request).await.unwrap(); assert_eq!( resp.headers() .get("ce-specversion") .unwrap() .to_str() .unwrap(), "1.0" ); assert_eq!( resp.headers().get("ce-id").unwrap().to_str().unwrap(), "0001" ); assert_eq!( resp.headers().get("ce-type").unwrap().to_str().unwrap(), "example.test" ); assert_eq!( resp.headers().get("ce-source").unwrap().to_str().unwrap(), "http://localhost/" ); assert_eq!( resp.headers() .get("content-type") .unwrap() .to_str() .unwrap(), "application/json" ); assert_eq!( resp.headers().get("ce-someint").unwrap().to_str().unwrap(), "10" ); let (_, body) = resp.into_parts(); let body = axum::body::to_bytes(body, usize::MAX).await.unwrap(); assert_eq!(j.to_string().as_bytes(), body); } }