Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Axum integration #1088

Merged
merged 35 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
bc7f4a8
Add Error to Connection Stream
btielen Jul 15, 2022
11ecc25
Add post_with_variables test
btielen Jul 22, 2022
2932e6e
Decouple test and implementation
btielen Jul 23, 2022
719eb97
Add juniper_axum
btielen Jul 24, 2022
183302c
Clippy and format
btielen Jul 24, 2022
f9326e5
Merge branch 'master' into axum
ilslv Aug 3, 2022
59ab64a
Corrections
ilslv Aug 3, 2022
7414b4c
Update juniper_axum/README.md
LegNeato Aug 28, 2023
e1a1104
Update juniper_warp/src/lib.rs
LegNeato Aug 28, 2023
fbef4c0
Merge branch 'master' into axum
tyranron Nov 7, 2023
b5d5be8
Revert unrelevant changes
tyranron Nov 7, 2023
f5b0d70
Add to CI
tyranron Nov 7, 2023
2691dc4
Tune up deps
tyranron Nov 7, 2023
5f50474
Refactor solution, vol.1
tyranron Nov 7, 2023
224e30c
Refactor solution, vol.2 [skip ci]
tyranron Nov 7, 2023
072717e
Get rid of `GetQueryVariables`
tyranron Nov 7, 2023
aa03df3
Get rid of `JsonRequestBody` [skip ci]
tyranron Nov 7, 2023
baea7e6
Parametrize with `ScalarValue`
tyranron Nov 8, 2023
8961631
Fix `extract` unit tests
tyranron Nov 8, 2023
2a819fd
Rework `graphql-ws` subscriptions
tyranron Nov 8, 2023
ac97a3a
Fix doc tests
tyranron Nov 8, 2023
4600686
Add `graphql-transport-ws` impl
tyranron Nov 8, 2023
3b3e7e3
Impl auto-selection between new `graphql-transport-ws` and old `graph…
tyranron Nov 8, 2023
4d89d51
Add ready-to-go `graphql` handler
tyranron Nov 8, 2023
ccac700
Add ready-to-go `ws`, `graphql_ws` and `graphql_transport_ws` handlers
tyranron Nov 8, 2023
fa73e0b
Fix docs
tyranron Nov 8, 2023
5491556
Add `release.toml` [skip ci]
tyranron Nov 8, 2023
90bcc3c
Update workspace
tyranron Nov 8, 2023
cac125f
Rework `simple` example
tyranron Nov 8, 2023
afa9521
Rework `strawars` example as `custom`
tyranron Nov 8, 2023
e2561c7
Reworking integration tests, vol.1
tyranron Nov 8, 2023
8ba8de5
Reworking integration tests, vol.2
tyranron Nov 8, 2023
c44f5cd
Fill-up CHANGELOG
tyranron Nov 8, 2023
c9cf94e
Fix tests
tyranron Nov 8, 2023
bb6dcaa
Try fix MSRV
tyranron Nov 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ jobs:
- { feature: graphql-ws, crate: juniper_graphql_ws }
- { feature: <none>, crate: juniper_actix }
- { feature: subscriptions, crate: juniper_actix }
- { feature: <none>, crate: juniper_axum }
- { feature: subscriptions, crate: juniper_axum }
- { feature: <none>, crate: juniper_warp }
- { feature: subscriptions, crate: juniper_warp }
runs-on: ubuntu-latest
Expand Down Expand Up @@ -148,6 +150,7 @@ jobs:
- juniper_subscriptions
- juniper_graphql_ws
- juniper_actix
- juniper_axum
- juniper_hyper
#- juniper_iron
- juniper_rocket
Expand Down Expand Up @@ -200,6 +203,7 @@ jobs:
- juniper_integration_tests
- juniper_codegen_tests
- juniper_actix
- juniper_axum
- juniper_hyper
- juniper_iron
- juniper_rocket
Expand Down Expand Up @@ -326,6 +330,7 @@ jobs:
- juniper_subscriptions
- juniper_graphql_ws
- juniper_actix
- juniper_axum
- juniper_hyper
- juniper_iron
- juniper_rocket
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ members = [
"juniper_graphql_ws",
"juniper_warp",
"juniper_actix",
"juniper_axum",
"tests/codegen",
"tests/integration",
]
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ your Schemas automatically.
### Web Frameworks

- [actix][actix]
- [axum][axum]
- [hyper][hyper]
- [rocket][rocket]
- [iron][iron]
Expand All @@ -93,6 +94,7 @@ your Schemas automatically.
Juniper has not reached 1.0 yet, thus some API instability should be expected.

[actix]: https://actix.rs/
[axum]: https://docs.rs/axum
[graphql]: http://graphql.org
[graphiql]: https://github.com/graphql/graphiql
[playground]: https://github.com/prisma/graphql-playground
Expand Down
3 changes: 3 additions & 0 deletions juniper/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ As an exception to other [GraphQL] libraries for other languages, [Juniper] buil
### Web servers

- [`actix-web`] ([`juniper_actix`] crate)
- [`axum`] ([`juniper_axum`] crate)
- [`hyper`] ([`juniper_hyper`] crate)
- [`iron`] ([`juniper_iron`] crate)
- [`rocket`] ([`juniper_rocket`] crate)
Expand All @@ -81,11 +82,13 @@ This project is licensed under [BSD 2-Clause License](https://github.com/graphql


[`actix-web`]: https://docs.rs/actix-web
[`axum`]: https://docs.rs/axum
[`bigdecimal`]: https://docs.rs/bigdecimal
[`bson`]: https://docs.rs/bson
[`chrono`]: https://docs.rs/chrono
[`chrono-tz`]: https://docs.rs/chrono-tz
[`juniper_actix`]: https://docs.rs/juniper_actix
[`juniper_axum`]: https://docs.rs/juniper_axum
[`juniper_hyper`]: https://docs.rs/juniper_hyper
[`juniper_iron`]: https://docs.rs/juniper_iron
[`juniper_rocket`]: https://docs.rs/juniper_rocket
Expand Down
6 changes: 6 additions & 0 deletions juniper/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ exactly = 2
search = "juniper = \\{ version = \"[^\"]+\""
replace = "juniper = { version = \"{{version}}\""

[[pre-release-replacements]]
file = "../juniper_axum/Cargo.toml"
exactly = 2
search = "juniper = \\{ version = \"[^\"]+\""
replace = "juniper = { version = \"{{version}}\""

[[pre-release-replacements]]
file = "../juniper_graphql_ws/Cargo.toml"
exactly = 1
Expand Down
62 changes: 52 additions & 10 deletions juniper/src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ where
pub operation_name: Option<String>,

/// Optional variables to execute the GraphQL operation with.
// TODO: Use `Variables` instead of `InputValue`?
#[serde(bound(
deserialize = "InputValue<S>: Deserialize<'de>",
serialize = "InputValue<S>: Serialize",
Expand Down Expand Up @@ -238,11 +239,11 @@ where
/// A batch operation request.
///
/// Empty batch is considered as invalid value, so cannot be deserialized.
#[serde(deserialize_with = "deserialize_non_empty_vec")]
#[serde(deserialize_with = "deserialize_non_empty_batch")]
Batch(Vec<GraphQLRequest<S>>),
}

fn deserialize_non_empty_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
fn deserialize_non_empty_batch<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
where
D: de::Deserializer<'de>,
T: Deserialize<'de>,
Expand All @@ -251,7 +252,10 @@ where

let v = Vec::<T>::deserialize(deserializer)?;
if v.is_empty() {
Err(D::Error::invalid_length(0, &"a positive integer"))
Err(D::Error::invalid_length(
0,
&"non-empty batch of GraphQL requests",
))
} else {
Ok(v)
}
Expand Down Expand Up @@ -403,6 +407,9 @@ pub mod tests {
println!(" - test_get_with_variables");
test_get_with_variables(integration);

println!(" - test_post_with_variables");
test_post_with_variables(integration);

println!(" - test_simple_post");
test_simple_post(integration);

Expand Down Expand Up @@ -501,13 +508,48 @@ pub mod tests {
"NEW_HOPE",
"EMPIRE",
"JEDI"
],
"homePlanet": "Tatooine",
"name": "Luke Skywalker",
"id": "1000"
}
],
"homePlanet": "Tatooine",
"name": "Luke Skywalker",
"id": "1000"
}
}"#
}
}"#
)
.expect("Invalid JSON constant in test")
);
}

fn test_post_with_variables<T: HttpIntegration>(integration: &T) {
let response = integration.post_json(
"/",
r#"{
"query":
"query($id: String!) { human(id: $id) { id, name, appearsIn, homePlanet } }",
"variables": {"id": "1000"}
}"#,
);

assert_eq!(response.status_code, 200);
assert_eq!(response.content_type, "application/json");

assert_eq!(
unwrap_json_response(&response),
serde_json::from_str::<Json>(
r#"{
"data": {
"human": {
"appearsIn": [
"NEW_HOPE",
"EMPIRE",
"JEDI"
],
"homePlanet": "Tatooine",
"name": "Luke Skywalker",
"id": "1000"
}
}
}"#
)
.expect("Invalid JSON constant in test")
);
Expand Down Expand Up @@ -752,7 +794,7 @@ pub mod tests {

#[allow(missing_docs)]
pub async fn run_test_suite<T: WsIntegration>(integration: &T) {
println!("Running `graphql-ws` test suite for integration");
println!("Running `graphql-transport-ws` test suite for integration");

println!(" - graphql_ws::test_simple_subscription");
test_simple_subscription(integration).await;
Expand Down
2 changes: 2 additions & 0 deletions juniper/src/tests/fixtures/starwars/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{collections::HashMap, pin::Pin};

use crate::{graphql_interface, graphql_object, graphql_subscription, Context, GraphQLEnum};

#[derive(Clone, Copy, Debug)]
pub struct Query;

#[graphql_object(context = Database)]
Expand Down Expand Up @@ -33,6 +34,7 @@ impl Query {
}
}

#[derive(Clone, Copy, Debug)]
pub struct Subscription;

type HumanStream = Pin<Box<dyn futures::Stream<Item = Human> + Send>>;
Expand Down
4 changes: 2 additions & 2 deletions juniper_actix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "juniper_actix"
version = "0.5.0-dev"
edition = "2021"
rust-version = "1.68"
rust-version = "1.73"
description = "`juniper` GraphQL integration with `actix-web`."
license = "BSD-2-Clause"
authors = ["Jordao Rosario <[email protected]>"]
Expand All @@ -12,7 +12,7 @@ repository = "https://github.com/graphql-rust/juniper"
readme = "README.md"
categories = ["asynchronous", "web-programming", "web-programming::http-server"]
keywords = ["actix-web", "apollo", "graphql", "juniper", "websocket"]
exclude = ["/examples/", "/release.toml"]
exclude = ["/release.toml"]

[package.metadata.docs.rs]
all-features = true
Expand Down
6 changes: 3 additions & 3 deletions juniper_actix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Crates.io](https://img.shields.io/crates/v/juniper_actix.svg?maxAge=2592000)](https://crates.io/crates/juniper_actix)
[![Documentation](https://docs.rs/juniper_actix/badge.svg)](https://docs.rs/juniper_actix)
[![CI](https://github.com/graphql-rust/juniper/workflows/CI/badge.svg?branch=master "CI")](https://github.com/graphql-rust/juniper/actions?query=workflow%3ACI+branch%3Amaster)
[![Rust 1.68+](https://img.shields.io/badge/rustc-1.68+-lightgray.svg "Rust 1.68+")](https://blog.rust-lang.org/2023/03/09/Rust-1.68.0.html)
[![Rust 1.73+](https://img.shields.io/badge/rustc-1.73+-lightgray.svg "Rust 1.73+")](https://blog.rust-lang.org/2023/10/05/Rust-1.73.0.html)

- [Changelog](https://github.com/graphql-rust/juniper/blob/master/juniper_actix/CHANGELOG.md)

Expand All @@ -26,7 +26,7 @@ A basic usage example can also be found in the [API docs][`juniper_actix`].

## Examples

Check [`examples/actix_server.rs`][1] for example code of a working [`actix-web`] server with [GraphQL] handlers.
Check [`examples/subscription.rs`][1] for example code of a working [`actix-web`] server with [GraphQL] handlers.



Expand All @@ -46,5 +46,5 @@ This project is licensed under [BSD 2-Clause License](https://github.com/graphql
[Juniper Book]: https://graphql-rust.github.io
[Rust]: https://www.rust-lang.org

[1]: https://github.com/graphql-rust/juniper/blob/master/juniper_actix/examples/actix_server.rs
[1]: https://github.com/graphql-rust/juniper/blob/master/juniper_actix/examples/subscription.rs

3 changes: 1 addition & 2 deletions juniper_actix/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ where
/// let app = App::new()
/// .route("/", web::get().to(|| graphiql_handler("/graphql", Some("/graphql/subscriptions"))));
/// ```
#[allow(dead_code)]
pub async fn graphiql_handler(
graphql_endpoint_url: &str,
subscriptions_endpoint_url: Option<&'static str>,
Expand Down Expand Up @@ -419,7 +418,7 @@ pub mod subscriptions {
/// Possible errors of serving an [`actix_ws`] connection.
#[derive(Debug)]
enum Error {
/// Deserializing of a client or server message failed.
/// Deserializing of a client [`actix_ws::Message`] failed.
Serde(serde_json::Error),

/// Unexpected client [`actix_ws::Message`].
Expand Down
43 changes: 43 additions & 0 deletions juniper_axum/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
`juniper_axum` changelog
========================

All user visible changes to `juniper_axum` crate will be documented in this file. This project uses [Semantic Versioning 2.0.0].




## master

### Initialized

- Dependent on 0.6 version of [`axum` crate]. ([#1088])
- Dependent on 0.16 version of [`juniper` crate]. ([#1088])
- Dependent on 0.4 version of [`juniper_graphql_ws` crate]. ([#1088])

### Added

- `extract::JuniperRequest` and `response::JuniperResponse` for using in custom [`axum` crate] handlers. ([#1088])
- `graphql` handler processing [GraphQL] requests for the specified schema. ([#1088], [#1184])
- `subscriptions::graphql_transport_ws()` handler and `subscriptions::serve_graphql_transport_ws()` function allowing to process the [new `graphql-transport-ws` GraphQL over WebSocket Protocol][graphql-transport-ws]. ([#1088], [#986])
- `subscriptions::graphql_ws()` handler and `subscriptions::serve_graphql_ws()` function allowing to process the [legacy `graphql-ws` GraphQL over WebSocket Protocol][graphql-ws]. ([#1088], [#986])
- `subscriptions::ws()` handler and `subscriptions::serve_ws()` function allowing to auto-select between the [legacy `graphql-ws` GraphQL over WebSocket Protocol][graphql-ws] and the [new `graphql-transport-ws` GraphQL over WebSocket Protocol][graphql-transport-ws], based on the `Sec-Websocket-Protocol` HTTP header value. ([#1088], [#986])
- `graphiql` handler serving [GraphiQL]. ([#1088])
- `playground` handler serving [GraphQL Playground]. ([#1088])
- `simple.rs` and `custom.rs` integration examples. ([#1088], [#986], [#1184])

[#986]: /../../issues/986
[#1088]: /../../pull/1088
[#1184]: /../../issues/1184




[`axum` crate]: https://docs.rs/axum
[`juniper` crate]: https://docs.rs/juniper
[`juniper_graphql_ws` crate]: https://docs.rs/juniper_graphql_ws
[GraphiQL]: https://github.com/graphql/graphiql
[GraphQL]: http://graphql.org
[GraphQL Playground]: https://github.com/prisma/graphql-playground
[Semantic Versioning 2.0.0]: https://semver.org
[graphql-transport-ws]: https://github.com/enisdenjo/graphql-ws/blob/v5.14.0/PROTOCOL.md
[graphql-ws]: https://github.com/apollographql/subscriptions-transport-ws/blob/v0.11.0/PROTOCOL.md
61 changes: 61 additions & 0 deletions juniper_axum/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[package]
name = "juniper_axum"
version = "0.1.0"
edition = "2021"
rust-version = "1.73"
description = "`juniper` GraphQL integration with `axum`."
license = "BSD-2-Clause"
authors = [
"Benno Tielen <[email protected]>",
"Kai Ren <[email protected]>",
]
documentation = "https://docs.rs/juniper_axum"
homepage = "https://github.com/graphql-rust/juniper/tree/master/juniper_axum"
repository = "https://github.com/graphql-rust/juniper"
readme = "README.md"
categories = ["asynchronous", "web-programming", "web-programming::http-server"]
keywords = ["apollo", "axum", "graphql", "juniper", "websocket"]
exclude = ["/release.toml"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
subscriptions = ["axum/ws", "juniper_graphql_ws/graphql-ws", "dep:futures"]

[dependencies]
axum = "0.6.20"
futures = { version = "0.3.22", optional = true }
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"] }
serde = { version = "1.0.122", features = ["derive"] }
serde_json = "1.0.18"

# Fixes for `minimal-versions` check.
# TODO: Try remove on upgrade of `axum` crate.
bytes = "1.2"

[dev-dependencies]
anyhow = "1.0"
axum = { version = "0.6", features = ["macros"] }
hyper = "0.14"
juniper = { version = "0.16.0-dev", path = "../juniper", features = ["expose-test-schema"] }
tokio = { version = "1.20", features = ["macros", "rt-multi-thread", "time"] }
tokio-stream = "0.1"
tokio-tungstenite = "0.20"
tracing = "0.1"
tracing-subscriber = "0.3"
urlencoding = "2.1"

[[example]]
name = "custom"
required-features = ["subscriptions"]

[[example]]
name = "simple"
required-features = ["subscriptions"]

[[test]]
name = "ws_test_suite"
required-features = ["subscriptions"]
Loading