Upgrade axum
crate from 0.6 to 0.7 version (#1224)
This commit is contained in:
parent
bd8dc582a4
commit
58ae682f91
8 changed files with 63 additions and 60 deletions
|
@ -10,7 +10,7 @@ All user visible changes to `juniper_axum` crate will be documented in this file
|
||||||
|
|
||||||
### Initialized
|
### Initialized
|
||||||
|
|
||||||
- Dependent on 0.6 version of [`axum` crate]. ([#1088])
|
- Dependent on 0.7 version of [`axum` crate]. ([#1088], [#1224])
|
||||||
- Dependent on 0.16 version of [`juniper` crate]. ([#1088])
|
- Dependent on 0.16 version of [`juniper` crate]. ([#1088])
|
||||||
- Dependent on 0.4 version of [`juniper_graphql_ws` crate]. ([#1088])
|
- Dependent on 0.4 version of [`juniper_graphql_ws` crate]. ([#1088])
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ All user visible changes to `juniper_axum` crate will be documented in this file
|
||||||
[#986]: /../../issues/986
|
[#986]: /../../issues/986
|
||||||
[#1088]: /../../pull/1088
|
[#1088]: /../../pull/1088
|
||||||
[#1184]: /../../issues/1184
|
[#1184]: /../../issues/1184
|
||||||
|
[#1224]: /../../pull/1224
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
subscriptions = ["axum/ws", "juniper_graphql_ws/graphql-ws", "dep:futures"]
|
subscriptions = ["axum/ws", "juniper_graphql_ws/graphql-ws", "dep:futures"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.6.20"
|
axum = "0.7"
|
||||||
futures = { version = "0.3.22", optional = true }
|
futures = { version = "0.3.22", optional = true }
|
||||||
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
|
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
|
||||||
juniper_graphql_ws = { version = "0.4.0-dev", path = "../juniper_graphql_ws", features = ["graphql-transport-ws"] }
|
juniper_graphql_ws = { version = "0.4.0-dev", path = "../juniper_graphql_ws", features = ["graphql-transport-ws"] }
|
||||||
|
@ -38,9 +38,10 @@ bytes = "1.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
axum = { version = "0.6", features = ["macros"] }
|
axum = { version = "0.7", features = ["http1", "macros", "tokio"] }
|
||||||
|
futures = "0.3.22"
|
||||||
juniper = { version = "0.16.0-dev", path = "../juniper", features = ["expose-test-schema"] }
|
juniper = { version = "0.16.0-dev", path = "../juniper", features = ["expose-test-schema"] }
|
||||||
tokio = { version = "1.20", features = ["macros", "rt-multi-thread", "time"] }
|
tokio = { version = "1.20", features = ["macros", "net", "rt-multi-thread", "time"] }
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
tokio-tungstenite = "0.20"
|
tokio-tungstenite = "0.20"
|
||||||
tower-service = "0.3"
|
tower-service = "0.3"
|
||||||
|
|
|
@ -19,6 +19,7 @@ use juniper_axum::{
|
||||||
extract::JuniperRequest, graphiql, playground, response::JuniperResponse, subscriptions,
|
extract::JuniperRequest, graphiql, playground, response::JuniperResponse, subscriptions,
|
||||||
};
|
};
|
||||||
use juniper_graphql_ws::ConnectionConfig;
|
use juniper_graphql_ws::ConnectionConfig;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
type Schema = RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
|
type Schema = RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ async fn main() {
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route(
|
.route(
|
||||||
"/graphql",
|
"/graphql",
|
||||||
on(MethodFilter::GET | MethodFilter::POST, custom_graphql),
|
on(MethodFilter::GET.or(MethodFilter::POST), custom_graphql),
|
||||||
)
|
)
|
||||||
.route("/subscriptions", get(custom_subscriptions))
|
.route("/subscriptions", get(custom_subscriptions))
|
||||||
.route("/graphiql", get(graphiql("/graphql", "/subscriptions")))
|
.route("/graphiql", get(graphiql("/graphql", "/subscriptions")))
|
||||||
|
@ -78,9 +79,11 @@ async fn main() {
|
||||||
.layer(Extension(database));
|
.layer(Extension(database));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
|
||||||
tracing::info!("listening on {addr}");
|
let listener = TcpListener::bind(addr)
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| panic!("failed to run `axum::Server`: {e}"));
|
.unwrap_or_else(|e| panic!("failed to listen on {addr}: {e}"));
|
||||||
|
tracing::info!("listening on {addr}");
|
||||||
|
axum::serve(listener, app)
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|e| panic!("failed to run `axum::serve`: {e}"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use futures::stream::{BoxStream, StreamExt as _};
|
||||||
use juniper::{graphql_object, graphql_subscription, EmptyMutation, FieldError, RootNode};
|
use juniper::{graphql_object, graphql_subscription, EmptyMutation, FieldError, RootNode};
|
||||||
use juniper_axum::{graphiql, graphql, playground, ws};
|
use juniper_axum::{graphiql, graphql, playground, ws};
|
||||||
use juniper_graphql_ws::ConnectionConfig;
|
use juniper_graphql_ws::ConnectionConfig;
|
||||||
use tokio::time::interval;
|
use tokio::{net::TcpListener, time::interval};
|
||||||
use tokio_stream::wrappers::IntervalStream;
|
use tokio_stream::wrappers::IntervalStream;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
@ -65,7 +65,7 @@ async fn main() {
|
||||||
.route(
|
.route(
|
||||||
"/graphql",
|
"/graphql",
|
||||||
on(
|
on(
|
||||||
MethodFilter::GET | MethodFilter::POST,
|
MethodFilter::GET.or(MethodFilter::POST),
|
||||||
graphql::<Arc<Schema>>,
|
graphql::<Arc<Schema>>,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -79,9 +79,11 @@ async fn main() {
|
||||||
.layer(Extension(Arc::new(schema)));
|
.layer(Extension(Arc::new(schema)));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
|
||||||
tracing::info!("listening on {addr}");
|
let listener = TcpListener::bind(addr)
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| panic!("failed to run `axum::Server`: {e}"));
|
.unwrap_or_else(|e| panic!("failed to listen on {addr}: {e}"));
|
||||||
|
tracing::info!("listening on {addr}");
|
||||||
|
axum::serve(listener, app)
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|e| panic!("failed to run `axum::serve`: {e}"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,14 +71,14 @@ where
|
||||||
S: ScalarValue;
|
S: ScalarValue;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<S, State> FromRequest<State, Body> for JuniperRequest<S>
|
impl<S, State> FromRequest<State> for JuniperRequest<S>
|
||||||
where
|
where
|
||||||
S: ScalarValue,
|
S: ScalarValue,
|
||||||
State: Sync,
|
State: Sync,
|
||||||
Query<GetRequest>: FromRequestParts<State>,
|
Query<GetRequest>: FromRequestParts<State>,
|
||||||
Json<GraphQLBatchRequest<S>>: FromRequest<State, Body>,
|
Json<GraphQLBatchRequest<S>>: FromRequest<State>,
|
||||||
<Json<GraphQLBatchRequest<S>> as FromRequest<State, Body>>::Rejection: fmt::Display,
|
<Json<GraphQLBatchRequest<S>> as FromRequest<State>>::Rejection: fmt::Display,
|
||||||
String: FromRequest<State, Body>,
|
String: FromRequest<State>,
|
||||||
{
|
{
|
||||||
type Rejection = Response;
|
type Rejection = Response;
|
||||||
|
|
||||||
|
@ -96,7 +96,9 @@ where
|
||||||
.into_response()
|
.into_response()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
match (req.method(), content_type) {
|
// TODO: Move into `match` expression directly once MSRV is bumped higher than 1.74.
|
||||||
|
let method = req.method();
|
||||||
|
match (method, content_type) {
|
||||||
(&Method::GET, _) => req
|
(&Method::GET, _) => req
|
||||||
.extract_parts::<Query<GetRequest>>()
|
.extract_parts::<Query<GetRequest>>()
|
||||||
.await
|
.await
|
||||||
|
@ -180,13 +182,8 @@ impl<S: ScalarValue> TryFrom<GetRequest> for GraphQLRequest<S> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod juniper_request_tests {
|
mod juniper_request_tests {
|
||||||
use std::fmt;
|
use axum::{body::Body, extract::FromRequest as _, http::Request};
|
||||||
|
use futures::TryStreamExt as _;
|
||||||
use axum::{
|
|
||||||
body::{Body, Bytes, HttpBody},
|
|
||||||
extract::FromRequest as _,
|
|
||||||
http::Request,
|
|
||||||
};
|
|
||||||
use juniper::{
|
use juniper::{
|
||||||
graphql_input_value,
|
graphql_input_value,
|
||||||
http::{GraphQLBatchRequest, GraphQLRequest},
|
http::{GraphQLBatchRequest, GraphQLRequest},
|
||||||
|
@ -279,18 +276,15 @@ mod juniper_request_tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the provided [`HttpBody`] into a [`String`].
|
/// Converts the provided [`Body`] into a [`String`].
|
||||||
async fn display_body<B>(mut body: B) -> String
|
async fn display_body(body: Body) -> String {
|
||||||
where
|
String::from_utf8(
|
||||||
B: HttpBody<Data = Bytes> + Unpin,
|
body.into_data_stream()
|
||||||
B::Error: fmt::Display,
|
.map_ok(|bytes| bytes.to_vec())
|
||||||
{
|
.try_concat()
|
||||||
let mut body_bytes = vec![];
|
.await
|
||||||
while let Some(bytes) = body.data().await {
|
.unwrap(),
|
||||||
body_bytes.extend(
|
)
|
||||||
bytes.unwrap_or_else(|e| panic!("failed to represent `Body` as `Bytes`: {e}")),
|
.unwrap_or_else(|e| panic!("not UTF-8 body: {e}"))
|
||||||
);
|
|
||||||
}
|
|
||||||
String::from_utf8(body_bytes).unwrap_or_else(|e| panic!("not UTF-8 body: {e}"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::{Body, HttpBody as _},
|
body::Body,
|
||||||
http::Request,
|
http::Request,
|
||||||
response::Response,
|
response::Response,
|
||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Extension, Router,
|
Extension, Router,
|
||||||
};
|
};
|
||||||
|
use futures::TryStreamExt as _;
|
||||||
use juniper::{
|
use juniper::{
|
||||||
http::tests::{run_http_test_suite, HttpIntegration, TestResponse},
|
http::tests::{run_http_test_suite, HttpIntegration, TestResponse},
|
||||||
tests::fixtures::starwars::schema::{Database, Query},
|
tests::fixtures::starwars::schema::{Database, Query},
|
||||||
|
@ -97,12 +98,15 @@ async fn into_test_response(resp: Response) -> TestResponse {
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut body = resp.into_body();
|
let body = String::from_utf8(
|
||||||
let mut body_bytes = vec![];
|
resp.into_body()
|
||||||
while let Some(bytes) = body.data().await {
|
.into_data_stream()
|
||||||
body_bytes.extend(bytes.unwrap());
|
.map_ok(|bytes| bytes.to_vec())
|
||||||
}
|
.try_concat()
|
||||||
let body = String::from_utf8(body_bytes).unwrap_or_else(|e| panic!("not UTF-8 body: {e}"));
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| panic!("not UTF-8 body: {e}"));
|
||||||
|
|
||||||
TestResponse {
|
TestResponse {
|
||||||
status_code,
|
status_code,
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#![cfg(not(windows))]
|
#![cfg(not(windows))]
|
||||||
|
|
||||||
use std::{
|
use std::{net::SocketAddr, sync::Arc};
|
||||||
net::{SocketAddr, TcpListener},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use axum::{routing::get, Extension, Router};
|
use axum::{routing::get, Extension, Router};
|
||||||
|
@ -15,7 +12,10 @@ use juniper::{
|
||||||
};
|
};
|
||||||
use juniper_axum::subscriptions;
|
use juniper_axum::subscriptions;
|
||||||
use juniper_graphql_ws::ConnectionConfig;
|
use juniper_graphql_ws::ConnectionConfig;
|
||||||
use tokio::{net::TcpStream, time::timeout};
|
use tokio::{
|
||||||
|
net::{TcpListener, TcpStream},
|
||||||
|
time::timeout,
|
||||||
|
};
|
||||||
use tokio_tungstenite::{connect_async, tungstenite::Message, MaybeTlsStream, WebSocketStream};
|
use tokio_tungstenite::{connect_async, tungstenite::Message, MaybeTlsStream, WebSocketStream};
|
||||||
|
|
||||||
type Schema = RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
|
type Schema = RootNode<'static, Query, EmptyMutation<Database>, Subscription>;
|
||||||
|
@ -49,15 +49,13 @@ impl TestApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(self, messages: Vec<WsIntegrationMessage>) -> Result<(), anyhow::Error> {
|
async fn run(self, messages: Vec<WsIntegrationMessage>) -> Result<(), anyhow::Error> {
|
||||||
let listener = TcpListener::bind("0.0.0.0:0".parse::<SocketAddr>().unwrap()).unwrap();
|
let listener = TcpListener::bind("0.0.0.0:0".parse::<SocketAddr>().unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
axum::Server::from_tcp(listener)
|
axum::serve(listener, self.0).await.unwrap();
|
||||||
.unwrap()
|
|
||||||
.serve(self.0.into_make_service())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let (mut websocket, _) = connect_async(format!("ws://{}/subscriptions", addr))
|
let (mut websocket, _) = connect_async(format!("ws://{}/subscriptions", addr))
|
||||||
|
|
|
@ -39,7 +39,7 @@ impl TestWarpIntegration {
|
||||||
let rt = tokio::runtime::Runtime::new()
|
let rt = tokio::runtime::Runtime::new()
|
||||||
.unwrap_or_else(|e| panic!("failed to create `tokio::Runtime`: {e}"));
|
.unwrap_or_else(|e| panic!("failed to create `tokio::Runtime`: {e}"));
|
||||||
rt.block_on(async move {
|
rt.block_on(async move {
|
||||||
make_test_response(req.filter(&self.filter).await.unwrap_or_else(|rejection| {
|
into_test_response(req.filter(&self.filter).await.unwrap_or_else(|rejection| {
|
||||||
let code = if rejection.is_not_found() {
|
let code = if rejection.is_not_found() {
|
||||||
http::StatusCode::NOT_FOUND
|
http::StatusCode::NOT_FOUND
|
||||||
} else if let Some(body::BodyDeserializeError { .. }) = rejection.find() {
|
} else if let Some(body::BodyDeserializeError { .. }) = rejection.find() {
|
||||||
|
@ -101,7 +101,7 @@ impl HttpIntegration for TestWarpIntegration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn make_test_response(resp: reply::Response) -> TestResponse {
|
async fn into_test_response(resp: reply::Response) -> TestResponse {
|
||||||
let (parts, body) = resp.into_parts();
|
let (parts, body) = resp.into_parts();
|
||||||
|
|
||||||
let status_code = parts.status.as_u16().into();
|
let status_code = parts.status.as_u16().into();
|
||||||
|
|
Loading…
Reference in a new issue