Upgrade dependencies, including http and hyper, where possible. (#233)

* Upgrade axum.
Breaks docs.

Signed-off-by: Omar Zabala-Ferrera <73452461+ozabalaferrera@users.noreply.github.com>

* Upgrade several dependencies.
delegate-attr, base64, snafu, bitflags, hostname, and serde_yaml.

Signed-off-by: Omar Zabala-Ferrera <73452461+ozabalaferrera@users.noreply.github.com>

* Change target wasm32-wasi to wasm32-wasip1.

Signed-off-by: Omar Zabala-Ferrera <73452461+ozabalaferrera@users.noreply.github.com>

---------

Signed-off-by: Omar Zabala-Ferrera <73452461+ozabalaferrera@users.noreply.github.com>
This commit is contained in:
Omar Zabala-Ferrera 2024-12-02 11:45:10 -05:00 committed by GitHub
parent 9b38aead8d
commit 09661ddaf7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
47 changed files with 636 additions and 169 deletions

View File

@ -22,7 +22,7 @@ jobs:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- wasm32-unknown-unknown
- wasm32-wasi
- wasm32-wasip1
steps:
- uses: actions/checkout@v2
@ -104,14 +104,14 @@ jobs:
with:
command: build
toolchain: ${{ matrix.toolchain }}
args: --target ${{ matrix.target }} --features "http-binding hyper hyper_wasi"
args: --target ${{ matrix.target }} --features "http-0-2-binding hyper-0-14 hyper_wasi"
- uses: actions-rs/cargo@v1
name: "Test"
if: matrix.target == 'wasm32-wasi'
with:
command: test
toolchain: ${{ matrix.toolchain }}
args: --target ${{ matrix.target }} --features "http-binding hyper hyper_wasi"
args: --target ${{ matrix.target }} --features "http-0-2-binding hyper-0-14 hyper_wasi"
env:
CARGO_TARGET_WASM32_WASI_RUNNER: wasmedge
# Build examples

View File

@ -1,6 +1,6 @@
[package]
name = "cloudevents-sdk"
version = "0.7.0"
version = "0.8.0"
authors = ["Francesco Guardiani <francescoguard@gmail.com>"]
license-file = "LICENSE"
edition = "2018"
@ -23,57 +23,60 @@ name = "cloudevents"
[features]
http-binding = ["async-trait", "bytes", "futures", "http"]
actix = ["actix-web", "actix-http", "async-trait", "bytes", "futures", "http"]
http-0-2-binding = ["async-trait", "bytes", "futures", "http-0-2"]
actix = ["actix-web", "actix-http", "async-trait", "bytes", "futures", "http-0-2"]
reqwest = ["reqwest-lib", "async-trait", "bytes", "http", "uuid/js"]
rdkafka = ["rdkafka-lib", "bytes", "futures"]
warp = ["warp-lib", "bytes", "http", "hyper"]
axum = ["bytes", "http", "hyper", "axum-lib", "http-body", "async-trait"]
poem = ["bytes", "http", "poem-lib", "hyper", "async-trait"]
warp = ["warp-lib", "bytes", "http-0-2", "http-body-util", "hyper-0-14"]
axum = ["bytes", "http", "hyper", "axum-lib", "http-body-util", "async-trait"]
poem = ["bytes", "http", "poem-lib", "hyper", "async-trait", "http-body-util", "futures"]
nats = ["nats-lib"]
[dependencies]
serde = { version = "^1.0", features = ["derive"] }
serde_json = "^1.0"
chrono = { version = "^0.4", features = ["serde"] }
delegate-attr = "^0.2"
base64 = "^0.12"
url = { version = "^2.1", features = ["serde"] }
snafu = "^0.6"
bitflags = "^1.2"
delegate-attr = "^0.3"
base64 = "^0.22"
url = { version = "^2.5", features = ["serde"] }
snafu = "^0.8"
bitflags = "^2.6"
uuid = { version = "1", features = ["v4"] }
# runtime optional deps
actix-web = { version = "4", optional = true }
actix-http = { version = "3", optional = true }
reqwest-lib = { version = "^0.11", default-features = false, features = ["rustls-tls"], optional = true, package = "reqwest" }
reqwest-lib = { version = "^0.12", default-features = false, features = ["rustls-tls"], optional = true, package = "reqwest" }
rdkafka-lib = { version = "^0.36", features = ["cmake-build"], optional = true, package = "rdkafka" }
warp-lib = { version = "^0.3", optional = true, package = "warp" }
async-trait = { version = "^0.1.33", optional = true }
async-trait = { version = "^0.1", optional = true }
bytes = { version = "^1.0", optional = true }
futures = { version = "^0.3", optional = true }
http = { version = "0.2", optional = true }
axum-lib = { version = "^0.6", optional = true, package="axum"}
http-body = { version = "^0.4", optional = true }
poem-lib = { version = "=1.2.34", optional = true, package = "poem" }
nats-lib = { version = "0.21.0", optional = true, package = "nats" }
futures = { version = "^0.3", optional = true, features = ["compat"]}
http = { version = "1.1", optional = true}
http-0-2 = { version = "0.2", optional = true, package = "http"}
axum-lib = { version = "^0.7", optional = true, package="axum"}
http-body-util = {version = "^0.1", optional = true}
poem-lib = { version = "^3.1", optional = true, package = "poem" }
nats-lib = { version = "0.25.0", optional = true, package = "nats" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
hostname = "^0.3"
hostname = "^0.4"
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
web-sys = { version = "^0.3", features = ["Window", "Location"] }
[target.'cfg(not(target_os = "wasi"))'.dependencies]
hyper = { version = "^0.14", optional = true }
hyper = { version = "^1.4", optional = true, package="hyper" }
hyper-0-14 = { version = "^0.14", optional = true, package = "hyper"}
[target.'cfg(all(target_arch = "wasm32", target_os = "wasi"))'.dependencies]
hyper_wasi = { version = "0.15", features = ["full"], optional = true }
[dev-dependencies]
rstest = "0.6"
rstest = "0.23"
claims = "0.7.1"
version-sync = "0.9.2"
serde_yaml = "0.8"
serde_yaml = "^0.9"
rmp-serde = "1"
# runtime dev-deps
@ -81,14 +84,14 @@ rmp-serde = "1"
url = { version = "^2.1", features = ["serde"] }
serde_json = { version = "^1.0" }
chrono = { version = "^0.4", features = ["serde"] }
mockito = "0.25.1"
mockito = "0.31.1"
mime = "0.3"
[target.'cfg(not(target_os = "wasi"))'.dev-dependencies]
actix-rt = { version = "^2" }
tokio = { version = "^1.0", features = ["full"] }
tower = { version = "0.4", features = ["util"] }
tower = { version = "0.5", features = ["util"] }
[target.'cfg(all(target_arch = "wasm32", target_os = "wasi"))'.dev-dependencies]
tokio_wasi = { version = "1", features = [

View File

@ -42,7 +42,7 @@ enabling your Protocol Binding of choice:
```toml
[dependencies]
cloudevents-sdk = { version = "0.7.0" }
cloudevents-sdk = { version = "0.8.0" }
```
Now you can start creating events:

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies]
cloudevents-sdk = { path = "../..", features = ["actix"] }
actix-web = "4"
actix-cors = "0.6.0-beta.8"
actix-cors = "^0.7"
serde_json = "^1.0"
url = { version = "^2.1" }
env_logger = "0.7.1"
env_logger = "^0.11"

View File

@ -6,16 +6,16 @@ edition = "2021"
[dependencies]
cloudevents-sdk = { path = "../..", features = ["axum"] }
axum = "^0.6"
http = "^0.2"
axum = "^0.7"
http = "^1.1"
tokio = { version = "^1", features = ["full"] }
tracing = "^0.1"
tracing-subscriber = "^0.2"
tower-http = { version = "^0.1", features = ["trace"] }
tracing-subscriber = "^0.3"
tower-http = { version = "^0.5", features = ["trace"] }
[dev-dependencies]
tower = { version = "^0.4", features = ["util"] }
serde = { version = "^1.0", features = ["derive"] }
serde_json = "^1.0"
chrono = { version = "^0.4", features = ["serde"] }
hyper = { version = "^0.14" }
hyper = { version = "^1.4" }

View File

@ -4,7 +4,6 @@ use axum::{
};
use cloudevents::Event;
use http::StatusCode;
use std::net::SocketAddr;
use tower_http::trace::TraceLayer;
fn echo_app() -> Router {
@ -27,12 +26,8 @@ async fn main() {
}
tracing_subscriber::fmt::init();
let service = echo_app();
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
tracing::debug!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(service.into_make_service())
.await
.unwrap();
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
axum::serve(listener, service).await.unwrap();
}
#[cfg(test)]

View File

@ -9,4 +9,4 @@ edition = "2021"
[dependencies]
cloudevents-sdk = { path = "../..", features = ["nats"] }
serde_json = "^1.0"
nats = "0.21.0"
nats = "^0.25"

View File

@ -7,8 +7,8 @@ edition = "2021"
cloudevents-sdk = { path = "../..", features = ["poem"] }
tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] }
tracing = "0.1"
poem = { version = "1" }
tracing-subscriber = "0.2"
poem = { version = "^3.0" }
tracing-subscriber = "0.3"
serde_json = "1.0"
[dev-dependencies]

View File

@ -10,7 +10,7 @@ edition = "2018"
crate-type = ["cdylib"]
[dependencies]
reqwest = "^0.11"
reqwest = "^0.12"
uuid = "1"
cloudevents-sdk = { path = "../..", features = ["reqwest"] }
url = { version = "^2.1" }

View File

@ -5,11 +5,11 @@ edition = "2021"
[dependencies]
anyhow = "1.0"
cloudevents-sdk = { path = "../..", features = ["http-binding", "hyper_wasi", "hyper" ] }
cloudevents-sdk = { path = "../..", features = ["http-0-2-binding", "hyper_wasi", "hyper-0-14" ] }
hyper_wasi = { version = "0.15", features = ["full"] }
log = "0.4.21"
tokio_wasi = { version = "1", features = ["io-util", "fs", "net", "time", "rt", "macros"] }
serde_json = " 1.0.116"
serde_json = "^1.0"
[dev-dependencies]
bytes = "1.6.0"

View File

@ -1,5 +1,5 @@
use cloudevents::binding::http::builder::adapter::to_response;
use cloudevents::binding::http::to_event;
use cloudevents::binding::http_0_2::builder::adapter::to_response;
use cloudevents::binding::http_0_2::to_event;
use hyper::service::{make_service_fn, service_fn};
use hyper::Server;
@ -23,7 +23,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
}
Ok(())
}
async fn handle_request(req: Request<Body>) -> Result<Response<Body>, anyhow::Error> {
async fn handle_request(
req: Request<Body>,
) -> Result<Response<Body>, anyhow::Error> {
match (req.method(), req.uri().path()) {
(&Method::POST, "/") => {
let headers = req.headers().clone();
@ -34,7 +36,9 @@ async fn handle_request(req: Request<Body>) -> Result<Response<Body>, anyhow::Er
to_response(_respevt).map_err(|err| err.into())
}
(&Method::GET, "/health/readiness") => Ok(Response::new(Body::from(""))),
(&Method::GET, "/health/readiness") => {
Ok(Response::new(Body::from("")))
}
(&Method::GET, "/health/liveness") => Ok(Response::new(Body::from(""))),
_ => {
let mut not_found = Response::default();

View File

@ -1,4 +1,4 @@
use crate::binding::http::{to_event, Headers};
use crate::binding::http_0_2::{to_event, Headers};
use crate::Event;
use actix_web::dev::Payload;
use actix_web::web::BytesMut;
@ -6,6 +6,7 @@ use actix_web::{web, HttpRequest};
use async_trait::async_trait;
use futures::{future::LocalBoxFuture, FutureExt, StreamExt};
use http::header::{AsHeaderName, HeaderName, HeaderValue};
use http_0_2 as http;
/// Implement Headers for the actix HeaderMap
impl<'a> Headers<'a> for actix_http::header::HeaderMap {

View File

@ -1,8 +1,9 @@
use crate::binding::http::{Builder, Serializer};
use crate::binding::http_0_2::{Builder, Serializer};
use crate::message::{BinaryDeserializer, Result};
use crate::Event;
use actix_web::http::StatusCode;
use actix_web::{HttpRequest, HttpResponse, HttpResponseBuilder};
use http_0_2 as http;
impl Builder<HttpResponse> for HttpResponseBuilder {
fn header(&mut self, key: &str, value: http::header::HeaderValue) {

View File

@ -1,45 +1,46 @@
use axum_lib as axum;
use async_trait::async_trait;
use axum::extract::FromRequest;
use axum::http::Request;
use http::request::Parts;
use axum::body::Bytes;
use axum::extract::{FromRequest, Request};
use axum::response::Response;
use axum_lib as axum;
use http;
use http::StatusCode;
use http_body::Body;
use hyper::body;
use crate::binding::http::to_event;
use crate::event::Event;
type BoxError = Box<dyn std::error::Error + Send + Sync>;
#[async_trait]
impl<S, B> FromRequest<S, B> for Event
impl<S> FromRequest<S> for Event
where
B: Body + Send + 'static,
B::Data: Send,
B::Error: Into<BoxError>,
Bytes: FromRequest<S>,
S: Send + Sync,
{
type Rejection = (StatusCode, String);
type Rejection = Response;
async fn from_request(req: Request<B>, _state: &S) -> Result<Self, Self::Rejection> {
let (Parts { headers, .. }, req_body) = req.into_parts();
let buf = body::to_bytes(req_body)
.await
.map_err(|e| (StatusCode::BAD_REQUEST, format!("{}", e.into())))?
.to_vec();
async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
let (parts, body) = req.into_parts();
to_event(&headers, buf).map_err(|e| (StatusCode::BAD_REQUEST, format!("{}", e)))
let body = axum::body::to_bytes(body, usize::MAX).await.map_err(|e| {
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::from(e.to_string()))
.unwrap()
})?;
to_event(&parts.headers, body.to_vec()).map_err(|e| {
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(axum::body::Body::from(e.to_string()))
.unwrap()
})
}
}
#[cfg(test)]
mod tests {
use axum_lib as axum;
use super::*;
use axum::body::Body;
use axum::extract::FromRequest;
use axum::http::{self, Request, StatusCode};
use crate::test::fixtures;
@ -80,7 +81,7 @@ mod tests {
assert!(result.is_err());
let rejection = result.unwrap_err();
let reason = rejection.0;
let reason = rejection.status();
assert_eq!(reason, StatusCode::BAD_REQUEST)
}

View File

@ -155,7 +155,7 @@ mod tests {
);
let (_, body) = resp.into_parts();
let body = hyper::body::to_bytes(body).await.unwrap();
let body = axum::body::to_bytes(body, usize::MAX).await.unwrap();
assert_eq!(j.to_string().as_bytes(), body);
}

View File

@ -1,27 +1,21 @@
use axum_lib as axum;
use axum::{
body::{boxed, BoxBody},
http::Response,
response::IntoResponse,
};
use http::{header, StatusCode};
use hyper::body::Body;
use crate::binding::http::builder::adapter::to_response;
use crate::event::Event;
use axum::{body::Body, http::Response, response::IntoResponse};
use axum_lib as axum;
use http;
use http::{header, StatusCode};
impl IntoResponse for Event {
fn into_response(self) -> Response<BoxBody> {
fn into_response(self) -> Response<Body> {
match to_response(self) {
Ok(resp) => {
let (parts, body) = resp.into_parts();
Response::from_parts(parts, boxed(body))
Response::from_parts(parts, Body::new(body))
}
Err(err) => Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(header::CONTENT_TYPE, "text/plain")
.body(boxed(Body::from(err.to_string())))
.body(Body::from(err.to_string()))
.unwrap(),
}
}
@ -105,7 +99,7 @@ mod tests {
);
let (_, body) = resp.into_parts();
let body = hyper::body::to_bytes(body).await.unwrap();
let body = axum::body::to_bytes(body, usize::MAX).await.unwrap();
assert_eq!(fixtures::json_data_binary(), body);
}

View File

@ -1,33 +1,38 @@
use bytes::Bytes;
use http::Response;
use hyper::body::Body;
use http_body_util::Full;
use std::cell::Cell;
use crate::binding::http::{Builder, Serializer};
use crate::message::{BinaryDeserializer, Error, Result};
use crate::Event;
use std::convert::Infallible;
type BoxBody = http_body_util::combinators::UnsyncBoxBody<Bytes, Infallible>;
struct Adapter {
builder: Cell<http::response::Builder>,
}
impl Builder<Response<Body>> for Adapter {
impl Builder<Response<BoxBody>> for Adapter {
fn header(&mut self, key: &str, value: http::header::HeaderValue) {
self.builder.set(self.builder.take().header(key, value));
}
fn body(&mut self, bytes: Vec<u8>) -> Result<Response<Body>> {
fn body(&mut self, bytes: Vec<u8>) -> Result<Response<BoxBody>> {
self.builder
.take()
.body(Body::from(bytes))
.body(BoxBody::new(Full::from(bytes)))
.map_err(|e| crate::message::Error::Other {
source: Box::new(e),
})
}
fn finish(&mut self) -> Result<Response<Body>> {
fn finish(&mut self) -> Result<Response<BoxBody>> {
self.body(Vec::new())
}
}
pub fn to_response(event: Event) -> std::result::Result<Response<Body>, Error> {
pub fn to_response(event: Event) -> std::result::Result<Response<BoxBody>, Error> {
BinaryDeserializer::deserialize_binary(
event,
Serializer::new(Adapter {

View File

@ -3,6 +3,8 @@ pub mod adapter;
use crate::message::Result;
use http;
pub trait Builder<R> {
fn header(&mut self, key: &str, value: http::header::HeaderValue);
fn body(&mut self, bytes: Vec<u8>) -> Result<R>;

View File

@ -8,6 +8,8 @@ use crate::{
Result, StructuredDeserializer, StructuredSerializer,
},
};
use http;
use std::convert::TryFrom;
pub struct Deserializer<'a, T: Headers<'a>> {

View File

@ -1,5 +1,7 @@
use http::header::{AsHeaderName, HeaderMap, HeaderName, HeaderValue};
use http;
/// Any http library should be able to use the
/// [`to_event`](super::to_event) function with an implementation of
/// this trait.

View File

@ -13,6 +13,8 @@ mod serializer;
pub use builder::Builder;
use core::convert::TryFrom;
use http::Response;
use http;
pub use serializer::Serializer;
use std::convert::TryInto;
use std::fmt::Debug;
@ -53,6 +55,8 @@ mod tests {
use core::convert::TryFrom;
use http::Response;
use http;
#[test]
fn test_response_to_event() {
let event = fixtures::v10::minimal_string_extension();

View File

@ -12,6 +12,8 @@ use crate::message::{
};
use crate::Event;
use http::Request;
use http;
use std::convert::TryFrom;
use std::fmt::Debug;
@ -131,6 +133,8 @@ mod tests {
use crate::test::fixtures;
use bytes::Bytes;
use http::Request;
use http;
use std::convert::TryFrom;
#[test]

View File

@ -0,0 +1,44 @@
use http::Response;
use http_0_2 as http;
use hyper::body::Body;
use std::cell::Cell;
#[cfg(not(target_os = "wasi"))]
use hyper_0_14 as hyper;
#[cfg(target_os = "wasi")]
use hyper;
use crate::binding::http_0_2::{Builder, Serializer};
use crate::message::{BinaryDeserializer, Error, Result};
use crate::Event;
struct Adapter {
builder: Cell<http::response::Builder>,
}
impl Builder<Response<Body>> for Adapter {
fn header(&mut self, key: &str, value: http::header::HeaderValue) {
self.builder.set(self.builder.take().header(key, value));
}
fn body(&mut self, bytes: Vec<u8>) -> Result<Response<Body>> {
self.builder
.take()
.body(Body::from(bytes))
.map_err(|e| crate::message::Error::Other {
source: Box::new(e),
})
}
fn finish(&mut self) -> Result<Response<Body>> {
self.body(Vec::new())
}
}
pub fn to_response(event: Event) -> std::result::Result<Response<Body>, Error> {
BinaryDeserializer::deserialize_binary(
event,
Serializer::new(Adapter {
builder: Cell::new(http::Response::builder()),
}),
)
}

View File

@ -0,0 +1,11 @@
#[cfg(feature = "hyper-0-14")]
pub mod adapter;
use crate::message::Result;
use http_0_2 as http;
pub trait Builder<R> {
fn header(&mut self, key: &str, value: http::header::HeaderValue);
fn body(&mut self, bytes: Vec<u8>) -> Result<R>;
fn finish(&mut self) -> Result<R>;
}

View File

@ -0,0 +1,101 @@
use super::{Headers, SPEC_VERSION_HEADER};
use crate::{
binding::CLOUDEVENTS_JSON_HEADER,
event::SpecVersion,
header_value_to_str, message,
message::{
BinaryDeserializer, BinarySerializer, Encoding, MessageAttributeValue, MessageDeserializer,
Result, StructuredDeserializer, StructuredSerializer,
},
};
use http_0_2 as http;
use std::convert::TryFrom;
pub struct Deserializer<'a, T: Headers<'a>> {
headers: &'a T,
body: Vec<u8>,
}
impl<'a, T: Headers<'a>> Deserializer<'a, T> {
pub fn new(headers: &'a T, body: Vec<u8>) -> Deserializer<'a, T> {
Deserializer { headers, body }
}
}
impl<'a, T: Headers<'a>> BinaryDeserializer for Deserializer<'a, T> {
fn deserialize_binary<R: Sized, V: BinarySerializer<R>>(self, mut visitor: V) -> Result<R> {
if self.encoding() != Encoding::BINARY {
return Err(message::Error::WrongEncoding {});
}
let spec_version = SpecVersion::try_from(
self.headers
.get(SPEC_VERSION_HEADER)
.map(|a| header_value_to_str!(a))
.unwrap()?,
)?;
let attributes = spec_version.attribute_names();
visitor = visitor.set_spec_version(spec_version)?;
for (hn, hv) in self.headers.iter().filter(|(hn, _)| {
let key = hn.as_str();
SPEC_VERSION_HEADER.ne(key) && key.starts_with("ce-")
}) {
let name = &hn.as_str()["ce-".len()..];
if attributes.contains(&name) {
visitor = visitor.set_attribute(
name,
MessageAttributeValue::String(String::from(header_value_to_str!(hv)?)),
)?
} else {
visitor = visitor.set_extension(
name,
MessageAttributeValue::String(String::from(header_value_to_str!(hv)?)),
)?
}
}
if let Some(hv) = self.headers.get(http::header::CONTENT_TYPE) {
visitor = visitor.set_attribute(
"datacontenttype",
MessageAttributeValue::String(String::from(header_value_to_str!(hv)?)),
)?
}
if !self.body.is_empty() {
visitor.end_with_data(self.body)
} else {
visitor.end()
}
}
}
impl<'a, T: Headers<'a>> StructuredDeserializer for Deserializer<'a, T> {
fn deserialize_structured<R: Sized, V: StructuredSerializer<R>>(self, visitor: V) -> Result<R> {
if self.encoding() != Encoding::STRUCTURED {
return Err(message::Error::WrongEncoding {});
}
visitor.set_structured_event(self.body)
}
}
impl<'a, T: Headers<'a>> MessageDeserializer for Deserializer<'a, T> {
fn encoding(&self) -> Encoding {
if self
.headers
.get(http::header::CONTENT_TYPE)
.and_then(|v| v.to_str().ok())
.filter(|&v| v.starts_with(CLOUDEVENTS_JSON_HEADER))
.is_some()
{
Encoding::STRUCTURED
} else if self.headers.get(SPEC_VERSION_HEADER).is_some() {
Encoding::BINARY
} else {
Encoding::UNKNOWN
}
}
}

View File

@ -0,0 +1,22 @@
use http::header::{AsHeaderName, HeaderMap, HeaderName, HeaderValue};
use http_0_2 as http;
/// Any http library should be able to use the
/// [`to_event`](super::to_event) function with an implementation of
/// this trait.
pub trait Headers<'a> {
type Iterator: Iterator<Item = (&'a HeaderName, &'a HeaderValue)>;
fn get<K: AsHeaderName>(&self, name: K) -> Option<&HeaderValue>;
fn iter(&'a self) -> Self::Iterator;
}
/// Implemention for the HeaderMap used by warp/reqwest
impl<'a> Headers<'a> for HeaderMap<HeaderValue> {
type Iterator = http::header::Iter<'a, HeaderValue>;
fn get<K: AsHeaderName>(&self, name: K) -> Option<&HeaderValue> {
self.get(name)
}
fn iter(&'a self) -> Self::Iterator {
self.iter()
}
}

View File

@ -0,0 +1,73 @@
pub mod builder;
pub mod deserializer;
mod headers;
use crate::{
message::{Error, MessageDeserializer},
Event,
};
use deserializer::Deserializer;
pub use headers::Headers;
mod serializer;
pub use builder::Builder;
use core::convert::TryFrom;
use http::Response;
use http_0_2 as http;
pub use serializer::Serializer;
use std::convert::TryInto;
use std::fmt::Debug;
pub static SPEC_VERSION_HEADER: &str = "ce-specversion";
/// Turn a pile of HTTP headers and a body into a CloudEvent
pub fn to_event<'a, T: Headers<'a>>(
headers: &'a T,
body: Vec<u8>,
) -> std::result::Result<Event, Error> {
MessageDeserializer::into_event(Deserializer::new(headers, body))
}
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;
use http_0_2 as http;
#[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

@ -0,0 +1,159 @@
use std::{cell::RefCell, rc::Rc};
use crate::binding::http_0_2::builder::Builder;
use crate::binding::{
http_0_2::{header_prefix, SPEC_VERSION_HEADER},
CLOUDEVENTS_JSON_HEADER,
};
use crate::event::SpecVersion;
use crate::message::BinaryDeserializer;
use crate::message::{
BinarySerializer, Error, MessageAttributeValue, Result, StructuredSerializer,
};
use crate::Event;
use http::Request;
use http_0_2 as http;
use std::convert::TryFrom;
use std::fmt::Debug;
macro_rules! str_to_header_value {
($header_value:expr) => {
http::header::HeaderValue::from_str(&$header_value.to_string()).map_err(|e| {
crate::message::Error::Other {
source: Box::new(e),
}
})
};
}
pub struct Serializer<T> {
builder: Rc<RefCell<dyn Builder<T>>>,
}
impl<T> Serializer<T> {
pub fn new<B: Builder<T> + 'static>(delegate: B) -> Serializer<T> {
let builder = Rc::new(RefCell::new(delegate));
Serializer { builder }
}
}
impl<T> BinarySerializer<T> for Serializer<T> {
fn set_spec_version(self, spec_version: SpecVersion) -> Result<Self> {
self.builder
.borrow_mut()
.header(SPEC_VERSION_HEADER, str_to_header_value!(spec_version)?);
Ok(self)
}
fn set_attribute(self, name: &str, value: MessageAttributeValue) -> Result<Self> {
self.builder
.borrow_mut()
.header(&header_prefix(name), str_to_header_value!(value)?);
Ok(self)
}
fn set_extension(self, name: &str, value: MessageAttributeValue) -> Result<Self> {
self.builder
.borrow_mut()
.header(&header_prefix(name), str_to_header_value!(value)?);
Ok(self)
}
fn end_with_data(self, bytes: Vec<u8>) -> Result<T> {
self.builder.borrow_mut().body(bytes)
}
fn end(self) -> Result<T> {
self.builder.borrow_mut().finish()
}
}
impl<T> StructuredSerializer<T> for Serializer<T> {
fn set_structured_event(self, bytes: Vec<u8>) -> Result<T> {
let mut builder = self.builder.borrow_mut();
builder.header(
http::header::CONTENT_TYPE.as_str(),
http::HeaderValue::from_static(CLOUDEVENTS_JSON_HEADER),
);
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 http_0_2 as http;
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

@ -11,8 +11,6 @@ pub mod axum;
docsrs,
doc(cfg(any(
feature = "http-binding",
feature = "actix",
feature = "warp",
feature = "reqwest",
feature = "axum",
feature = "poem"
@ -20,13 +18,19 @@ pub mod axum;
)]
#[cfg(any(
feature = "http-binding",
feature = "actix",
feature = "warp",
feature = "reqwest",
feature = "axum",
feature = "poem"
))]
pub mod http;
#[cfg_attr(
docsrs,
doc(cfg(any(feature = "http-0-2-binding", feature = "actix", feature = "warp",)))
)]
#[cfg(any(feature = "http-0-2-binding", feature = "actix", feature = "warp",))]
pub mod http_0_2;
#[cfg_attr(docsrs, doc(cfg(feature = "nats")))]
#[cfg(feature = "nats")]
pub mod nats;

View File

@ -1,18 +1,16 @@
use async_trait::async_trait;
use crate::binding::http::to_event;
use crate::Event;
use poem_lib::error::ResponseError;
use poem_lib::http::StatusCode;
use poem_lib::{FromRequest, Request, RequestBody, Result};
use crate::binding::http::to_event;
use crate::Event;
impl ResponseError for crate::message::Error {
fn status(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
}
#[async_trait]
impl<'a> FromRequest<'a> for Event {
async fn from_request(req: &'a Request, body: &mut RequestBody) -> Result<Self> {
Ok(to_event(req.headers(), body.take()?.into_vec().await?)?)
@ -57,7 +55,7 @@ mod tests {
let (req, mut body) = req.split();
let resp = Event::from_request(&req, &mut body).await.err().unwrap();
assert_eq!(resp.as_response().status(), StatusCode::BAD_REQUEST);
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
assert_eq!(resp.to_string(), "Invalid specversion BAD SPECIFICATION");
}

View File

@ -1,14 +1,33 @@
use crate::{AttributesReader, Data, Event};
use bytes::Bytes;
use poem_lib::http::StatusCode;
use poem_lib::{IntoResponse, Response};
use crate::binding::http::builder::adapter::to_response;
use crate::Event;
impl IntoResponse for Event {
fn into_response(self) -> Response {
match to_response(self) {
Ok(resp) => resp.into(),
Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into(),
let mut builder = Response::builder().status(StatusCode::OK);
if let Some(dct) = self.datacontenttype() {
builder = builder.content_type(dct);
}
for (key, value) in self.iter() {
builder = builder.header(format!("ce-{key}").as_str(), value.to_string());
}
match self.data {
Some(data) => match data {
Data::Binary(v) => builder.body(Bytes::copy_from_slice(v.as_slice())),
Data::String(s) => builder.body(s.clone()),
Data::Json(j) => match serde_json::to_string(&j) {
Ok(s) => builder.body(s),
Err(e) => Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(e.to_string()),
},
},
None => builder.finish(),
}
}
}

View File

@ -114,7 +114,7 @@ mod private {
#[cfg(test)]
mod tests {
use super::*;
use mockito::{mock, Matcher};
use mockito::Matcher;
use reqwest_lib as reqwest;
use crate::message::StructuredDeserializer;
@ -123,7 +123,7 @@ mod tests {
#[tokio::test]
async fn test_request() {
let url = mockito::server_url();
let m = mock("POST", "/")
let m = mockito::mock("POST", "/")
.match_header("ce-specversion", "1.0")
.match_header("ce-id", "0001")
.match_header("ce-type", "test_event.test_application")
@ -149,7 +149,7 @@ mod tests {
#[tokio::test]
async fn test_request_with_full_data() {
let url = mockito::server_url();
let m = mock("POST", "/")
let m = mockito::mock("POST", "/")
.match_header("ce-specversion", "1.0")
.match_header("ce-id", "0001")
.with_header("ce-type", "test_event.test_application")
@ -183,7 +183,7 @@ mod tests {
let input = fixtures::v10::full_json_data_string_extension();
let url = mockito::server_url();
let m = mock("POST", "/")
let m = mockito::mock("POST", "/")
.match_header("content-type", "application/cloudevents+json")
.match_body(Matcher::Exact(serde_json::to_string(&input).unwrap()))
.create();
@ -204,8 +204,9 @@ mod tests {
#[tokio::test]
async fn test_batched_request() {
let input = vec![fixtures::v10::full_json_data_string_extension()];
let url = mockito::server_url();
let m = mock("POST", "/")
let m = mockito::mock("POST", "/")
.match_header("content-type", "application/cloudevents-batch+json")
.match_body(Matcher::Exact(serde_json::to_string(&input).unwrap()))
.create();

View File

@ -4,6 +4,7 @@ use crate::binding;
use crate::message::{Error, Result};
use crate::Event;
use async_trait::async_trait;
use http;
use http::header;
use reqwest::Response;
@ -68,7 +69,6 @@ mod private {
#[cfg(test)]
mod tests {
use super::*;
use mockito::mock;
use reqwest_lib as reqwest;
use std::vec;
@ -77,7 +77,7 @@ mod tests {
#[tokio::test]
async fn test_response() {
let url = mockito::server_url();
let _m = mock("GET", "/")
let _m = mockito::mock("GET", "/")
.with_status(200)
.with_header("ce-specversion", "1.0")
.with_header("ce-id", "0001")
@ -104,7 +104,7 @@ mod tests {
#[tokio::test]
async fn test_response_with_full_data() {
let url = mockito::server_url();
let _m = mock("GET", "/")
let _m = mockito::mock("GET", "/")
.with_status(200)
.with_header("ce-specversion", "1.0")
.with_header("ce-id", "0001")
@ -139,7 +139,7 @@ mod tests {
let expected = fixtures::v10::full_json_data_string_extension();
let url = mockito::server_url();
let _m = mock("GET", "/")
let _m = mockito::mock("GET", "/")
.with_status(200)
.with_header(
"content-type",
@ -166,7 +166,7 @@ mod tests {
let expected = vec![fixtures::v10::full_json_data_string_extension()];
let url = mockito::server_url();
let _m = mock("GET", "/")
let _m = mockito::mock("GET", "/")
.with_status(200)
.with_header(
"content-type",

View File

@ -1,6 +1,6 @@
use warp_lib as warp;
use crate::binding::http;
use crate::binding::http_0_2 as http;
use crate::Event;
use warp::http::HeaderMap;

View File

@ -24,6 +24,7 @@
//!
//! ```
//! # use warp_lib as warp;
//! # use http_0_2 as http;
//! use cloudevents::{Event, EventBuilder, EventBuilderV10};
//! use http::StatusCode;
//! use serde_json::json;

View File

@ -1,11 +1,12 @@
use warp_lib as warp;
use crate::binding::http::builder::adapter::to_response;
use crate::binding::http_0_2::builder::adapter::to_response;
use crate::Event;
use http::StatusCode;
use http_0_2 as http;
use hyper_0_14 as hyper;
use warp::reply::Response;
///
/// # Serializes [`crate::Event`] as a http response
///
@ -32,6 +33,7 @@ pub fn from_event(event: Event) -> Response {
#[cfg(test)]
mod tests {
use crate::test::fixtures;
use hyper_0_14 as hyper;
#[test]
fn test_response() {

View File

@ -3,6 +3,7 @@ use super::{
EventFormatSerializerV03, EventFormatSerializerV10,
};
use crate::event::{AttributesReader, ExtensionValue};
use base64::prelude::*;
use serde::de::{Error, IntoDeserializer};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::{Map, Value};
@ -58,7 +59,9 @@ pub fn parse_data_string<E: serde::de::Error>(v: Value) -> Result<String, E> {
pub fn parse_data_base64<E: serde::de::Error>(v: Value) -> Result<Vec<u8>, E> {
parse_field!(v, String, E).and_then(|s| {
base64::decode(s).map_err(|e| E::custom(format_args!("decode error `{}`", e)))
BASE64_STANDARD
.decode(s)
.map_err(|e| E::custom(format_args!("decode error `{}`", e)))
})
}

View File

@ -84,26 +84,29 @@ pub struct Event {
#[delegate(self.attributes)]
impl AttributesReader for Event {
fn id(&self) -> &str;
fn source(&self) -> &UriReference;
fn specversion(&self) -> SpecVersion;
fn ty(&self) -> &str;
fn datacontenttype(&self) -> Option<&str>;
fn dataschema(&self) -> Option<&Url>;
fn subject(&self) -> Option<&str>;
fn time(&self) -> Option<&DateTime<Utc>>;
fn id(&self) -> &str {}
fn source(&self) -> &UriReference {}
fn specversion(&self) -> SpecVersion {}
fn ty(&self) -> &str {}
fn datacontenttype(&self) -> Option<&str> {}
fn dataschema(&self) -> Option<&Url> {}
fn subject(&self) -> Option<&str> {}
fn time(&self) -> Option<&DateTime<Utc>> {}
}
#[delegate(self.attributes)]
impl AttributesWriter for Event {
fn set_id(&mut self, id: impl Into<String>) -> String;
fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference;
fn set_type(&mut self, ty: impl Into<String>) -> String;
fn set_subject(&mut self, subject: Option<impl Into<String>>) -> Option<String>;
fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>) -> Option<DateTime<Utc>>;
fn set_datacontenttype(&mut self, datacontenttype: Option<impl Into<String>>)
-> Option<String>;
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url>;
fn set_id(&mut self, id: impl Into<String>) -> String {}
fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference {}
fn set_type(&mut self, ty: impl Into<String>) -> String {}
fn set_subject(&mut self, subject: Option<impl Into<String>>) -> Option<String> {}
fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>) -> Option<DateTime<Utc>> {}
fn set_datacontenttype(
&mut self,
datacontenttype: Option<impl Into<String>>,
) -> Option<String> {
}
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url> {}
}
impl Default for Event {

View File

@ -221,7 +221,7 @@ impl crate::event::message::AttributesDeserializer for super::Attributes {
mod tests {
use super::*;
use crate::test::fixtures;
use chrono::NaiveDateTime;
use chrono::DateTime;
#[test]
fn iter_v03_test() {
@ -243,13 +243,10 @@ mod tests {
datacontenttype: None,
schemaurl: None,
subject: None,
time: Some(DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp(61, 0),
Utc,
)),
time: DateTime::from_timestamp(61, 0),
};
let b = &mut a.into_iter();
let time = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc);
let time = DateTime::from_timestamp(61, 0).unwrap();
assert_eq!(
("specversion", AttributeValue::SpecVersion(SpecVersion::V03)),

View File

@ -4,6 +4,7 @@ use crate::event::format::{
parse_data_base64, parse_data_base64_json, parse_data_json, parse_data_string,
};
use crate::event::{Data, ExtensionValue};
use base64::prelude::*;
use chrono::{DateTime, Utc};
use serde::de::IntoDeserializer;
use serde::ser::SerializeMap;
@ -102,7 +103,7 @@ impl<S: serde::Serializer> crate::event::format::EventFormatSerializer<S, Attrib
Some(Data::Json(j)) => state.serialize_entry("data", j)?,
Some(Data::String(s)) => state.serialize_entry("data", s)?,
Some(Data::Binary(v)) => {
state.serialize_entry("data", &base64::encode(v))?;
state.serialize_entry("data", &BASE64_STANDARD.encode(v))?;
state.serialize_entry("datacontentencoding", "base64")?;
}
_ => (),

View File

@ -222,7 +222,6 @@ impl AttributesConverter for Attributes {
mod tests {
use super::*;
use crate::test::fixtures;
use chrono::NaiveDateTime;
#[test]
fn iter_v10_test() {
@ -244,13 +243,10 @@ mod tests {
datacontenttype: None,
dataschema: None,
subject: None,
time: Some(DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp(61, 0),
Utc,
)),
time: DateTime::from_timestamp(61, 0),
};
let b = &mut a.into_iter();
let time = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc);
let time = DateTime::from_timestamp(61, 0).unwrap();
assert_eq!(
("specversion", AttributeValue::SpecVersion(SpecVersion::V10)),

View File

@ -4,6 +4,7 @@ use crate::event::format::{
parse_data_base64, parse_data_base64_json, parse_data_json, parse_data_string,
};
use crate::event::{Data, ExtensionValue};
use base64::prelude::*;
use chrono::{DateTime, Utc};
use serde::de::IntoDeserializer;
use serde::ser::SerializeMap;
@ -102,7 +103,9 @@ impl<S: serde::Serializer> crate::event::format::EventFormatSerializer<S, Attrib
match data {
Some(Data::Json(j)) => state.serialize_entry("data", j)?,
Some(Data::String(s)) => state.serialize_entry("data", s)?,
Some(Data::Binary(v)) => state.serialize_entry("data_base64", &base64::encode(v))?,
Some(Data::Binary(v)) => {
state.serialize_entry("data_base64", &BASE64_STANDARD.encode(v))?
}
_ => (),
};
for (k, v) in extensions {

View File

@ -54,7 +54,7 @@
//! [Extractors]: https://actix.rs/docs/extractors/
//! [Responders]: https://actix.rs/docs/handlers/
#![doc(html_root_url = "https://docs.rs/cloudevents-sdk/0.7.0")]
#![doc(html_root_url = "https://docs.rs/cloudevents-sdk/0.8.0")]
#![deny(rustdoc::broken_intra_doc_links)]
#![cfg_attr(docsrs, feature(doc_cfg))] // Show feature gate in doc

View File

@ -1,4 +1,5 @@
use crate::event::{ExtensionValue, UriReference};
use base64::prelude::*;
use chrono::{DateTime, Utc};
use std::convert::TryInto;
use std::fmt;
@ -46,10 +47,14 @@ impl fmt::Display for MessageAttributeValue {
MessageAttributeValue::Boolean(b) => write!(f, "{}", b),
MessageAttributeValue::Integer(i) => write!(f, "{}", i),
MessageAttributeValue::String(s) => write!(f, "{}", s),
MessageAttributeValue::Binary(v) => write!(f, "{}", base64::encode(v)),
MessageAttributeValue::Binary(v) => {
write!(f, "{}", BASE64_STANDARD.encode(v))
}
MessageAttributeValue::Uri(u) => write!(f, "{}", u),
MessageAttributeValue::UriRef(u) => write!(f, "{}", u),
MessageAttributeValue::DateTime(d) => write!(f, "{}", d.to_rfc3339()),
MessageAttributeValue::DateTime(d) => {
write!(f, "{}", d.to_rfc3339())
}
}
}
}

View File

@ -45,7 +45,7 @@ pub fn subject() -> String {
}
pub fn time() -> DateTime<Utc> {
Utc.ymd(2020, 3, 16).and_hms(11, 50, 00)
Utc.with_ymd_and_hms(2020, 3, 16, 11, 50, 00).unwrap()
}
pub fn string_extension() -> (String, String) {

View File

@ -1,5 +1,6 @@
use crate::test::fixtures::*;
use crate::{Event, EventBuilder, EventBuilderV03};
use base64::prelude::*;
use serde_json::{json, Value};
use url::Url;
@ -120,7 +121,7 @@ pub fn full_json_base64_data_json() -> Value {
"datacontenttype": json_datacontenttype(),
"schemaurl": dataschema(),
"datacontentencoding": "base64",
"data": base64::encode(json_data_binary())
"data": BASE64_STANDARD.encode(json_data_binary())
})
}
@ -199,6 +200,6 @@ pub fn full_xml_base64_data_json() -> Value {
int_ext_name: int_ext_value,
"datacontenttype": xml_datacontenttype(),
"datacontentencoding": "base64",
"data": base64::encode(Vec::from(xml_data()))
"data": BASE64_STANDARD.encode(Vec::from(xml_data()))
})
}

View File

@ -1,5 +1,6 @@
use crate::test::fixtures::*;
use crate::{Event, EventBuilder, EventBuilderV10};
use base64::prelude::*;
use serde_json::{json, Value};
use url::Url;
@ -166,7 +167,7 @@ pub fn full_json_base64_data_json() -> Value {
int_ext_name: int_ext_value,
"datacontenttype": json_datacontenttype(),
"dataschema": dataschema(),
"data_base64": base64::encode(json_data_binary())
"data_base64": BASE64_STANDARD.encode(json_data_binary())
})
}
@ -175,7 +176,7 @@ pub fn full_non_json_base64_data() -> Value {
Value::Object(mut m) => {
m.insert(
"data_base64".to_string(),
Value::String(base64::encode(b"hello world")),
Value::String(BASE64_STANDARD.encode(b"hello world")),
);
Value::Object(m)
}
@ -187,7 +188,11 @@ pub fn full_non_json_data() -> Event {
let mut event = full_json_data();
let value = full_non_json_base64_data();
if let Value::Object(m) = value {
event.set_data_unchecked(base64::decode(m["data_base64"].as_str().unwrap()).unwrap());
event.set_data_unchecked(
BASE64_STANDARD
.decode(m["data_base64"].as_str().unwrap())
.unwrap(),
);
}
event
}
@ -266,6 +271,6 @@ pub fn full_xml_base64_data_json() -> Value {
bool_ext_name: bool_ext_value,
int_ext_name: int_ext_value,
"datacontenttype": xml_datacontenttype(),
"data_base64": base64::encode(Vec::from(xml_data()))
"data_base64": BASE64_STANDARD.encode(Vec::from(xml_data()))
})
}