Skip to content

Commit 0741f2b

Browse files
dejanbjcrossley3
authored andcommitted
Add support for core http crate binding
Signed-off-by: Dejan Bosanac <[email protected]>
1 parent 62b895c commit 0741f2b

File tree

5 files changed

+145
-5
lines changed

5 files changed

+145
-5
lines changed

Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ categories = ["web-programming", "encoding", "data-structures"]
1717
name = "cloudevents"
1818

1919
[features]
20+
http-binding = ["async-trait", "bytes", "futures", "http"]
2021
actix = ["actix-web", "async-trait", "bytes", "futures", "http"]
2122
reqwest = ["reqwest-lib", "async-trait", "bytes", "http"]
2223
rdkafka = ["rdkafka-lib", "bytes", "futures"]
@@ -43,17 +44,20 @@ bytes = { version = "^1.0", optional = true }
4344
futures = { version = "^0.3", optional = true }
4445
http = { version = "0.2", optional = true }
4546
hyper = { version = "^0.14", optional = true }
46-
axum-lib = { version = "^0.2", optional = true , package="axum"}
47+
axum-lib = { version = "^0.2", optional = true, package="axum"}
4748
http-body = { version = "^0.4", optional = true}
4849

4950
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
5051
hostname = "^0.3"
5152
uuid = { version = "^0.8", features = ["v4"] }
5253

53-
[target.'cfg(target_arch = "wasm32")'.dependencies]
54+
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
5455
web-sys = { version = "^0.3", features = ["Window", "Location"] }
5556
uuid = { version = "^0.8", features = ["v4", "wasm-bindgen"] }
5657

58+
[target.'cfg(all(target_arch = "wasm32", target_os="wasi"))'.dependencies]
59+
uuid = { version = "^0.8", features = ["v4"] }
60+
5761
[dev-dependencies]
5862
rstest = "0.6"
5963
claim = "0.3.1"

src/binding/http/mod.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub mod builder;
2-
mod deserializer;
2+
pub mod deserializer;
33
mod headers;
44

55
use crate::{
@@ -11,7 +11,11 @@ pub use headers::Headers;
1111
mod serializer;
1212

1313
pub use builder::Builder;
14+
use core::convert::TryFrom;
15+
use http::Response;
1416
pub use serializer::Serializer;
17+
use std::convert::TryInto;
18+
use std::fmt::Debug;
1519

1620
pub static SPEC_VERSION_HEADER: &str = "ce-specversion";
1721

@@ -26,3 +30,42 @@ pub fn to_event<'a, T: Headers<'a>>(
2630
pub fn header_prefix(name: &str) -> String {
2731
super::header_prefix("ce-", name)
2832
}
33+
34+
impl<T> TryFrom<Response<T>> for Event
35+
where
36+
T: TryInto<Vec<u8>>,
37+
<T as TryInto<Vec<u8>>>::Error: Debug,
38+
{
39+
type Error = crate::message::Error;
40+
41+
fn try_from(response: Response<T>) -> Result<Self, Self::Error> {
42+
let headers = response.headers().to_owned();
43+
let body = T::try_into(response.into_body()).unwrap();
44+
45+
to_event(&headers, body)
46+
}
47+
}
48+
49+
#[cfg(test)]
50+
mod tests {
51+
use crate::test::fixtures;
52+
use crate::Event;
53+
use core::convert::TryFrom;
54+
use http::Response;
55+
56+
#[test]
57+
fn test_response_to_event() {
58+
let event = fixtures::v10::minimal_string_extension();
59+
60+
let response = Response::builder()
61+
.header("ce-id", fixtures::id())
62+
.header("ce-source", fixtures::source())
63+
.header("ce-type", fixtures::ty())
64+
.header("ce-specversion", "1.0")
65+
.header("ce-someint", "10")
66+
.body(Vec::new())
67+
.unwrap();
68+
69+
assert_eq!(event, Event::try_from(response).unwrap());
70+
}
71+
}

src/binding/http/serializer.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ use crate::binding::{
66
CLOUDEVENTS_JSON_HEADER,
77
};
88
use crate::event::SpecVersion;
9-
use crate::message::{BinarySerializer, MessageAttributeValue, Result, StructuredSerializer};
9+
use crate::message::BinaryDeserializer;
10+
use crate::message::{
11+
BinarySerializer, Error, MessageAttributeValue, Result, StructuredSerializer,
12+
};
13+
use crate::Event;
14+
use http::Request;
15+
use std::convert::TryFrom;
16+
use std::fmt::Debug;
1017

1118
macro_rules! str_to_header_value {
1219
($header_value:expr) => {
@@ -70,3 +77,81 @@ impl<T> StructuredSerializer<T> for Serializer<T> {
7077
builder.body(bytes)
7178
}
7279
}
80+
81+
impl<T> BinarySerializer<http::request::Request<Option<T>>> for http::request::Builder
82+
where
83+
T: TryFrom<Vec<u8>>,
84+
<T as TryFrom<Vec<u8>>>::Error: Debug,
85+
{
86+
fn set_spec_version(mut self, sv: SpecVersion) -> Result<Self> {
87+
self = self.header(SPEC_VERSION_HEADER, &sv.to_string());
88+
Ok(self)
89+
}
90+
91+
fn set_attribute(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
92+
let key = &header_prefix(name);
93+
self = self.header(key, &value.to_string());
94+
Ok(self)
95+
}
96+
97+
fn set_extension(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
98+
let key = &header_prefix(name);
99+
self = self.header(key, &value.to_string());
100+
Ok(self)
101+
}
102+
103+
fn end_with_data(self, bytes: Vec<u8>) -> Result<http::request::Request<Option<T>>> {
104+
let body = T::try_from(bytes).unwrap();
105+
self.body(Some(body)).map_err(|e| Error::Other {
106+
source: Box::new(e),
107+
})
108+
}
109+
110+
fn end(self) -> Result<http::request::Request<Option<T>>> {
111+
self.body(None).map_err(|e| Error::Other {
112+
source: Box::new(e),
113+
})
114+
}
115+
}
116+
117+
impl<T> TryFrom<Event> for Request<Option<T>>
118+
where
119+
T: TryFrom<Vec<u8>>,
120+
<T as TryFrom<Vec<u8>>>::Error: Debug,
121+
{
122+
type Error = crate::message::Error;
123+
124+
fn try_from(event: Event) -> Result<Self> {
125+
BinaryDeserializer::deserialize_binary(event, http::request::Builder::new())
126+
}
127+
}
128+
129+
#[cfg(test)]
130+
mod tests {
131+
use crate::test::fixtures;
132+
use bytes::Bytes;
133+
use http::Request;
134+
use std::convert::TryFrom;
135+
136+
#[test]
137+
fn test_event_to_http_request() {
138+
let event = fixtures::v10::minimal_string_extension();
139+
let request: Request<Option<Vec<u8>>> = Request::try_from(event).unwrap();
140+
141+
assert_eq!(request.headers()["ce-id"], "0001");
142+
assert_eq!(request.headers()["ce-type"], "test_event.test_application");
143+
}
144+
145+
#[test]
146+
fn test_event_to_bytes_body() {
147+
let event = fixtures::v10::full_binary_json_data_string_extension();
148+
let request: Request<Option<Vec<u8>>> = Request::try_from(event).unwrap();
149+
150+
assert_eq!(request.headers()["ce-id"], "0001");
151+
assert_eq!(request.headers()["ce-type"], "test_event.test_application");
152+
assert_eq!(
153+
request.body().as_ref().unwrap(),
154+
&Bytes::from(fixtures::json_data().to_string())
155+
);
156+
}
157+
}

src/binding/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod actix;
55
#[cfg(feature = "axum")]
66
pub mod axum;
77
#[cfg(any(
8+
feature = "http-binding",
89
feature = "actix",
910
feature = "warp",
1011
feature = "reqwest",

src/event/attributes.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ pub(crate) fn default_hostname() -> Url {
268268
.unwrap()
269269
}
270270

271-
#[cfg(target_arch = "wasm32")]
271+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
272272
pub(crate) fn default_hostname() -> Url {
273273
use std::str::FromStr;
274274

@@ -281,3 +281,10 @@ pub(crate) fn default_hostname() -> Url {
281281
)
282282
.unwrap()
283283
}
284+
285+
#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
286+
pub(crate) fn default_hostname() -> Url {
287+
use std::str::FromStr;
288+
289+
Url::from_str("http://localhost").unwrap()
290+
}

0 commit comments

Comments
 (0)