From 03021f7242bb4037faeb7bb9aa30b9b0ea6a8c41 Mon Sep 17 00:00:00 2001 From: Omar Zabala-Ferrera <73452461+ozabalaferrera@users.noreply.github.com> Date: Sat, 13 Jul 2024 23:40:55 -0400 Subject: [PATCH] Upgrade axum. Breaks docs. Signed-off-by: Omar Zabala-Ferrera <73452461+ozabalaferrera@users.noreply.github.com> --- Cargo.toml | 8 ++++- src/binding/axum/extract.rs | 53 ++++++++++++++++------------- src/binding/axum/mod.rs | 10 +++--- src/binding/axum/response.rs | 22 +++++------- src/binding/http/builder/adapter.rs | 43 +++++++++++++++++++++++ src/binding/http/builder/mod.rs | 4 ++- src/binding/http/deserializer.rs | 2 ++ src/binding/http/headers.rs | 2 ++ src/binding/http/mod.rs | 4 +++ src/binding/http/serializer.rs | 4 +++ src/message/mod.rs | 12 +++++++ 11 files changed, 121 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bb72c95..84f15dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ actix = ["actix-web", "actix-http", "async-trait", "bytes", "futures", "http"] 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"] +axum = ["bytes", "http-1-1", "hyper-1-3", "axum-lib-0-7", "http-body-1-0", "http-body-util", "async-trait"] poem = ["bytes", "http", "poem-lib", "hyper", "async-trait"] nats = ["nats-lib"] @@ -50,10 +50,15 @@ rdkafka-lib = { version = "^0.36", features = ["cmake-build"], optional = true, warp-lib = { version = "^0.3", optional = true, package = "warp" } async-trait = { version = "^0.1.33", optional = true } bytes = { version = "^1.0", optional = true } +# bytes-1-6 = { version = "^1.6", optional = true, package="bytes" } futures = { version = "^0.3", optional = true } http = { version = "0.2", optional = true } +http-1-1 = { version = "1.1", optional = true, package = "http"} axum-lib = { version = "^0.6", optional = true, package="axum"} +axum-lib-0-7 = { version = "^0.7", optional = true, package="axum"} http-body = { version = "^0.4", optional = true } +http-body-1-0 = { version = "^1.0", optional = true, package="http-body" } +http-body-util = {version = "^0.1", optional = true} poem-lib = { version = "=1.2.34", optional = true, package = "poem" } nats-lib = { version = "0.21.0", optional = true, package = "nats" } @@ -65,6 +70,7 @@ web-sys = { version = "^0.3", features = ["Window", "Location"] } [target.'cfg(not(target_os = "wasi"))'.dependencies] hyper = { version = "^0.14", optional = true } +hyper-1-3 = { version = "^1.3", optional = true, package="hyper" } [target.'cfg(all(target_arch = "wasm32", target_os = "wasi"))'.dependencies] hyper_wasi = { version = "0.15", features = ["full"], optional = true } diff --git a/src/binding/axum/extract.rs b/src/binding/axum/extract.rs index fd03379..ceb7383 100644 --- a/src/binding/axum/extract.rs +++ b/src/binding/axum/extract.rs @@ -1,45 +1,52 @@ -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_0_7 as axum; use http::StatusCode; -use http_body::Body; -use hyper::body; +use http_1_1 as http; use crate::binding::http::to_event; use crate::event::Event; -type BoxError = Box; - #[async_trait] -impl FromRequest for Event +impl FromRequest for Event where - B: Body + Send + 'static, - B::Data: Send, - B::Error: Into, + Bytes: FromRequest, S: Send + Sync, { - type Rejection = (StatusCode, String); + type Rejection = Response; - async fn from_request(req: Request, _state: &S) -> Result { - 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 { + 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 axum_lib_0_7 as axum; use super::*; use axum::body::Body; + use axum::extract::FromRequest; use axum::http::{self, Request, StatusCode}; use crate::test::fixtures; @@ -80,7 +87,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) } diff --git a/src/binding/axum/mod.rs b/src/binding/axum/mod.rs index cb7b8a3..6c9d7ca 100644 --- a/src/binding/axum/mod.rs +++ b/src/binding/axum/mod.rs @@ -6,13 +6,14 @@ //! To echo events: //! //! ``` -//! use axum_lib as axum; +//! # use axum_lib_0_7 as axum; //! use axum::{ //! routing::{get, post}, //! Router, //! }; //! use cloudevents::Event; //! use http::StatusCode; +//! # use http_1_1 as http; //! //! fn app() -> Router { //! Router::new() @@ -31,13 +32,14 @@ //! To create event inside request handlers and send them as responses: //! //! ``` -//! use axum_lib as axum; +//! # use axum_lib_0_7 as axum; //! use axum::{ //! routing::{get, post}, //! Router, //! }; //! use cloudevents::{Event, EventBuilder, EventBuilderV10}; //! use http::StatusCode; +//! # use http_1_1 as http; //! use serde_json::json; //! //! fn app() -> Router { @@ -77,7 +79,7 @@ pub mod response; #[cfg(test)] mod tests { - use axum_lib as axum; + use axum_lib_0_7 as axum; use axum::{ body::Body, @@ -155,7 +157,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); } diff --git a/src/binding/axum/response.rs b/src/binding/axum/response.rs index 3f4b956..6a8efe6 100644 --- a/src/binding/axum/response.rs +++ b/src/binding/axum/response.rs @@ -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_0_7 as axum; +use http::{header, StatusCode}; +use http_1_1 as http; impl IntoResponse for Event { - fn into_response(self) -> Response { + fn into_response(self) -> Response { 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); } diff --git a/src/binding/http/builder/adapter.rs b/src/binding/http/builder/adapter.rs index afdd497..2f58e61 100644 --- a/src/binding/http/builder/adapter.rs +++ b/src/binding/http/builder/adapter.rs @@ -1,15 +1,27 @@ +#[cfg(feature = "axum")] +use bytes::Bytes; use http::Response; +#[cfg(feature = "axum")] +use http_1_1 as http; +#[cfg(feature = "axum")] +use http_body_util::Full; +#[cfg(not(feature = "axum"))] use hyper::body::Body; use std::cell::Cell; use crate::binding::http::{Builder, Serializer}; use crate::message::{BinaryDeserializer, Error, Result}; use crate::Event; +#[cfg(feature = "axum")] +use std::convert::Infallible; +#[cfg(feature = "axum")] +type BoxBody = http_body_util::combinators::UnsyncBoxBody; struct Adapter { builder: Cell, } +#[cfg(not(feature = "axum"))] impl Builder> for Adapter { fn header(&mut self, key: &str, value: http::header::HeaderValue) { self.builder.set(self.builder.take().header(key, value)); @@ -27,6 +39,27 @@ impl Builder> for Adapter { } } +#[cfg(feature = "axum")] +impl Builder> 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) -> Result> { + self.builder + .take() + .body(BoxBody::new(Full::from(bytes))) + .map_err(|e| crate::message::Error::Other { + source: Box::new(e), + }) + } + + fn finish(&mut self) -> Result> { + self.body(Vec::new()) + } +} + +#[cfg(not(feature = "axum"))] pub fn to_response(event: Event) -> std::result::Result, Error> { BinaryDeserializer::deserialize_binary( event, @@ -35,3 +68,13 @@ pub fn to_response(event: Event) -> std::result::Result, Error> { }), ) } + +#[cfg(feature = "axum")] +pub fn to_response(event: Event) -> std::result::Result, Error> { + BinaryDeserializer::deserialize_binary( + event, + Serializer::new(Adapter { + builder: Cell::new(http::Response::builder()), + }), + ) +} diff --git a/src/binding/http/builder/mod.rs b/src/binding/http/builder/mod.rs index 81b6381..acd145e 100644 --- a/src/binding/http/builder/mod.rs +++ b/src/binding/http/builder/mod.rs @@ -1,7 +1,9 @@ -#[cfg(feature = "hyper")] +#[cfg(any(feature = "hyper", feature = "hyper-1-3"))] pub mod adapter; use crate::message::Result; +#[cfg(feature = "axum")] +use http_1_1 as http; pub trait Builder { fn header(&mut self, key: &str, value: http::header::HeaderValue); diff --git a/src/binding/http/deserializer.rs b/src/binding/http/deserializer.rs index 21a1c80..a8e2223 100644 --- a/src/binding/http/deserializer.rs +++ b/src/binding/http/deserializer.rs @@ -8,6 +8,8 @@ use crate::{ Result, StructuredDeserializer, StructuredSerializer, }, }; +#[cfg(feature = "axum")] +use http_1_1 as http; use std::convert::TryFrom; pub struct Deserializer<'a, T: Headers<'a>> { diff --git a/src/binding/http/headers.rs b/src/binding/http/headers.rs index a129d87..8b2816d 100644 --- a/src/binding/http/headers.rs +++ b/src/binding/http/headers.rs @@ -1,4 +1,6 @@ use http::header::{AsHeaderName, HeaderMap, HeaderName, HeaderValue}; +#[cfg(feature = "axum")] +use http_1_1 as http; /// Any http library should be able to use the /// [`to_event`](super::to_event) function with an implementation of diff --git a/src/binding/http/mod.rs b/src/binding/http/mod.rs index 52b0e03..a459920 100644 --- a/src/binding/http/mod.rs +++ b/src/binding/http/mod.rs @@ -13,6 +13,8 @@ mod serializer; pub use builder::Builder; use core::convert::TryFrom; use http::Response; +#[cfg(feature = "axum")] +use http_1_1 as http; pub use serializer::Serializer; use std::convert::TryInto; use std::fmt::Debug; @@ -52,6 +54,8 @@ mod tests { use crate::Event; use core::convert::TryFrom; use http::Response; + #[cfg(feature = "axum")] + use http_1_1 as http; #[test] fn test_response_to_event() { diff --git a/src/binding/http/serializer.rs b/src/binding/http/serializer.rs index 30ca8e1..4f38cf8 100644 --- a/src/binding/http/serializer.rs +++ b/src/binding/http/serializer.rs @@ -12,6 +12,8 @@ use crate::message::{ }; use crate::Event; use http::Request; +#[cfg(feature = "axum")] +use http_1_1 as 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; + #[cfg(feature = "axum")] + use http_1_1 as http; use std::convert::TryFrom; #[test] diff --git a/src/message/mod.rs b/src/message/mod.rs index 1466057..4cd9bb4 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -2,6 +2,18 @@ //! //! Note: these APIs should be considered unstable and subject to changes. +#[cfg(all( + feature = "axum", + any( + feature = "http-binding", + feature = "actix", + feature = "reqwest", + feature = "warp", + feature = "poem" + ) +))] +compile_error!("feature `axum` cannot be used with features `http-binding`, `actix`, `reqwest`, `warp`, or `poem`"); + mod deserializer; mod encoding; mod error;