From e16e9667cfff9c00b19526862debbb9c27bc9cea Mon Sep 17 00:00:00 2001 From: Sunli Date: Thu, 11 Nov 2021 09:33:45 +0800 Subject: [PATCH] Add poem-example Signed-off-by: Sunli --- .github/workflows/rust_tests.yml | 9 ++ Cargo.toml | 2 +- example-projects/poem-example/Cargo.toml | 15 ++++ example-projects/poem-example/README.md | 23 +++++ example-projects/poem-example/src/main.rs | 102 ++++++++++++++++++++++ 5 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 example-projects/poem-example/Cargo.toml create mode 100644 example-projects/poem-example/README.md create mode 100644 example-projects/poem-example/src/main.rs diff --git a/.github/workflows/rust_tests.yml b/.github/workflows/rust_tests.yml index c071688..df77e47 100644 --- a/.github/workflows/rust_tests.yml +++ b/.github/workflows/rust_tests.yml @@ -137,3 +137,12 @@ jobs: command: build toolchain: ${{ matrix.toolchain }} args: --target ${{ matrix.target }} --manifest-path ./example-projects/axum-example/Cargo.toml + + - uses: actions-rs/cargo@v1 + name: "Build poem-example" + if: matrix.target == 'x86_64-unknown-linux-gnu' && matrix.toolchain == 'stable' + with: + command: build + toolchain: ${{ matrix.toolchain }} + args: --target ${{ matrix.target }} --manifest-path ./example-projects/poem-example/Cargo.toml + diff --git a/Cargo.toml b/Cargo.toml index df99710..576ed05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ http = { version = "0.2", optional = true } hyper = { version = "^0.14", optional = true } axum-lib = { version = "^0.2", optional = true, package = "axum" } http-body = { version = "^0.4", optional = true } -poem-lib = { version = "1.0.21", optional = true, package = "poem" } +poem-lib = { version = "1.0.23", optional = true, package = "poem" } [target."cfg(not(target_arch = \"wasm32\"))".dependencies] hostname = "^0.3" diff --git a/example-projects/poem-example/Cargo.toml b/example-projects/poem-example/Cargo.toml new file mode 100644 index 0000000..6774902 --- /dev/null +++ b/example-projects/poem-example/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "poem-example" +version = "0.1.0" +edition = "2021" + +[dependencies] +cloudevents-sdk = { path = "../..", features = ["poem"] } +tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] } +tracing = "0.1" +poem = { version = "1.0.23" } +tracing-subscriber = "0.2" + +[dev-dependencies] +chrono = { version = "0.4", features = ["serde"] } +serde_json = "1.0" diff --git a/example-projects/poem-example/README.md b/example-projects/poem-example/README.md new file mode 100644 index 0000000..aac4ca8 --- /dev/null +++ b/example-projects/poem-example/README.md @@ -0,0 +1,23 @@ +To run the server: + +```console +cargo run +``` + +To test a GET: + +```console +curl http://localhost:8080 +``` + +To test a POST: + +```console +curl -d '{"hello": "world"}' \ + -H'content-type: application/json' \ + -H'ce-specversion: 1.0' \ + -H'ce-id: 1' \ + -H'ce-source: http://cloudevents.io' \ + -H'ce-type: dev.knative.example' \ + http://localhost:8080 +``` diff --git a/example-projects/poem-example/src/main.rs b/example-projects/poem-example/src/main.rs new file mode 100644 index 0000000..ba16bd8 --- /dev/null +++ b/example-projects/poem-example/src/main.rs @@ -0,0 +1,102 @@ +use cloudevents::Event; +use poem::listener::TcpListener; +use poem::middleware::Tracing; +use poem::{get, handler, Endpoint, EndpointExt, Response, Route, Server}; + +#[handler] +async fn index_get() -> &'static str { + "hello from cloudevents server" +} + +#[handler] +async fn index_post(event: Event) -> Event { + tracing::debug!("received cloudevent {}", &event); + event +} + +fn echo_app() -> impl Endpoint { + Route::new() + .at("/", get(index_get).post(index_post)) + .with(Tracing) +} + +#[tokio::main] +async fn main() -> Result<(), std::io::Error> { + if std::env::var("RUST_LOG").is_err() { + std::env::set_var("RUST_LOG", "poem=debug") + } + tracing_subscriber::fmt::init(); + + let server = Server::new(TcpListener::bind("127.0.0.1:8080")).await?; + server.run(echo_app()).await +} + +#[cfg(test)] +mod tests { + use super::*; + use chrono::Utc; + use poem::http::Method; + use poem::{Body, Request}; + use serde_json::json; + + #[tokio::test] + async fn poem_test() { + if std::env::var("RUST_LOG").is_err() { + std::env::set_var("RUST_LOG", "poem_example=debug") + } + tracing_subscriber::fmt::init(); + + let app = echo_app(); + let time = Utc::now(); + let j = json!({"hello": "world"}); + let request = Request::builder() + .method(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_json(&j).unwrap()); + + let resp: Response = app.call(request).await; + 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" + ); + + assert_eq!( + j.to_string().as_bytes(), + resp.into_body().into_vec().await.unwrap() + ); + } +}