Add support for core http crate binding

Signed-off-by: Dejan Bosanac <dejan@sensatic.net>
This commit is contained in:
Dejan Bosanac 2021-09-24 12:06:29 +02:00 committed by Jim Crossley
parent 62b895c025
commit 0741f2bf28
5 changed files with 145 additions and 5 deletions

View File

@ -17,6 +17,7 @@ categories = ["web-programming", "encoding", "data-structures"]
name = "cloudevents"
[features]
http-binding = ["async-trait", "bytes", "futures", "http"]
actix = ["actix-web", "async-trait", "bytes", "futures", "http"]
reqwest = ["reqwest-lib", "async-trait", "bytes", "http"]
rdkafka = ["rdkafka-lib", "bytes", "futures"]
@ -43,17 +44,20 @@ bytes = { version = "^1.0", optional = true }
futures = { version = "^0.3", optional = true }
http = { version = "0.2", optional = true }
hyper = { version = "^0.14", optional = true }
axum-lib = { version = "^0.2", optional = true , package="axum"}
axum-lib = { version = "^0.2", optional = true, package="axum"}
http-body = { version = "^0.4", optional = true}
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
hostname = "^0.3"
uuid = { version = "^0.8", features = ["v4"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
web-sys = { version = "^0.3", features = ["Window", "Location"] }
uuid = { version = "^0.8", features = ["v4", "wasm-bindgen"] }
[target.'cfg(all(target_arch = "wasm32", target_os="wasi"))'.dependencies]
uuid = { version = "^0.8", features = ["v4"] }
[dev-dependencies]
rstest = "0.6"
claim = "0.3.1"

View File

@ -1,5 +1,5 @@
pub mod builder;
mod deserializer;
pub mod deserializer;
mod headers;
use crate::{
@ -11,7 +11,11 @@ pub use headers::Headers;
mod serializer;
pub use builder::Builder;
use core::convert::TryFrom;
use http::Response;
pub use serializer::Serializer;
use std::convert::TryInto;
use std::fmt::Debug;
pub static SPEC_VERSION_HEADER: &str = "ce-specversion";
@ -26,3 +30,42 @@ pub fn to_event<'a, T: Headers<'a>>(
pub fn header_prefix(name: &str) -> String {
super::header_prefix("ce-", name)
}
impl<T> TryFrom<Response<T>> for Event
where
T: TryInto<Vec<u8>>,
<T as TryInto<Vec<u8>>>::Error: Debug,
{
type Error = crate::message::Error;
fn try_from(response: Response<T>) -> Result<Self, Self::Error> {
let headers = response.headers().to_owned();
let body = T::try_into(response.into_body()).unwrap();
to_event(&headers, body)
}
}
#[cfg(test)]
mod tests {
use crate::test::fixtures;
use crate::Event;
use core::convert::TryFrom;
use http::Response;
#[test]
fn test_response_to_event() {
let event = fixtures::v10::minimal_string_extension();
let response = Response::builder()
.header("ce-id", fixtures::id())
.header("ce-source", fixtures::source())
.header("ce-type", fixtures::ty())
.header("ce-specversion", "1.0")
.header("ce-someint", "10")
.body(Vec::new())
.unwrap();
assert_eq!(event, Event::try_from(response).unwrap());
}
}

View File

@ -6,7 +6,14 @@ use crate::binding::{
CLOUDEVENTS_JSON_HEADER,
};
use crate::event::SpecVersion;
use crate::message::{BinarySerializer, MessageAttributeValue, Result, StructuredSerializer};
use crate::message::BinaryDeserializer;
use crate::message::{
BinarySerializer, Error, MessageAttributeValue, Result, StructuredSerializer,
};
use crate::Event;
use http::Request;
use std::convert::TryFrom;
use std::fmt::Debug;
macro_rules! str_to_header_value {
($header_value:expr) => {
@ -70,3 +77,81 @@ impl<T> StructuredSerializer<T> for Serializer<T> {
builder.body(bytes)
}
}
impl<T> BinarySerializer<http::request::Request<Option<T>>> for http::request::Builder
where
T: TryFrom<Vec<u8>>,
<T as TryFrom<Vec<u8>>>::Error: Debug,
{
fn set_spec_version(mut self, sv: SpecVersion) -> Result<Self> {
self = self.header(SPEC_VERSION_HEADER, &sv.to_string());
Ok(self)
}
fn set_attribute(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
let key = &header_prefix(name);
self = self.header(key, &value.to_string());
Ok(self)
}
fn set_extension(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
let key = &header_prefix(name);
self = self.header(key, &value.to_string());
Ok(self)
}
fn end_with_data(self, bytes: Vec<u8>) -> Result<http::request::Request<Option<T>>> {
let body = T::try_from(bytes).unwrap();
self.body(Some(body)).map_err(|e| Error::Other {
source: Box::new(e),
})
}
fn end(self) -> Result<http::request::Request<Option<T>>> {
self.body(None).map_err(|e| Error::Other {
source: Box::new(e),
})
}
}
impl<T> TryFrom<Event> for Request<Option<T>>
where
T: TryFrom<Vec<u8>>,
<T as TryFrom<Vec<u8>>>::Error: Debug,
{
type Error = crate::message::Error;
fn try_from(event: Event) -> Result<Self> {
BinaryDeserializer::deserialize_binary(event, http::request::Builder::new())
}
}
#[cfg(test)]
mod tests {
use crate::test::fixtures;
use bytes::Bytes;
use http::Request;
use std::convert::TryFrom;
#[test]
fn test_event_to_http_request() {
let event = fixtures::v10::minimal_string_extension();
let request: Request<Option<Vec<u8>>> = Request::try_from(event).unwrap();
assert_eq!(request.headers()["ce-id"], "0001");
assert_eq!(request.headers()["ce-type"], "test_event.test_application");
}
#[test]
fn test_event_to_bytes_body() {
let event = fixtures::v10::full_binary_json_data_string_extension();
let request: Request<Option<Vec<u8>>> = Request::try_from(event).unwrap();
assert_eq!(request.headers()["ce-id"], "0001");
assert_eq!(request.headers()["ce-type"], "test_event.test_application");
assert_eq!(
request.body().as_ref().unwrap(),
&Bytes::from(fixtures::json_data().to_string())
);
}
}

View File

@ -5,6 +5,7 @@ pub mod actix;
#[cfg(feature = "axum")]
pub mod axum;
#[cfg(any(
feature = "http-binding",
feature = "actix",
feature = "warp",
feature = "reqwest",

View File

@ -268,7 +268,7 @@ pub(crate) fn default_hostname() -> Url {
.unwrap()
}
#[cfg(target_arch = "wasm32")]
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub(crate) fn default_hostname() -> Url {
use std::str::FromStr;
@ -281,3 +281,10 @@ pub(crate) fn default_hostname() -> Url {
)
.unwrap()
}
#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
pub(crate) fn default_hostname() -> Url {
use std::str::FromStr;
Url::from_str("http://localhost").unwrap()
}