Skip to content

Commit 935234a

Browse files
committed
New feature: cloudevents-actix
Conditionally compile actix module when enabled Mostly straightforward, though I don't particularly love that dev-deps can't be optional: rust-lang/cargo#1596 Signed-off-by: Jim Crossley <[email protected]>
1 parent 303ed92 commit 935234a

File tree

11 files changed

+575
-8
lines changed

11 files changed

+575
-8
lines changed

Cargo.toml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ categories = ["web-programming", "encoding", "data-structures"]
1616
[lib]
1717
name = "cloudevents"
1818

19+
[features]
20+
cloudevents-actix = ["actix-web", "async-trait", "lazy_static", "bytes", "futures"]
21+
1922
[dependencies]
2023
serde = { version = "^1.0", features = ["derive"] }
2124
serde_json = "^1.0"
@@ -26,6 +29,13 @@ url = { version = "^2.1", features = ["serde"] }
2629
snafu = "^0.6"
2730
bitflags = "^1.2"
2831

32+
# actix optional deps
33+
actix-web = { version = "^3", default-features = false, optional = true }
34+
async-trait = { version = "^0.1.33", optional = true }
35+
lazy_static = { version = "1.4.0", optional = true }
36+
bytes = { version = "^1.0", optional = true }
37+
futures = { version = "^0.3", optional = true }
38+
2939
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
3040
hostname = "^0.3"
3141
uuid = { version = "^0.8", features = ["v4"] }
@@ -40,13 +50,19 @@ claim = "0.3.1"
4050
version-sync = "^0.9"
4151
serde_yaml = "0.8"
4252

53+
# actix dev-deps
54+
actix-rt = { version = "^1" }
55+
url = { version = "^2.1", features = ["serde"] }
56+
serde_json = { version = "^1.0" }
57+
chrono = { version = "^0.4", features = ["serde"] }
58+
4359
[workspace]
4460
members = [
4561
".",
4662
"cloudevents-sdk-actix-web",
4763
"cloudevents-sdk-reqwest",
4864
"cloudevents-sdk-rdkafka",
49-
"cloudevents-sdk-warp"
65+
"cloudevents-sdk-warp",
5066
]
5167
exclude = [
5268
"example-projects/actix-web-example",

cloudevents-sdk-actix-web/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ cloudevents-sdk = { version = "0.3.0", path = ".." }
1717
actix-web = { version = "^3", default-features = false }
1818
async-trait = "^0.1.33"
1919
lazy_static = "1.4.0"
20-
bytes = "^0.5"
20+
bytes = "^1.0"
2121
futures = "^0.3"
2222

2323
[dev-dependencies]

cloudevents-sdk-rdkafka/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ categories = ["web-programming", "encoding"]
1414

1515
[dependencies]
1616
bytes = "^1.0"
17-
cloudevents-sdk = { version = "0.3.0", path = ".." }
17+
cloudevents-sdk = { path = ".." }
1818
lazy_static = "1.4.0"
1919
rdkafka = { version = "^0.25", features = ["cmake-build"] }
2020

2121
[dev-dependencies]
2222
url = { version = "^2.1" }
2323
serde_json = "^1.0"
2424
chrono = { version = "^0.4", features = ["serde"] }
25-
futures = "0.3.5"
25+
futures = "^0.3"
2626
version-sync = "^0.9"

cloudevents-sdk-reqwest/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ categories = ["web-programming", "encoding", "web-programming::http-client"]
1414

1515
[dependencies]
1616
async-trait = "^0.1.33"
17-
cloudevents-sdk = { version = "0.3.0", path = ".." }
17+
cloudevents-sdk = { path = ".." }
1818
lazy_static = "1.4.0"
1919
bytes = "^1.0"
2020

example-projects/actix-web-example/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ authors = ["Francesco Guardiani <[email protected]>"]
55
edition = "2018"
66

77
[dependencies]
8-
cloudevents-sdk = { path = "../.." }
9-
cloudevents-sdk-actix-web = { path = "../../cloudevents-sdk-actix-web" }
8+
cloudevents-sdk = { path = "../..", features = ["cloudevents-actix"] }
109
actix-web = "^3"
1110
actix-cors = "^0.5"
1211
lazy_static = "1.4.0"

example-projects/actix-web-example/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer};
2+
use cloudevents::actix::{HttpRequestExt, HttpResponseBuilderExt};
23
use cloudevents::{EventBuilder, EventBuilderV10};
3-
use cloudevents_sdk_actix_web::{HttpResponseBuilderExt, HttpRequestExt};
44
use serde_json::json;
55

66
#[post("/")]

src/actix/headers.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use crate::event::SpecVersion;
2+
use actix_web::http::header;
3+
use actix_web::http::{HeaderName, HeaderValue};
4+
use lazy_static::lazy_static;
5+
use std::collections::HashMap;
6+
use std::str::FromStr;
7+
8+
macro_rules! unwrap_optional_header {
9+
($headers:expr, $name:expr) => {
10+
$headers
11+
.get::<&'static HeaderName>(&$name)
12+
.map(|a| header_value_to_str!(a))
13+
};
14+
}
15+
16+
macro_rules! header_value_to_str {
17+
($header_value:expr) => {
18+
$header_value
19+
.to_str()
20+
.map_err(|e| crate::message::Error::Other {
21+
source: Box::new(e),
22+
})
23+
};
24+
}
25+
26+
macro_rules! str_to_header_value {
27+
($header_value:expr) => {
28+
HeaderValue::from_str($header_value).map_err(|e| crate::message::Error::Other {
29+
source: Box::new(e),
30+
})
31+
};
32+
}
33+
34+
macro_rules! str_name_to_header {
35+
($attribute:expr) => {
36+
HeaderName::from_str($attribute).map_err(|e| crate::message::Error::Other {
37+
source: Box::new(e),
38+
})
39+
};
40+
}
41+
42+
macro_rules! attribute_name_to_header {
43+
($attribute:expr) => {
44+
str_name_to_header!(&["ce-", $attribute].concat())
45+
};
46+
}
47+
48+
fn attributes_to_headers(
49+
it: impl Iterator<Item = &'static str>,
50+
) -> HashMap<&'static str, HeaderName> {
51+
it.map(|s| {
52+
if s == "datacontenttype" {
53+
(s, header::CONTENT_TYPE)
54+
} else {
55+
(s, attribute_name_to_header!(s).unwrap())
56+
}
57+
})
58+
.collect()
59+
}
60+
61+
lazy_static! {
62+
pub(crate) static ref ATTRIBUTES_TO_HEADERS: HashMap<&'static str, HeaderName> =
63+
attributes_to_headers(SpecVersion::all_attribute_names());
64+
pub(crate) static ref SPEC_VERSION_HEADER: HeaderName =
65+
HeaderName::from_static("ce-specversion");
66+
pub(crate) static ref CLOUDEVENTS_JSON_HEADER: HeaderValue =
67+
HeaderValue::from_static("application/cloudevents+json");
68+
}

src/actix/mod.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! This crate integrates the [cloudevents-sdk](https://docs.rs/cloudevents-sdk) with [Actix web](https://docs.rs/actix-web/) to easily send and receive CloudEvents.
2+
//!
3+
//! To deserialize an HTTP request as CloudEvent:
4+
//!
5+
//! ```
6+
//! use cloudevents::actix::HttpRequestExt;
7+
//! use actix_web::{HttpRequest, web, post};
8+
//!
9+
//! #[post("/")]
10+
//! async fn post_event(req: HttpRequest, payload: web::Payload) -> Result<String, actix_web::Error> {
11+
//! let event = req.to_event(payload).await?;
12+
//! println!("Received Event: {:?}", event);
13+
//! Ok(format!("{:?}", event))
14+
//! }
15+
//! ```
16+
//!
17+
//! To serialize a CloudEvent to an HTTP response:
18+
//!
19+
//! ```
20+
//! use cloudevents::actix::HttpResponseBuilderExt;
21+
//! use actix_web::{HttpRequest, web, get, HttpResponse};
22+
//! use cloudevents::{EventBuilderV10, EventBuilder};
23+
//! use serde_json::json;
24+
//!
25+
//! #[get("/")]
26+
//! async fn get_event() -> Result<HttpResponse, actix_web::Error> {
27+
//! Ok(HttpResponse::Ok()
28+
//! .event(
29+
//! EventBuilderV10::new()
30+
//! .id("0001")
31+
//! .ty("example.test")
32+
//! .source("http://localhost/")
33+
//! .data("application/json", json!({"hello": "world"}))
34+
//! .build()
35+
//! .expect("No error while building the event"),
36+
//! )
37+
//! .await?
38+
//! )
39+
//! }
40+
//! ```
41+
//!
42+
//! Check out the [cloudevents-sdk](https://docs.rs/cloudevents-sdk) docs for more details on how to use [`cloudevents::Event`]
43+
44+
#![doc(html_root_url = "https://docs.rs/cloudevents-sdk/0.3.1")]
45+
#![deny(broken_intra_doc_links)]
46+
47+
#[macro_use]
48+
mod headers;
49+
mod server_request;
50+
mod server_response;
51+
52+
pub use server_request::request_to_event;
53+
pub use server_request::HttpRequestDeserializer;
54+
pub use server_request::HttpRequestExt;
55+
pub use server_response::event_to_response;
56+
pub use server_response::HttpResponseBuilderExt;
57+
pub use server_response::HttpResponseSerializer;

0 commit comments

Comments
 (0)