reproduce issue 3004

This commit is contained in:
Yann Simon 2024-10-22 23:27:37 +02:00
parent 280d16a610
commit b110d55a58
No known key found for this signature in database
4 changed files with 65 additions and 2 deletions

View file

@ -43,7 +43,10 @@ typed-routing = ["dep:axum-macros", "dep:percent-encoding", "dep:serde_html_form
axum = { path = "../axum", version = "0.8.0-alpha.1", default-features = false, features = ["original-uri"] }
axum-core = { path = "../axum-core", version = "0.5.0-alpha.1" }
bytes = "1.1.0"
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
futures = "*"
futures-util = { version = "0.3", default-features = false, features = [
"alloc",
] }
http = "1.0.0"
http-body = "1.0.0"
http-body-util = "0.1.0"

View file

@ -78,6 +78,7 @@ pub mod handler;
pub mod middleware;
pub mod response;
pub mod routing;
mod test_method_routing;
#[cfg(feature = "json-lines")]
pub mod json_lines;

View file

@ -0,0 +1,59 @@
use std::{
collections::HashMap,
convert::Infallible,
marker::PhantomData,
task::{Context, Poll},
};
use axum::{
body::Body,
extract::Request,
http::StatusCode,
response::{IntoResponse, Response},
routing::MethodRouter,
};
use futures::{future::BoxFuture, FutureExt};
use tower::Service;
trait CommandFromBody {
fn command_from_body(body: &[u8]) -> Option<&str>;
}
struct ExampleService<C> {
routes: HashMap<String, MethodRouter>,
_phantom_c: PhantomData<fn() -> C>,
}
impl<C> Service<Request> for ExampleService<C>
where
C: CommandFromBody,
{
type Error = Infallible;
type Response = Response;
type Future = BoxFuture<'static, Result<Response, Infallible>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Request) -> Self::Future {
async move {
let (parts, body) = req.into_parts();
let Ok(bytes) = axum::body::to_bytes(body, usize::MAX).await else {
return Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response());
};
match C::command_from_body(&bytes).and_then(|cmd| self.routes.get(cmd)) {
Some(router) => {
let req = Request::from_parts(parts, Body::from(bytes));
router.call_with_state(req, ()).await
}
None => Ok(StatusCode::NOT_FOUND.into_response()),
}
}
.boxed()
}
}

View file

@ -1110,7 +1110,7 @@ where
self
}
pub(crate) fn call_with_state(&self, req: Request, state: S) -> RouteFuture<E> {
pub fn call_with_state(&self, req: Request, state: S) -> RouteFuture<E> {
macro_rules! call {
(
$req:expr,