From 12fd016dea963aa49e95f2a16c864f52ad822e39 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Mon, 8 Sep 2025 15:05:43 -0700 Subject: [PATCH 1/6] Remove actix-web integration --- Cargo.lock | 315 --------------------- Cargo.toml | 1 - integrations/actix-web/Cargo.toml | 38 --- integrations/actix-web/LICENSE-APACHE | 201 ------------- integrations/actix-web/LICENSE-MIT | 23 -- integrations/actix-web/src/handler.rs | 55 ---- integrations/actix-web/src/lib.rs | 12 - integrations/actix-web/src/request.rs | 240 ---------------- integrations/actix-web/src/subscription.rs | 303 -------------------- integrations/actix-web/tests/graphql.rs | 268 ------------------ integrations/actix-web/tests/test_utils.rs | 91 ------ 11 files changed, 1547 deletions(-) delete mode 100644 integrations/actix-web/Cargo.toml delete mode 100644 integrations/actix-web/LICENSE-APACHE delete mode 100644 integrations/actix-web/LICENSE-MIT delete mode 100644 integrations/actix-web/src/handler.rs delete mode 100644 integrations/actix-web/src/lib.rs delete mode 100644 integrations/actix-web/src/request.rs delete mode 100644 integrations/actix-web/src/subscription.rs delete mode 100644 integrations/actix-web/tests/graphql.rs delete mode 100644 integrations/actix-web/tests/test_utils.rs diff --git a/Cargo.lock b/Cargo.lock index a3d13c3b..531d8f9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,224 +12,6 @@ dependencies = [ "regex", ] -[[package]] -name = "actix" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de7fa236829ba0841304542f7614c42b80fca007455315c45c785ccfa873a85b" -dependencies = [ - "actix-macros", - "actix-rt", - "actix_derive", - "bitflags 2.9.4", - "bytes", - "crossbeam-channel", - "futures-core", - "futures-sink", - "futures-task", - "futures-util", - "log", - "once_cell", - "parking_lot", - "pin-project-lite 0.2.16", - "smallvec", - "tokio", - "tokio-util", -] - -[[package]] -name = "actix-codec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" -dependencies = [ - "bitflags 2.9.4", - "bytes", - "futures-core", - "futures-sink", - "memchr", - "pin-project-lite 0.2.16", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-http" -version = "3.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cceded2fb55f3c4b67068fa64962e2ca59614edc5b03167de9ff82ae803da0" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "base64 0.22.1", - "bitflags 2.9.4", - "bytes", - "bytestring", - "derive_more", - "encoding_rs", - "foldhash 0.1.5", - "futures-core", - "h2 0.3.27", - "http 0.2.12", - "httparse", - "httpdate", - "itoa", - "language-tags", - "local-channel", - "mime", - "percent-encoding", - "pin-project-lite 0.2.16", - "rand 0.9.2", - "sha1 0.10.6", - "smallvec", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn 2.0.106", -] - -[[package]] -name = "actix-router" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" -dependencies = [ - "bytestring", - "cfg-if", - "http 0.2.12", - "regex-lite", - "serde", - "tracing", -] - -[[package]] -name = "actix-rt" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63" -dependencies = [ - "actix-macros", - "futures-core", - "tokio", -] - -[[package]] -name = "actix-server" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" -dependencies = [ - "actix-rt", - "actix-service", - "actix-utils", - "futures-core", - "futures-util", - "mio", - "socket2 0.5.10", - "tokio", - "tracing", -] - -[[package]] -name = "actix-service" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" -dependencies = [ - "futures-core", - "pin-project-lite 0.2.16", -] - -[[package]] -name = "actix-utils" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" -dependencies = [ - "local-waker", - "pin-project-lite 0.2.16", -] - -[[package]] -name = "actix-web" -version = "4.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea" -dependencies = [ - "actix-codec", - "actix-http", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-utils", - "bytes", - "bytestring", - "cfg-if", - "derive_more", - "encoding_rs", - "foldhash 0.1.5", - "futures-core", - "futures-util", - "impl-more", - "itoa", - "language-tags", - "log", - "mime", - "once_cell", - "pin-project-lite 0.2.16", - "regex-lite", - "serde", - "serde_json", - "serde_urlencoded", - "smallvec", - "socket2 0.5.10", - "time 0.3.43", - "tracing", - "url", -] - -[[package]] -name = "actix-web-actors" -version = "4.3.1+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98c5300b38fd004fe7d2a964f9a90813fdbe8a81fed500587e78b1b71c6f980" -dependencies = [ - "actix", - "actix-codec", - "actix-http", - "actix-web", - "bytes", - "bytestring", - "futures-core", - "pin-project-lite 0.2.16", - "tokio", - "tokio-util", -] - -[[package]] -name = "actix_derive" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6ac1e58cded18cb28ddc17143c4dea5345b3ad575e14f32f66e4054a56eb271" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", -] - [[package]] name = "addr2line" version = "0.24.2" @@ -496,27 +278,6 @@ dependencies = [ "zxcvbn", ] -[[package]] -name = "async-graphql-actix-web" -version = "7.0.17" -dependencies = [ - "actix", - "actix-http", - "actix-rt", - "actix-web", - "actix-web-actors", - "async-channel 2.5.0", - "async-graphql", - "async-lock 3.4.1", - "async-stream", - "futures-channel", - "futures-util", - "serde", - "serde_cbor", - "serde_json", - "thiserror 1.0.69", -] - [[package]] name = "async-graphql-axum" version = "7.0.17" @@ -1098,15 +859,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bytestring" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" -dependencies = [ - "bytes", -] - [[package]] name = "cast" version = "0.3.0" @@ -1315,15 +1067,6 @@ dependencies = [ "itertools 0.13.0", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -1566,27 +1309,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "derive_more" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", - "unicode-xid", -] - [[package]] name = "devise" version = "0.4.2" @@ -2529,12 +2251,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "impl-more" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" - [[package]] name = "indexmap" version = "2.11.0" @@ -2677,12 +2393,6 @@ dependencies = [ "log", ] -[[package]] -name = "language-tags" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" - [[package]] name = "lazy_static" version = "1.5.0" @@ -2719,23 +2429,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" -[[package]] -name = "local-channel" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" -dependencies = [ - "futures-core", - "futures-sink", - "local-waker", -] - -[[package]] -name = "local-waker" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" - [[package]] name = "lock_api" version = "0.4.13" @@ -2832,7 +2525,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "log", "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.59.0", ] @@ -3530,12 +3222,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "regex-lite" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30" - [[package]] name = "regex-syntax" version = "0.8.6" @@ -4525,7 +4211,6 @@ dependencies = [ "io-uring", "libc", "mio", - "parking_lot", "pin-project-lite 0.2.16", "signal-hook-registry", "slab", diff --git a/Cargo.toml b/Cargo.toml index 4bb6af27..3a082f46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,7 +139,6 @@ members = [ "parser", "derive", "integrations/poem", - "integrations/actix-web", "integrations/rocket", "integrations/warp", "integrations/axum", diff --git a/integrations/actix-web/Cargo.toml b/integrations/actix-web/Cargo.toml deleted file mode 100644 index d88263a4..00000000 --- a/integrations/actix-web/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -authors = ["sunli ", "Koxiaet"] -categories = ["network-programming", "asynchronous"] -description = "async-graphql for actix-web" -documentation = "https://docs.rs/async-graphql-actix-web/" -edition = "2024" -homepage = "https://github.com/async-graphql/async-graphql" -keywords = ["futures", "async", "graphql"] -license = "MIT OR Apache-2.0" -name = "async-graphql-actix-web" -repository = "https://github.com/async-graphql/async-graphql" -version = "7.0.17" - -[dependencies] -async-graphql.workspace = true - -actix = "0.13.3" -actix-http = "3.6.0" -actix-web = { version = "4.5.1", default-features = false } -actix-web-actors = "4.3.0" -async-channel = "2.2.0" -futures-channel = "0.3.30" -futures-util = { version = "0.3.30", default-features = false } -serde_cbor = { version = "0.11.2", optional = true } -serde_json.workspace = true -thiserror.workspace = true -async-stream = "0.3.5" - -[features] -cbor = ["serde_cbor"] -http2 = ["actix-web/http2"] -default = ["http2"] - -[dev-dependencies] -async-graphql = { workspace = true, features = ["playground"] } -actix-rt = "2.9.0" -async-lock = "3.4.0" -serde = { version = "1", features = ["derive"] } diff --git a/integrations/actix-web/LICENSE-APACHE b/integrations/actix-web/LICENSE-APACHE deleted file mode 100644 index f8e5e5ea..00000000 --- a/integrations/actix-web/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/integrations/actix-web/LICENSE-MIT b/integrations/actix-web/LICENSE-MIT deleted file mode 100644 index 468cd79a..00000000 --- a/integrations/actix-web/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/integrations/actix-web/src/handler.rs b/integrations/actix-web/src/handler.rs deleted file mode 100644 index 70a05efa..00000000 --- a/integrations/actix-web/src/handler.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::time::Duration; - -use actix_http::StatusCode; -use actix_web::{Handler, HttpRequest, HttpResponse, Responder}; -use async_graphql::{ - Executor, - http::{create_multipart_mixed_stream, is_accept_multipart_mixed}, -}; -use futures_util::{FutureExt, StreamExt, future::LocalBoxFuture}; - -use crate::{GraphQLRequest, GraphQLResponse}; - -/// A GraphQL handler. -#[derive(Clone)] -pub struct GraphQL { - executor: E, -} - -impl GraphQL { - /// Create a GraphQL handler. - pub fn new(executor: E) -> Self { - Self { executor } - } -} - -impl Handler<(HttpRequest, GraphQLRequest)> for GraphQL { - type Output = HttpResponse; - type Future = LocalBoxFuture<'static, Self::Output>; - - fn call(&self, (http_req, graphql_req): (HttpRequest, GraphQLRequest)) -> Self::Future { - let executor = self.executor.clone(); - async move { - let is_accept_multipart_mixed = http_req - .headers() - .get("accept") - .and_then(|value| value.to_str().ok()) - .map(is_accept_multipart_mixed) - .unwrap_or_default(); - - if is_accept_multipart_mixed { - let stream = executor.execute_stream(graphql_req.0, None); - HttpResponse::build(StatusCode::OK) - .insert_header(("content-type", "multipart/mixed; boundary=graphql")) - .streaming( - create_multipart_mixed_stream(stream, Duration::from_secs(30)) - .map(Ok::<_, actix_web::Error>), - ) - } else { - GraphQLResponse(executor.execute(graphql_req.into_inner()).await.into()) - .respond_to(&http_req) - } - } - .boxed_local() - } -} diff --git a/integrations/actix-web/src/lib.rs b/integrations/actix-web/src/lib.rs deleted file mode 100644 index 8244e4fd..00000000 --- a/integrations/actix-web/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! Async-graphql integration with Actix-web -#![forbid(unsafe_code)] -#![allow(clippy::upper_case_acronyms)] -#![warn(missing_docs)] - -mod handler; -mod request; -mod subscription; - -pub use handler::GraphQL; -pub use request::{GraphQLBatchRequest, GraphQLRequest, GraphQLResponse}; -pub use subscription::GraphQLSubscription; diff --git a/integrations/actix-web/src/request.rs b/integrations/actix-web/src/request.rs deleted file mode 100644 index 736a747d..00000000 --- a/integrations/actix-web/src/request.rs +++ /dev/null @@ -1,240 +0,0 @@ -use std::{ - future::Future, - io::{self, ErrorKind}, - pin::Pin, - str::FromStr, -}; - -use actix_http::{ - body::BoxBody, - error::PayloadError, - header::{HeaderName, HeaderValue}, -}; -use actix_web::{ - Error, FromRequest, HttpRequest, HttpResponse, Responder, Result, - dev::Payload, - error::JsonPayloadError, - http, - http::{Method, StatusCode}, -}; -use async_graphql::{ParseRequestError, http::MultipartOptions}; -use futures_util::{ - StreamExt, TryStreamExt, - future::{self, FutureExt}, -}; - -/// Extractor for GraphQL request. -/// -/// `async_graphql::http::MultipartOptions` allows to configure extraction -/// process. -pub struct GraphQLRequest(pub async_graphql::Request); - -impl GraphQLRequest { - /// Unwraps the value to `async_graphql::Request`. - #[must_use] - pub fn into_inner(self) -> async_graphql::Request { - self.0 - } -} - -type BatchToRequestMapper = - fn(<::Future as Future>::Output) -> Result; - -impl FromRequest for GraphQLRequest { - type Error = Error; - type Future = future::Map<::Future, BatchToRequestMapper>; - - fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { - GraphQLBatchRequest::from_request(req, payload).map(|res| { - Ok(Self( - res?.0 - .into_single() - .map_err(actix_web::error::ErrorBadRequest)?, - )) - }) - } -} - -/// Extractor for GraphQL batch request. -/// -/// `async_graphql::http::MultipartOptions` allows to configure extraction -/// process. -pub struct GraphQLBatchRequest(pub async_graphql::BatchRequest); - -impl GraphQLBatchRequest { - /// Unwraps the value to `async_graphql::BatchRequest`. - #[must_use] - pub fn into_inner(self) -> async_graphql::BatchRequest { - self.0 - } -} - -impl FromRequest for GraphQLBatchRequest { - type Error = Error; - type Future = Pin>>>; - - fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { - let config = req - .app_data::() - .cloned() - .unwrap_or_default(); - - if req.method() == Method::GET { - let res = async_graphql::http::parse_query_string(req.query_string()) - .map_err(io::Error::other); - Box::pin(async move { Ok(Self(async_graphql::BatchRequest::Single(res?))) }) - } else if req.method() == Method::POST { - let content_type = req - .headers() - .get(http::header::CONTENT_TYPE) - .and_then(|value| value.to_str().ok()) - .map(|value| value.to_string()); - - let (tx, rx) = async_channel::bounded(16); - - // Payload is !Send so we create indirection with a channel - let mut payload = payload.take(); - actix::spawn(async move { - while let Some(item) = payload.next().await { - if tx.send(item).await.is_err() { - return; - } - } - }); - - Box::pin(async move { - Ok(GraphQLBatchRequest( - async_graphql::http::receive_batch_body( - content_type, - rx.map_err(|e| match e { - PayloadError::Incomplete(Some(e)) | PayloadError::Io(e) => e, - PayloadError::Incomplete(None) => { - io::Error::from(ErrorKind::UnexpectedEof) - } - PayloadError::EncodingCorrupted => io::Error::new( - ErrorKind::InvalidData, - "cannot decode content-encoding", - ), - PayloadError::Overflow => io::Error::new( - ErrorKind::InvalidData, - "a payload reached size limit", - ), - PayloadError::UnknownLength => { - io::Error::other("a payload length is unknown") - } - #[cfg(feature = "http2")] - PayloadError::Http2Payload(e) if e.is_io() => e.into_io().unwrap(), - #[cfg(feature = "http2")] - PayloadError::Http2Payload(e) => io::Error::other(e), - _ => io::Error::other(e), - }) - .into_async_read(), - config, - ) - .await - .map_err(|err| match err { - ParseRequestError::PayloadTooLarge => { - actix_web::error::ErrorPayloadTooLarge(err) - } - _ => actix_web::error::ErrorBadRequest(err), - })?, - )) - }) - } else { - Box::pin(async move { - Err(actix_web::error::ErrorMethodNotAllowed( - "GraphQL only supports GET and POST requests", - )) - }) - } - } -} - -/// Responder for a GraphQL response. -/// -/// This contains a batch response, but since regular responses are a type of -/// batch response it works for both. -pub struct GraphQLResponse(pub async_graphql::BatchResponse); - -impl From for GraphQLResponse { - fn from(resp: async_graphql::Response) -> Self { - Self(resp.into()) - } -} - -impl From for GraphQLResponse { - fn from(resp: async_graphql::BatchResponse) -> Self { - Self(resp) - } -} - -#[cfg(feature = "cbor")] -mod cbor { - use core::fmt; - - use actix_web::{ResponseError, http::StatusCode}; - - #[derive(Debug)] - pub struct Error(pub serde_cbor::Error); - impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } - } - impl ResponseError for Error { - fn status_code(&self) -> StatusCode { - StatusCode::INTERNAL_SERVER_ERROR - } - } -} - -impl Responder for GraphQLResponse { - type Body = BoxBody; - - fn respond_to(self, req: &HttpRequest) -> HttpResponse { - let mut builder = HttpResponse::build(StatusCode::OK); - - if self.0.is_ok() { - if let Some(cache_control) = self.0.cache_control().value() { - builder.append_header((http::header::CACHE_CONTROL, cache_control)); - } - } - - let accept = req - .headers() - .get(http::header::ACCEPT) - .and_then(|val| val.to_str().ok()); - let (ct, body) = match accept { - // optional cbor support - #[cfg(feature = "cbor")] - // this avoids copy-pasting the mime type - Some(ct @ "application/cbor") => ( - ct, - match serde_cbor::to_vec(&self.0) { - Ok(body) => body, - Err(e) => return HttpResponse::from_error(cbor::Error(e)), - }, - ), - _ => ( - "application/graphql-response+json", - match serde_json::to_vec(&self.0) { - Ok(body) => body, - Err(e) => return HttpResponse::from_error(JsonPayloadError::Serialize(e)), - }, - ), - }; - - let mut resp = builder.content_type(ct).body(body); - - for (name, value) in self.0.http_headers_iter() { - if let (Ok(name), Ok(value)) = ( - HeaderName::from_str(name.as_str()), - HeaderValue::from_bytes(value.as_bytes()), - ) { - resp.headers_mut().append(name, value); - } - } - - resp - } -} diff --git a/integrations/actix-web/src/subscription.rs b/integrations/actix-web/src/subscription.rs deleted file mode 100644 index 7e3ee621..00000000 --- a/integrations/actix-web/src/subscription.rs +++ /dev/null @@ -1,303 +0,0 @@ -use std::{ - future::Future, - str::FromStr, - time::{Duration, Instant}, -}; - -use actix::{ - Actor, ActorContext, ActorFutureExt, ActorStreamExt, AsyncContext, ContextFutureSpawner, - StreamHandler, WrapFuture, WrapStream, -}; -use actix_http::{error::PayloadError, ws}; -use actix_web::{Error, HttpRequest, HttpResponse, web::Bytes}; -use actix_web_actors::ws::{CloseReason, Message, ProtocolError, WebsocketContext}; -use async_graphql::{ - Data, Executor, Result, - http::{ - ALL_WEBSOCKET_PROTOCOLS, DefaultOnConnInitType, DefaultOnPingType, WebSocket, - WebSocketProtocols, WsMessage, default_on_connection_init, default_on_ping, - }, -}; -use futures_util::stream::Stream; - -const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); -const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); - -#[derive(thiserror::Error, Debug)] -#[error("failed to parse graphql protocol")] -pub struct ParseGraphQLProtocolError; - -/// A builder for websocket subscription actor. -pub struct GraphQLSubscription { - executor: E, - data: Data, - on_connection_init: OnInit, - on_ping: OnPing, - keepalive_timeout: Option, -} - -impl GraphQLSubscription { - /// Create a GraphQL subscription builder. - pub fn new(executor: E) -> Self { - Self { - executor, - data: Default::default(), - on_connection_init: default_on_connection_init, - on_ping: default_on_ping, - keepalive_timeout: None, - } - } -} - -impl GraphQLSubscription -where - E: Executor, - OnInit: FnOnce(serde_json::Value) -> OnInitFut + Unpin + Send + 'static, - OnInitFut: Future> + Send + 'static, - OnPing: FnOnce(Option<&Data>, Option) -> OnPingFut - + Clone - + Unpin - + Send - + 'static, - OnPingFut: Future>> + Send + 'static, -{ - /// Specify the initial subscription context data, usually you can get - /// something from the incoming request to create it. - #[must_use] - pub fn with_data(self, data: Data) -> Self { - Self { data, ..self } - } - - /// Specify a callback function to be called when the connection is - /// initialized. - /// - /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data - /// specified by [`with_data`]. - #[must_use] - pub fn on_connection_init(self, callback: F) -> GraphQLSubscription - where - F: FnOnce(serde_json::Value) -> R + Unpin + Send + 'static, - R: Future> + Send + 'static, - { - GraphQLSubscription { - executor: self.executor, - data: self.data, - on_connection_init: callback, - on_ping: self.on_ping, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Specify a ping callback function. - /// - /// This function if present, will be called with the data sent by the - /// client in the [`Ping` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#ping). - /// - /// The function should return the data to be sent in the [`Pong` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#pong). - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn on_ping(self, callback: F) -> GraphQLSubscription - where - F: FnOnce(Option<&Data>, Option) -> R + Send + Clone + 'static, - R: Future>> + Send + 'static, - { - GraphQLSubscription { - executor: self.executor, - data: self.data, - on_connection_init: self.on_connection_init, - on_ping: callback, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Sets a timeout for receiving an acknowledgement of the keep-alive ping. - /// - /// If the ping is not acknowledged within the timeout, the connection will - /// be closed. - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn keepalive_timeout(self, timeout: impl Into>) -> Self { - Self { - keepalive_timeout: timeout.into(), - ..self - } - } - - /// Start the subscription actor. - pub fn start(self, request: &HttpRequest, stream: S) -> Result - where - S: Stream> + 'static, - { - let protocol = request - .headers() - .get("sec-websocket-protocol") - .and_then(|value| value.to_str().ok()) - .and_then(|protocols| { - protocols - .split(',') - .find_map(|p| WebSocketProtocols::from_str(p.trim()).ok()) - }) - .ok_or_else(|| actix_web::error::ErrorBadRequest(ParseGraphQLProtocolError))?; - - let actor = GraphQLSubscriptionActor { - executor: self.executor, - data: Some(self.data), - protocol, - last_heartbeat: Instant::now(), - messages: None, - on_connection_init: Some(self.on_connection_init), - on_ping: self.on_ping, - keepalive_timeout: self.keepalive_timeout, - continuation: Vec::new(), - }; - - actix_web_actors::ws::WsResponseBuilder::new(actor, request, stream) - .protocols(&ALL_WEBSOCKET_PROTOCOLS) - .start() - } -} - -struct GraphQLSubscriptionActor { - executor: E, - data: Option, - protocol: WebSocketProtocols, - last_heartbeat: Instant, - messages: Option>>, - on_connection_init: Option, - on_ping: OnPing, - keepalive_timeout: Option, - continuation: Vec, -} - -impl GraphQLSubscriptionActor -where - E: Executor, - OnInit: FnOnce(serde_json::Value) -> OnInitFut + Unpin + Send + 'static, - OnInitFut: Future> + Send + 'static, - OnPing: FnOnce(Option<&Data>, Option) -> OnPingFut - + Clone - + Unpin - + Send - + 'static, - OnPingFut: Future>> + Send + 'static, -{ - fn send_heartbeats(&self, ctx: &mut WebsocketContext) { - ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| { - if Instant::now().duration_since(act.last_heartbeat) > CLIENT_TIMEOUT { - ctx.stop(); - } - ctx.ping(b""); - }); - } -} - -impl Actor for GraphQLSubscriptionActor -where - E: Executor, - OnInit: FnOnce(serde_json::Value) -> OnInitFut + Unpin + Send + 'static, - OnInitFut: Future> + Send + 'static, - OnPing: FnOnce(Option<&Data>, Option) -> OnPingFut - + Clone - + Unpin - + Send - + 'static, - OnPingFut: Future>> + Send + 'static, -{ - type Context = WebsocketContext; - - fn started(&mut self, ctx: &mut Self::Context) { - self.send_heartbeats(ctx); - - let (tx, rx) = async_channel::unbounded(); - - WebSocket::new(self.executor.clone(), rx, self.protocol) - .connection_data(self.data.take().unwrap()) - .on_connection_init(self.on_connection_init.take().unwrap()) - .on_ping(self.on_ping.clone()) - .keepalive_timeout(self.keepalive_timeout) - .into_actor(self) - .map(|response, _act, ctx| match response { - WsMessage::Text(text) => ctx.text(text), - WsMessage::Close(code, msg) => ctx.close(Some(CloseReason { - code: code.into(), - description: Some(msg), - })), - }) - .finish() - .spawn(ctx); - - self.messages = Some(tx); - } -} - -impl StreamHandler> - for GraphQLSubscriptionActor -where - E: Executor, - OnInit: FnOnce(serde_json::Value) -> OnInitFut + Unpin + Send + 'static, - OnInitFut: Future> + Send + 'static, - OnPing: FnOnce(Option<&Data>, Option) -> OnPingFut - + Clone - + Unpin - + Send - + 'static, - OnPingFut: Future>> + Send + 'static, -{ - fn handle(&mut self, msg: Result, ctx: &mut Self::Context) { - let msg = match msg { - Err(_) => { - ctx.stop(); - return; - } - Ok(msg) => msg, - }; - - let message = match msg { - Message::Ping(msg) => { - self.last_heartbeat = Instant::now(); - ctx.pong(&msg); - None - } - Message::Pong(_) => { - self.last_heartbeat = Instant::now(); - None - } - Message::Continuation(item) => match item { - ws::Item::FirstText(bytes) | ws::Item::FirstBinary(bytes) => { - self.continuation = bytes.to_vec(); - None - } - ws::Item::Continue(bytes) => { - self.continuation.extend_from_slice(&bytes); - None - } - ws::Item::Last(bytes) => { - self.continuation.extend_from_slice(&bytes); - Some(std::mem::take(&mut self.continuation)) - } - }, - Message::Text(s) => Some(s.into_bytes().to_vec()), - Message::Binary(bytes) => Some(bytes.to_vec()), - Message::Close(_) => { - ctx.stop(); - None - } - Message::Nop => None, - }; - - if let Some(message) = message { - let sender = self.messages.as_ref().unwrap().clone(); - - async move { sender.send(message).await } - .into_actor(self) - .map(|res, _actor, ctx| match res { - Ok(()) => {} - Err(_) => ctx.stop(), - }) - .spawn(ctx) - } - } -} diff --git a/integrations/actix-web/tests/graphql.rs b/integrations/actix-web/tests/graphql.rs deleted file mode 100644 index e408e14c..00000000 --- a/integrations/actix-web/tests/graphql.rs +++ /dev/null @@ -1,268 +0,0 @@ -use actix_http::Method; -use actix_web::{App, dev::Service, guard, test, web, web::Data}; -use async_graphql::*; -use serde_json::json; -use test_utils::*; - -mod test_utils; - -#[actix_rt::test] -async fn test_playground() { - let srv = test::init_service( - App::new().service( - web::resource("/") - .guard(guard::Get()) - .to(test_utils::gql_playgound), - ), - ) - .await; - let req = test::TestRequest::with_uri("/").to_request(); - let response = srv.call(req).await.unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert!( - std::str::from_utf8(&actix_web::body::to_bytes(body).await.unwrap()) - .unwrap() - .contains("graphql") - ); -} - -#[actix_rt::test] -async fn test_add() { - let srv = test::init_service( - App::new() - .app_data(Data::new(Schema::new( - AddQueryRoot, - EmptyMutation, - EmptySubscription, - ))) - .service( - web::resource("/") - .guard(guard::Post()) - .to(gql_handle_schema::), - ), - ) - .await; - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .set_payload(r#"{"query":"{ add(a: 10, b: 20) }"}"#) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert_eq!( - actix_web::body::to_bytes(body).await.unwrap(), - json!({"data": {"add": 30}}).to_string().into_bytes() - ); -} - -#[actix_rt::test] -async fn test_hello() { - let srv = test::init_service( - App::new() - .app_data(Data::new(Schema::new( - HelloQueryRoot, - EmptyMutation, - EmptySubscription, - ))) - .service( - web::resource("/") - .guard(guard::Post()) - .to(gql_handle_schema::), - ), - ) - .await; - - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .set_payload(r#"{"query":"{ hello }"}"#) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert_eq!( - actix_web::body::to_bytes(body).await.unwrap(), - json!({"data": {"hello": "Hello, world!"}}) - .to_string() - .into_bytes() - ); -} - -#[actix_rt::test] -async fn test_hello_header() { - let srv = test::init_service( - App::new() - .app_data(Data::new(Schema::new( - HelloQueryRoot, - EmptyMutation, - EmptySubscription, - ))) - .service( - web::resource("/") - .guard(guard::Post()) - .to(gql_handle_schema_with_header::), - ), - ) - .await; - - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .insert_header(("Name", "Foo")) - .set_payload(r#"{"query":"{ hello }"}"#) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert_eq!( - actix_web::body::to_bytes(body).await.unwrap(), - json!({"data": {"hello": "Hello, Foo!"}}) - .to_string() - .into_bytes() - ); -} - -#[actix_rt::test] -async fn test_count() { - let srv = test::init_service( - App::new() - .app_data(Data::new( - Schema::build(CountQueryRoot, CountMutation, EmptySubscription) - .data(Count::default()) - .finish(), - )) - .service( - web::resource("/") - .guard(guard::Post()) - .to(gql_handle_schema::), - ), - ) - .await; - - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .set_payload(r#"{"query":"{ count }"}"#) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert_eq!( - actix_web::body::to_bytes(body).await.unwrap(), - json!({"data": {"count": 0}}).to_string().into_bytes() - ); - - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .set_payload(r#"{"query":"mutation{ addCount(count: 10) }"}"#) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert_eq!( - actix_web::body::to_bytes(body).await.unwrap(), - json!({"data": {"addCount": 10}}).to_string().into_bytes(), - ); - - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .set_payload(r#"{"query":"mutation{ subtractCount(count: 2) }"}"#) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert_eq!( - actix_web::body::to_bytes(body).await.unwrap(), - json!({"data": {"subtractCount": 8}}) - .to_string() - .into_bytes() - ); - - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .set_payload(r#"{"query":"mutation{ subtractCount(count: 2) }"}"#) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - let body = response.into_body(); - assert_eq!( - actix_web::body::to_bytes(body).await.unwrap(), - json!({"data": {"subtractCount": 6}}) - .to_string() - .into_bytes() - ); -} - -#[cfg(feature = "cbor")] -#[actix_rt::test] -async fn test_cbor() { - let srv = test::init_service( - App::new() - .app_data(Data::new(Schema::new( - AddQueryRoot, - EmptyMutation, - EmptySubscription, - ))) - .service( - web::resource("/") - .guard(guard::Post()) - .to(gql_handle_schema::), - ), - ) - .await; - let response = srv - .call( - test::TestRequest::with_uri("/") - .method(Method::POST) - .set_payload(r#"{"query":"{ add(a: 10, b: 20) }"}"#) - .insert_header((actix_http::header::ACCEPT, "application/cbor")) - .to_request(), - ) - .await - .unwrap(); - assert!(response.status().is_success()); - #[derive(Debug, serde::Deserialize, PartialEq)] - struct Response { - data: ResponseInner, - } - #[derive(Debug, serde::Deserialize, PartialEq)] - struct ResponseInner { - add: i32, - } - let body = actix_web::body::to_bytes(response.into_body()) - .await - .unwrap(); - let response: Response = serde_cbor::from_slice(&body).unwrap(); - assert_eq!( - response, - Response { - data: ResponseInner { add: 30 } - } - ); -} diff --git a/integrations/actix-web/tests/test_utils.rs b/integrations/actix-web/tests/test_utils.rs deleted file mode 100644 index bbbfed00..00000000 --- a/integrations/actix-web/tests/test_utils.rs +++ /dev/null @@ -1,91 +0,0 @@ -use actix_web::{HttpRequest, HttpResponse, web}; -use async_graphql::{ - Context, EmptyMutation, EmptySubscription, Object, ObjectType, Schema, SubscriptionType, - http::{GraphQLPlaygroundConfig, playground_source}, -}; -use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse}; -use async_lock::Mutex; - -pub async fn gql_playgound() -> HttpResponse { - HttpResponse::Ok() - .content_type("text/html; charset=utf-8") - .body(playground_source(GraphQLPlaygroundConfig::new("/"))) -} - -pub(crate) struct AddQueryRoot; - -#[Object] -impl AddQueryRoot { - /// Returns the sum of a and b - async fn add(&self, a: i32, b: i32) -> i32 { - a + b - } -} - -struct Hello(String); - -pub(crate) struct HelloQueryRoot; - -#[Object] -impl HelloQueryRoot { - /// Returns hello - async fn hello<'a>(&self, ctx: &'a Context<'_>) -> String { - let name = ctx.data_opt::().map(|hello| hello.0.as_str()); - format!("Hello, {}!", name.unwrap_or("world")) - } -} - -pub type Count = Mutex; - -pub(crate) struct CountQueryRoot; - -#[Object] -impl CountQueryRoot { - async fn count<'a>(&self, ctx: &'a Context<'_>) -> i32 { - *ctx.data_unchecked::().lock().await - } -} - -pub(crate) struct CountMutation; - -#[Object] -impl CountMutation { - async fn add_count<'a>(&self, ctx: &'a Context<'_>, count: i32) -> i32 { - let mut guard_count = ctx.data_unchecked::().lock().await; - *guard_count += count; - *guard_count - } - - async fn subtract_count<'a>(&self, ctx: &'a Context<'_>, count: i32) -> i32 { - let mut guard_count = ctx.data_unchecked::().lock().await; - *guard_count -= count; - *guard_count - } -} - -pub async fn gql_handle_schema< - Q: ObjectType + 'static, - M: ObjectType + 'static, - S: SubscriptionType + 'static, ->( - schema: web::Data>, - req: GraphQLRequest, -) -> GraphQLResponse { - schema.execute(req.into_inner()).await.into() -} - -pub async fn gql_handle_schema_with_header( - schema: actix_web::web::Data>, - req: HttpRequest, - gql_request: GraphQLRequest, -) -> GraphQLResponse { - let name = req - .headers() - .get("Name") - .and_then(|value| value.to_str().map(|s| Hello(s.to_string())).ok()); - let mut request = gql_request.into_inner(); - if let Some(name) = name { - request = request.data(name); - } - schema.execute(request).await.into() -} From fc77d80c644c6366345bb895e27c95ef51103bc5 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Mon, 8 Sep 2025 15:05:58 -0700 Subject: [PATCH 2/6] Drop poem integration --- Cargo.lock | 168 +-------------- Cargo.toml | 1 - integrations/poem/Cargo.toml | 26 --- integrations/poem/LICENSE-APACHE | 201 ------------------ integrations/poem/LICENSE-MIT | 23 --- integrations/poem/src/extractor.rs | 87 -------- integrations/poem/src/lib.rs | 13 -- integrations/poem/src/query.rs | 74 ------- integrations/poem/src/response.rs | 50 ----- integrations/poem/src/subscription.rs | 283 -------------------------- 10 files changed, 3 insertions(+), 923 deletions(-) delete mode 100644 integrations/poem/Cargo.toml delete mode 100644 integrations/poem/LICENSE-APACHE delete mode 100644 integrations/poem/LICENSE-MIT delete mode 100644 integrations/poem/src/extractor.rs delete mode 100644 integrations/poem/src/lib.rs delete mode 100644 integrations/poem/src/query.rs delete mode 100644 integrations/poem/src/response.rs delete mode 100644 integrations/poem/src/subscription.rs diff --git a/Cargo.lock b/Cargo.lock index 531d8f9b..86a7514e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,21 +320,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-graphql-poem" -version = "7.0.17" -dependencies = [ - "async-graphql", - "futures-util", - "http 1.3.1", - "mime", - "poem", - "serde_json", - "tokio", - "tokio-stream", - "tokio-util", -] - [[package]] name = "async-graphql-rocket" version = "7.0.17" @@ -1776,25 +1761,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "h2" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.3.1", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "half" version = "1.8.3" @@ -1857,28 +1823,13 @@ checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ "base64 0.21.7", "bytes", - "headers-core 0.2.0", + "headers-core", "http 0.2.12", "httpdate", "mime", "sha1 0.10.6", ] -[[package]] -name = "headers" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" -dependencies = [ - "base64 0.22.1", - "bytes", - "headers-core 0.3.0", - "http 1.3.1", - "httpdate", - "mime", - "sha1 0.10.6", -] - [[package]] name = "headers-core" version = "0.2.0" @@ -1888,15 +1839,6 @@ dependencies = [ "http 0.2.12", ] -[[package]] -name = "headers-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" -dependencies = [ - "http 1.3.1", -] - [[package]] name = "heck" version = "0.5.0" @@ -2053,7 +1995,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.27", + "h2", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -2077,7 +2019,6 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.12", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -2548,18 +2489,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nom" version = "8.0.0" @@ -2874,53 +2803,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "poem" -version = "3.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f977080932c87287147dca052951c3e2696f8759863f6b4e4c0c9ffe7a4cc8b" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-util", - "headers 0.4.1", - "http 1.3.1", - "http-body-util", - "hyper 1.7.0", - "hyper-util", - "mime", - "nix", - "parking_lot", - "percent-encoding", - "pin-project-lite 0.2.16", - "poem-derive", - "regex", - "rfc7239", - "serde", - "serde_json", - "serde_urlencoded", - "smallvec", - "sync_wrapper", - "thiserror 2.0.16", - "tokio", - "tokio-tungstenite 0.27.0", - "tokio-util", - "tracing", - "wildmatch", -] - -[[package]] -name = "poem-derive" -version = "3.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056e2fea6de1cb240ffe23cfc4fc370b629f8be83b5f27e16b7acd5231a72de4" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.106", -] - [[package]] name = "polling" version = "2.8.0" @@ -3262,15 +3144,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "rfc7239" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a82f1d1e38e9a85bb58ffcfadf22ed6f2c94e8cd8581ec2b0f80a2a6858350f" -dependencies = [ - "uncased", -] - [[package]] name = "rocket" version = "0.5.1" @@ -4265,18 +4138,6 @@ dependencies = [ "tungstenite 0.26.2", ] -[[package]] -name = "tokio-tungstenite" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.27.0", -] - [[package]] name = "tokio-util" version = "0.7.16" @@ -4514,23 +4375,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "tungstenite" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" -dependencies = [ - "bytes", - "data-encoding", - "http 1.3.1", - "httparse", - "log", - "rand 0.9.2", - "sha1 0.10.6", - "thiserror 2.0.16", - "utf-8", -] - [[package]] name = "typeid" version = "1.0.3" @@ -4714,7 +4558,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "headers 0.3.9", + "headers", "http 0.2.12", "hyper 0.14.32", "log", @@ -4836,12 +4680,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "wildmatch" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd" - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 3a082f46..f1aa0203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,7 +138,6 @@ members = [ "value", "parser", "derive", - "integrations/poem", "integrations/rocket", "integrations/warp", "integrations/axum", diff --git a/integrations/poem/Cargo.toml b/integrations/poem/Cargo.toml deleted file mode 100644 index 2fd3df2d..00000000 --- a/integrations/poem/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -authors = ["sunli "] -categories = ["network-programming", "asynchronous"] -description = "async-graphql for poem" -documentation = "https://docs.rs/async-graphql-poem/" -edition = "2024" -homepage = "https://github.com/async-graphql/async-graphql" -keywords = ["futures", "async", "graphql", "poem"] -license = "MIT OR Apache-2.0" -name = "async-graphql-poem" -repository = "https://github.com/async-graphql/async-graphql" -version = "7.0.17" - -[dependencies] -async-graphql.workspace = true - -futures-util = { workspace = true, default-features = false } -poem = { version = "3.1.10", features = ["websocket"] } -serde_json.workspace = true -tokio-util = { workspace = true, default-features = false, features = [ - "compat", -] } -mime = "0.3.17" -tokio = { version = "1.36.0", features = ["time"] } -tokio-stream = "0.1.15" -http = "1.1.0" diff --git a/integrations/poem/LICENSE-APACHE b/integrations/poem/LICENSE-APACHE deleted file mode 100644 index f8e5e5ea..00000000 --- a/integrations/poem/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/integrations/poem/LICENSE-MIT b/integrations/poem/LICENSE-MIT deleted file mode 100644 index 468cd79a..00000000 --- a/integrations/poem/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/integrations/poem/src/extractor.rs b/integrations/poem/src/extractor.rs deleted file mode 100644 index 29104914..00000000 --- a/integrations/poem/src/extractor.rs +++ /dev/null @@ -1,87 +0,0 @@ -use async_graphql::http::MultipartOptions; -use poem::{ - FromRequest, Request, RequestBody, Result, - error::BadRequest, - http::{Method, header}, -}; -use tokio_util::compat::TokioAsyncReadCompatExt; - -/// An extractor for GraphQL request. -/// -/// You can just use the extractor as in the example below, but I would -/// recommend using the [`GraphQL`](crate::GraphQL) endpoint because it is -/// easier to integrate. -/// -/// # Example -/// -/// ``` -/// use async_graphql::{EmptyMutation, EmptySubscription, Object, Schema}; -/// use async_graphql_poem::GraphQLRequest; -/// use poem::{ -/// EndpointExt, Route, handler, -/// middleware::AddData, -/// post, -/// web::{Data, Json}, -/// }; -/// -/// struct Query; -/// -/// #[Object] -/// impl Query { -/// async fn value(&self) -> i32 { -/// 100 -/// } -/// } -/// -/// type MySchema = Schema; -/// -/// #[handler] -/// async fn index(req: GraphQLRequest, schema: Data<&MySchema>) -> Json { -/// Json(schema.execute(req.0).await) -/// } -/// -/// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); -/// let app = Route::new().at("/", post(index.with(AddData::new(schema)))); -/// ``` -pub struct GraphQLRequest(pub async_graphql::Request); - -impl<'a> FromRequest<'a> for GraphQLRequest { - async fn from_request(req: &'a Request, body: &mut RequestBody) -> Result { - Ok(GraphQLRequest( - GraphQLBatchRequest::from_request(req, body) - .await? - .0 - .into_single() - .map_err(BadRequest)?, - )) - } -} - -/// An extractor for GraphQL batch request. -pub struct GraphQLBatchRequest(pub async_graphql::BatchRequest); - -impl<'a> FromRequest<'a> for GraphQLBatchRequest { - async fn from_request(req: &'a Request, body: &mut RequestBody) -> Result { - if req.method() == Method::GET { - let req = - async_graphql::http::parse_query_string(req.uri().query().unwrap_or_default()) - .map_err(BadRequest)?; - Ok(Self(async_graphql::BatchRequest::Single(req))) - } else { - let content_type = req - .headers() - .get(header::CONTENT_TYPE) - .and_then(|value| value.to_str().ok()) - .map(ToString::to_string); - Ok(Self( - async_graphql::http::receive_batch_body( - content_type, - body.take()?.into_async_read().compat(), - MultipartOptions::default(), - ) - .await - .map_err(BadRequest)?, - )) - } - } -} diff --git a/integrations/poem/src/lib.rs b/integrations/poem/src/lib.rs deleted file mode 100644 index 67094ba8..00000000 --- a/integrations/poem/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Async-graphql integration with Poem -#![forbid(unsafe_code)] -#![warn(missing_docs)] - -mod extractor; -mod query; -mod response; -mod subscription; - -pub use extractor::{GraphQLBatchRequest, GraphQLRequest}; -pub use query::GraphQL; -pub use response::{GraphQLBatchResponse, GraphQLResponse}; -pub use subscription::{GraphQLProtocol, GraphQLSubscription, GraphQLWebSocket}; diff --git a/integrations/poem/src/query.rs b/integrations/poem/src/query.rs deleted file mode 100644 index 68807c9d..00000000 --- a/integrations/poem/src/query.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::time::Duration; - -use async_graphql::{ - Executor, - http::{create_multipart_mixed_stream, is_accept_multipart_mixed}, -}; -use futures_util::StreamExt; -use poem::{Body, Endpoint, FromRequest, IntoResponse, Request, Response, Result}; - -use crate::{GraphQLBatchRequest, GraphQLBatchResponse, GraphQLRequest}; - -/// A GraphQL query endpoint. -/// -/// # Example -/// -/// ``` -/// use async_graphql::{EmptyMutation, EmptySubscription, Object, Schema}; -/// use async_graphql_poem::GraphQL; -/// use poem::{Route, post}; -/// -/// struct Query; -/// -/// #[Object] -/// impl Query { -/// async fn value(&self) -> i32 { -/// 100 -/// } -/// } -/// -/// type MySchema = Schema; -/// -/// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); -/// let app = Route::new().at("/", post(GraphQL::new(schema))); -/// ``` -pub struct GraphQL { - executor: E, -} - -impl GraphQL { - /// Create a GraphQL endpoint. - pub fn new(executor: E) -> Self { - Self { executor } - } -} - -impl Endpoint for GraphQL -where - E: Executor, -{ - type Output = Response; - - async fn call(&self, req: Request) -> Result { - let is_accept_multipart_mixed = req - .header("accept") - .map(is_accept_multipart_mixed) - .unwrap_or_default(); - - if is_accept_multipart_mixed { - let (req, mut body) = req.split(); - let req = GraphQLRequest::from_request(&req, &mut body).await?; - let stream = self.executor.execute_stream(req.0, None); - Ok(Response::builder() - .header("content-type", "multipart/mixed; boundary=graphql") - .body(Body::from_bytes_stream( - create_multipart_mixed_stream(stream, Duration::from_secs(30)) - .map(Ok::<_, std::io::Error>), - ))) - } else { - let (req, mut body) = req.split(); - let req = GraphQLBatchRequest::from_request(&req, &mut body).await?; - Ok(GraphQLBatchResponse(self.executor.execute_batch(req.0).await).into_response()) - } - } -} diff --git a/integrations/poem/src/response.rs b/integrations/poem/src/response.rs deleted file mode 100644 index d731f59b..00000000 --- a/integrations/poem/src/response.rs +++ /dev/null @@ -1,50 +0,0 @@ -use std::str::FromStr; - -use http::{HeaderName, HeaderValue}; -use poem::{IntoResponse, Response, web::Json}; - -/// Response for `async_graphql::Request`. -pub struct GraphQLResponse(pub async_graphql::Response); - -impl From for GraphQLResponse { - fn from(resp: async_graphql::Response) -> Self { - Self(resp) - } -} - -impl IntoResponse for GraphQLResponse { - fn into_response(self) -> Response { - GraphQLBatchResponse(self.0.into()).into_response() - } -} - -/// Response for `async_graphql::BatchRequest`. -pub struct GraphQLBatchResponse(pub async_graphql::BatchResponse); - -impl From for GraphQLBatchResponse { - fn from(resp: async_graphql::BatchResponse) -> Self { - Self(resp) - } -} - -impl IntoResponse for GraphQLBatchResponse { - fn into_response(self) -> Response { - let mut resp = Json(&self.0).into_response(); - - if self.0.is_ok() { - if let Some(cache_control) = self.0.cache_control().value() { - if let Ok(value) = cache_control.try_into() { - resp.headers_mut().insert("cache-control", value); - } - } - } - - resp.headers_mut() - .extend(self.0.http_headers().iter().filter_map(|(name, value)| { - HeaderName::from_str(name.as_str()) - .ok() - .zip(HeaderValue::from_bytes(value.as_bytes()).ok()) - })); - resp - } -} diff --git a/integrations/poem/src/subscription.rs b/integrations/poem/src/subscription.rs deleted file mode 100644 index c2ef7f01..00000000 --- a/integrations/poem/src/subscription.rs +++ /dev/null @@ -1,283 +0,0 @@ -use std::{io::Error as IoError, str::FromStr, time::Duration}; - -use async_graphql::{ - Data, Executor, - http::{ - ALL_WEBSOCKET_PROTOCOLS, DefaultOnConnInitType, DefaultOnPingType, WebSocketProtocols, - WsMessage, default_on_connection_init, default_on_ping, - }, -}; -use futures_util::{ - Future, Sink, SinkExt, Stream, StreamExt, - future::{self}, - stream::{SplitSink, SplitStream}, -}; -use poem::{ - Endpoint, Error, FromRequest, IntoResponse, Request, RequestBody, Response, Result, - http::StatusCode, - web::websocket::{Message, WebSocket}, -}; - -/// A GraphQL protocol extractor. -/// -/// It extract GraphQL protocol from `SEC_WEBSOCKET_PROTOCOL` header. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct GraphQLProtocol(pub WebSocketProtocols); - -impl<'a> FromRequest<'a> for GraphQLProtocol { - async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result { - req.headers() - .get(http::header::SEC_WEBSOCKET_PROTOCOL) - .and_then(|value| value.to_str().ok()) - .and_then(|protocols| { - protocols - .split(',') - .find_map(|p| WebSocketProtocols::from_str(p.trim()).ok()) - }) - .map(Self) - .ok_or_else(|| Error::from_status(StatusCode::BAD_REQUEST)) - } -} - -/// A GraphQL subscription endpoint. -/// -/// # Example -/// -/// ``` -/// use async_graphql::{EmptyMutation, Object, Schema, Subscription}; -/// use async_graphql_poem::GraphQLSubscription; -/// use futures_util::{Stream, stream}; -/// use poem::{Route, get}; -/// -/// struct Query; -/// -/// #[Object] -/// impl Query { -/// async fn value(&self) -> i32 { -/// 100 -/// } -/// } -/// -/// struct Subscription; -/// -/// #[Subscription] -/// impl Subscription { -/// async fn values(&self) -> impl Stream { -/// stream::iter(vec![1, 2, 3, 4, 5]) -/// } -/// } -/// -/// type MySchema = Schema; -/// -/// let schema = Schema::new(Query, EmptyMutation, Subscription); -/// let app = Route::new().at("/ws", get(GraphQLSubscription::new(schema))); -/// ``` -pub struct GraphQLSubscription { - executor: E, -} - -impl GraphQLSubscription { - /// Create a GraphQL subscription endpoint. - pub fn new(executor: E) -> Self { - Self { executor } - } -} - -impl Endpoint for GraphQLSubscription -where - E: Executor, -{ - type Output = Response; - - async fn call(&self, req: Request) -> Result { - let (req, mut body) = req.split(); - let websocket = WebSocket::from_request(&req, &mut body).await?; - let protocol = GraphQLProtocol::from_request(&req, &mut body).await?; - let executor = self.executor.clone(); - - let resp = websocket - .protocols(ALL_WEBSOCKET_PROTOCOLS) - .on_upgrade(move |stream| GraphQLWebSocket::new(stream, executor, protocol).serve()) - .into_response(); - Ok(resp) - } -} - -/// A Websocket connection for GraphQL subscription. -pub struct GraphQLWebSocket { - sink: Sink, - stream: Stream, - executor: E, - data: Data, - on_connection_init: OnConnInit, - on_ping: OnPing, - protocol: GraphQLProtocol, - keepalive_timeout: Option, -} - -impl - GraphQLWebSocket< - SplitSink, - SplitStream, - E, - DefaultOnConnInitType, - DefaultOnPingType, - > -where - S: Stream> + Sink, - E: Executor, -{ - /// Create a [`GraphQLWebSocket`] object. - pub fn new(stream: S, executor: E, protocol: GraphQLProtocol) -> Self { - let (sink, stream) = stream.split(); - GraphQLWebSocket::new_with_pair(sink, stream, executor, protocol) - } -} - -impl GraphQLWebSocket -where - Sink: futures_util::sink::Sink, - Stream: futures_util::stream::Stream>, - E: Executor, -{ - /// Create a [`GraphQLWebSocket`] object with sink and stream objects. - pub fn new_with_pair( - sink: Sink, - stream: Stream, - executor: E, - protocol: GraphQLProtocol, - ) -> Self { - GraphQLWebSocket { - sink, - stream, - executor, - data: Data::default(), - on_connection_init: default_on_connection_init, - on_ping: default_on_ping, - protocol, - keepalive_timeout: None, - } - } -} - -impl - GraphQLWebSocket -where - Sink: futures_util::sink::Sink, - Stream: futures_util::stream::Stream>, - E: Executor, - OnConnInit: FnOnce(serde_json::Value) -> OnConnInitFut + Send + 'static, - OnConnInitFut: Future> + Send + 'static, - OnPing: FnOnce(Option<&Data>, Option) -> OnPingFut + Clone + Send + 'static, - OnPingFut: Future>> + Send + 'static, -{ - /// Specify the initial subscription context data, usually you can get - /// something from the incoming request to create it. - #[must_use] - pub fn with_data(self, data: Data) -> Self { - Self { data, ..self } - } - - /// Specify a callback function to be called when the connection is - /// initialized. - /// - /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data - /// specified by [`with_data`]. - #[must_use] - pub fn on_connection_init( - self, - callback: F, - ) -> GraphQLWebSocket - where - F: FnOnce(serde_json::Value) -> R + Send + 'static, - R: Future> + Send + 'static, - { - GraphQLWebSocket { - sink: self.sink, - stream: self.stream, - executor: self.executor, - data: self.data, - on_connection_init: callback, - on_ping: self.on_ping, - protocol: self.protocol, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Specify a ping callback function. - /// - /// This function if present, will be called with the data sent by the - /// client in the [`Ping` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#ping). - /// - /// The function should return the data to be sent in the [`Pong` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#pong). - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn on_ping(self, callback: F) -> GraphQLWebSocket - where - F: FnOnce(Option<&Data>, Option) -> R + Clone + Send + 'static, - R: Future>> + Send + 'static, - { - GraphQLWebSocket { - sink: self.sink, - stream: self.stream, - executor: self.executor, - data: self.data, - on_connection_init: self.on_connection_init, - on_ping: callback, - protocol: self.protocol, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Sets a timeout for receiving an acknowledgement of the keep-alive ping. - /// - /// If the ping is not acknowledged within the timeout, the connection will - /// be closed. - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn keepalive_timeout(self, timeout: impl Into>) -> Self { - Self { - keepalive_timeout: timeout.into(), - ..self - } - } - - /// Processing subscription requests. - pub async fn serve(self) { - let stream = self - .stream - .take_while(|res| future::ready(res.is_ok())) - .map(Result::unwrap) - .filter_map(|msg| { - if msg.is_text() || msg.is_binary() { - future::ready(Some(msg)) - } else { - future::ready(None) - } - }) - .map(Message::into_bytes); - - let stream = - async_graphql::http::WebSocket::new(self.executor.clone(), stream, self.protocol.0) - .connection_data(self.data) - .on_connection_init(self.on_connection_init) - .on_ping(self.on_ping.clone()) - .keepalive_timeout(self.keepalive_timeout) - .map(|msg| match msg { - WsMessage::Text(text) => Message::text(text), - WsMessage::Close(code, status) => Message::close_with(code, status), - }); - - let sink = self.sink; - futures_util::pin_mut!(stream, sink); - - while let Some(item) = stream.next().await { - if sink.send(item).await.is_err() { - break; - } - } - } -} From 5c8459a9fc11e22c6973ee065af40167cff27983 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Mon, 8 Sep 2025 15:06:25 -0700 Subject: [PATCH 3/6] Drop rocket integration --- Cargo.lock | 493 +---------------------------- Cargo.toml | 1 - integrations/rocket/Cargo.toml | 22 -- integrations/rocket/LICENSE-APACHE | 201 ------------ integrations/rocket/LICENSE-MIT | 23 -- integrations/rocket/src/lib.rs | 216 ------------- 6 files changed, 1 insertion(+), 955 deletions(-) delete mode 100644 integrations/rocket/Cargo.toml delete mode 100644 integrations/rocket/LICENSE-APACHE delete mode 100644 integrations/rocket/LICENSE-MIT delete mode 100644 integrations/rocket/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 86a7514e..99363cc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,17 +320,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-graphql-rocket" -version = "7.0.17" -dependencies = [ - "async-graphql", - "rocket", - "serde", - "serde_json", - "tokio-util", -] - [[package]] name = "async-graphql-tide" version = "7.0.17" @@ -572,21 +561,6 @@ dependencies = [ "tungstenite 0.13.0", ] -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - -[[package]] -name = "atomic" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" -dependencies = [ - "bytemuck", -] - [[package]] name = "atomic-waker" version = "1.1.2" @@ -708,12 +682,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "binascii" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" - [[package]] name = "bit-set" version = "0.5.3" @@ -823,12 +791,6 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" -[[package]] -name = "bytemuck" -version = "1.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" - [[package]] name = "byteorder" version = "1.5.0" @@ -986,17 +948,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time 0.3.43", - "version_check", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1294,39 +1245,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "devise" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d" -dependencies = [ - "devise_codegen", - "devise_core", -] - -[[package]] -name = "devise_codegen" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867" -dependencies = [ - "devise_core", - "quote", -] - -[[package]] -name = "devise_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7" -dependencies = [ - "bitflags 2.9.4", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.106", -] - [[package]] name = "digest" version = "0.9.0" @@ -1471,20 +1389,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "figment" -version = "0.10.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" -dependencies = [ - "atomic 0.6.1", - "pear", - "serde", - "toml", - "uncased", - "version_check", -] - [[package]] name = "find-msvc-tools" version = "0.1.1" @@ -1647,19 +1551,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1724,12 +1615,6 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - [[package]] name = "gloo-timers" version = "0.3.0" @@ -1961,7 +1846,7 @@ dependencies = [ "async-channel 1.9.0", "async-std", "base64 0.13.1", - "cookie 0.14.4", + "cookie", "futures-lite 1.13.0", "infer", "pin-project-lite 0.2.16", @@ -2209,12 +2094,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" -[[package]] -name = "inlinable_string" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" - [[package]] name = "input_buffer" version = "0.4.0" @@ -2271,17 +2150,6 @@ dependencies = [ "serde", ] -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi 0.5.2", - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "iso8601" version = "0.6.3" @@ -2370,16 +2238,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" -[[package]] -name = "lock_api" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.28" @@ -2389,21 +2247,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "serde", - "serde_json", - "tracing", - "tracing-subscriber", -] - [[package]] name = "lru" version = "0.16.0" @@ -2413,15 +2256,6 @@ dependencies = [ "hashbrown 0.15.5", ] -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - [[package]] name = "matchit" version = "0.8.4" @@ -2484,8 +2318,6 @@ dependencies = [ "memchr", "mime", "spin", - "tokio", - "tokio-util", "version_check", ] @@ -2498,15 +2330,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "nu-ansi-term" -version = "0.50.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "num-bigint" version = "0.4.6" @@ -2556,16 +2379,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi 0.5.2", - "libc", -] - [[package]] name = "object" version = "0.36.7" @@ -2612,52 +2425,6 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "pear" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", -] - -[[package]] -name = "pear_codegen" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.106", -] - [[package]] name = "percent-encoding" version = "2.3.2" @@ -2892,19 +2659,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", - "version_check", - "yansi", -] - [[package]] name = "quick-error" version = "2.0.1" @@ -3052,15 +2806,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" -dependencies = [ - "bitflags 2.9.4", -] - [[package]] name = "ref-cast" version = "1.0.24" @@ -3144,87 +2889,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "rocket" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f" -dependencies = [ - "async-stream", - "async-trait", - "atomic 0.5.3", - "binascii", - "bytes", - "either", - "figment", - "futures", - "indexmap", - "log", - "memchr", - "multer", - "num_cpus", - "parking_lot", - "pin-project-lite 0.2.16", - "rand 0.8.5", - "ref-cast", - "rocket_codegen", - "rocket_http", - "serde", - "state", - "tempfile", - "time 0.3.43", - "tokio", - "tokio-stream", - "tokio-util", - "ubyte", - "version_check", - "yansi", -] - -[[package]] -name = "rocket_codegen" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" -dependencies = [ - "devise", - "glob", - "indexmap", - "proc-macro2", - "quote", - "rocket_http", - "syn 2.0.106", - "unicode-xid", - "version_check", -] - -[[package]] -name = "rocket_http" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e274915a20ee3065f611c044bd63c40757396b6dbc057d6046aec27f14f882b9" -dependencies = [ - "cookie 0.18.1", - "either", - "futures", - "http 0.2.12", - "hyper 0.14.32", - "indexmap", - "log", - "memchr", - "pear", - "percent-encoding", - "pin-project-lite 0.2.16", - "ref-cast", - "serde", - "smallvec", - "stable-pattern", - "state", - "time 0.3.43", - "tokio", - "uncased", -] - [[package]] name = "route-recognizer" version = "0.2.0" @@ -3335,12 +2999,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "secrecy" version = "0.10.3" @@ -3458,15 +3116,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3542,15 +3191,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - [[package]] name = "shlex" version = "1.3.0" @@ -3630,15 +3270,6 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -[[package]] -name = "stable-pattern" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" -dependencies = [ - "memchr", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -3654,15 +3285,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "state" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" -dependencies = [ - "loom", -] - [[package]] name = "static_assertions_next" version = "1.1.2" @@ -3937,15 +3559,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - [[package]] name = "tide" version = "0.16.0" @@ -4085,7 +3698,6 @@ dependencies = [ "libc", "mio", "pin-project-lite 0.2.16", - "signal-hook-registry", "slab", "socket2 0.6.0", "tokio-macros", @@ -4152,26 +3764,11 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - [[package]] name = "toml_datetime" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] [[package]] name = "toml_edit" @@ -4180,19 +3777,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", - "serde", - "serde_spanned", "toml_datetime", - "toml_write", "winnow", ] -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - [[package]] name = "tower" version = "0.5.2" @@ -4269,7 +3857,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", - "valuable", ] [[package]] @@ -4284,35 +3871,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - [[package]] name = "try-lock" version = "0.2.5" @@ -4387,31 +3945,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" -[[package]] -name = "ubyte" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" -dependencies = [ - "serde", -] - [[package]] name = "ucd-trie" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" -[[package]] -name = "uncased" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" -dependencies = [ - "serde", - "version_check", -] - [[package]] name = "unicase" version = "2.8.1" @@ -4424,12 +3963,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "universal-hash" version = "0.4.1" @@ -4476,12 +4009,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - [[package]] name = "value-bag" version = "1.11.1" @@ -4711,15 +4238,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-core" version = "0.61.2" @@ -5046,15 +4564,6 @@ dependencies = [ "tap", ] -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" -dependencies = [ - "is-terminal", -] - [[package]] name = "yoke" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index f1aa0203..324d8741 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,7 +138,6 @@ members = [ "value", "parser", "derive", - "integrations/rocket", "integrations/warp", "integrations/axum", "integrations/tide", diff --git a/integrations/rocket/Cargo.toml b/integrations/rocket/Cargo.toml deleted file mode 100644 index b89bf34b..00000000 --- a/integrations/rocket/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -authors = ["Daniel Wiesenberg "] -categories = ["network-programming", "asynchronous"] -description = "async-graphql for Rocket.rs" -documentation = "https://docs.rs/async-graphql/" -edition = "2024" -homepage = "https://github.com/async-graphql/async-graphql" -keywords = ["futures", "async", "graphql", "rocket"] -license = "MIT OR Apache-2.0" -name = "async-graphql-rocket" -repository = "https://github.com/async-graphql/async-graphql" -version = "7.0.17" - -[dependencies] -async-graphql.workspace = true - -rocket = { version = "0.5.0", default-features = false } -serde.workspace = true -serde_json.workspace = true -tokio-util = { workspace = true, default-features = false, features = [ - "compat", -] } diff --git a/integrations/rocket/LICENSE-APACHE b/integrations/rocket/LICENSE-APACHE deleted file mode 100644 index f8e5e5ea..00000000 --- a/integrations/rocket/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/integrations/rocket/LICENSE-MIT b/integrations/rocket/LICENSE-MIT deleted file mode 100644 index 468cd79a..00000000 --- a/integrations/rocket/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/integrations/rocket/src/lib.rs b/integrations/rocket/src/lib.rs deleted file mode 100644 index d2a69080..00000000 --- a/integrations/rocket/src/lib.rs +++ /dev/null @@ -1,216 +0,0 @@ -//! Async-graphql integration with Rocket. -//! -//! Note: This integrates with the unreleased version 0.5 of Rocket, and so -//! breaking changes in both this library and Rocket are to be expected. -//! -//! To configure options for sending and receiving multipart requests, add your -//! instance of `MultipartOptions` to the state managed by Rocket -//! (`.manage(your_multipart_options)`). -//! -//! **[Full Example]()** - -#![warn(missing_docs)] -#![forbid(unsafe_code)] -#![allow(clippy::blocks_in_conditions)] - -use core::any::Any; -use std::io::Cursor; - -use async_graphql::{Executor, ParseRequestError, http::MultipartOptions}; -use rocket::{ - data::{self, Data, FromData, ToByteUnit}, - form::FromForm, - http::{ContentType, Header, Status}, - response::{self, Responder}, -}; -use tokio_util::compat::TokioAsyncReadCompatExt; - -/// A batch request which can be extracted from a request's body. -/// -/// # Examples -/// -/// ```ignore -/// #[rocket::post("/graphql", data = "", format = "application/json", rank = 1)] -/// async fn graphql_request(schema: State<'_, ExampleSchema>, request: BatchRequest) -> Response { -/// request.execute(&schema).await -/// } -/// ``` -#[derive(Debug)] -pub struct GraphQLBatchRequest(pub async_graphql::BatchRequest); - -impl GraphQLBatchRequest { - /// Shortcut method to execute the request on the executor. - pub async fn execute(self, executor: &E) -> GraphQLResponse - where - E: Executor, - { - GraphQLResponse(executor.execute_batch(self.0).await) - } -} - -#[rocket::async_trait] -impl<'r> FromData<'r> for GraphQLBatchRequest { - type Error = ParseRequestError; - - async fn from_data(req: &'r rocket::Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> { - let opts: MultipartOptions = req.rocket().state().copied().unwrap_or_default(); - - let request = async_graphql::http::receive_batch_body( - req.headers().get_one("Content-Type"), - data.open( - req.limits() - .get("graphql") - .unwrap_or_else(|| 128.kibibytes()), - ) - .compat(), - opts, - ) - .await; - - match request { - Ok(request) => data::Outcome::Success(Self(request)), - Err(e) => data::Outcome::Error(( - match e { - ParseRequestError::PayloadTooLarge => Status::PayloadTooLarge, - _ => Status::BadRequest, - }, - e, - )), - } - } -} - -/// A GraphQL request which can be extracted from the request's body. -/// -/// # Examples -/// -/// ```ignore -/// #[rocket::post("/graphql", data = "", format = "application/json", rank = 2)] -/// async fn graphql_request(schema: State<'_, ExampleSchema>, request: Request) -> Result { -/// request.execute(&schema).await -/// } -/// ``` -#[derive(Debug)] -pub struct GraphQLRequest(pub async_graphql::Request); - -impl GraphQLRequest { - /// Shortcut method to execute the request on the schema. - pub async fn execute(self, executor: &E) -> GraphQLResponse - where - E: Executor, - { - GraphQLResponse(executor.execute(self.0).await.into()) - } - - /// Insert some data for this request. - #[must_use] - pub fn data(mut self, data: D) -> Self { - self.0.data.insert(data); - self - } -} - -impl From for GraphQLRequest { - fn from(query: GraphQLQuery) -> Self { - let mut request = async_graphql::Request::new(query.query); - - if let Some(operation_name) = query.operation_name { - request = request.operation_name(operation_name); - } - - if let Some(variables) = query.variables { - let value = serde_json::from_str(&variables).unwrap_or_default(); - let variables = async_graphql::Variables::from_json(value); - request = request.variables(variables); - } - - GraphQLRequest(request) - } -} - -/// A GraphQL request which can be extracted from a query string. -/// -/// # Examples -/// -/// ```ignore -/// #[rocket::get("/graphql?")] -/// async fn graphql_query(schema: State<'_, ExampleSchema>, query: Query) -> Result { -/// query.execute(&schema).await -/// } -/// ``` -#[derive(FromForm, Debug)] -pub struct GraphQLQuery { - query: String, - #[field(name = "operationName")] - operation_name: Option, - variables: Option, -} - -impl GraphQLQuery { - /// Shortcut method to execute the request on the schema. - pub async fn execute(self, executor: &E) -> GraphQLResponse - where - E: Executor, - { - let request: GraphQLRequest = self.into(); - request.execute(executor).await - } -} - -#[rocket::async_trait] -impl<'r> FromData<'r> for GraphQLRequest { - type Error = ParseRequestError; - - async fn from_data(req: &'r rocket::Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> { - GraphQLBatchRequest::from_data(req, data) - .await - .and_then(|request| match request.0.into_single() { - Ok(single) => data::Outcome::Success(Self(single)), - Err(e) => data::Outcome::Error((Status::BadRequest, e)), - }) - } -} - -/// Wrapper around `async-graphql::Response` that is a Rocket responder so it -/// can be returned from a routing function in Rocket. -/// -/// It contains a `BatchResponse` but since a response is a type of batch -/// response it works for both. -#[derive(Debug)] -pub struct GraphQLResponse(pub async_graphql::BatchResponse); - -impl From for GraphQLResponse { - fn from(batch: async_graphql::BatchResponse) -> Self { - Self(batch) - } -} -impl From for GraphQLResponse { - fn from(res: async_graphql::Response) -> Self { - Self(res.into()) - } -} - -impl<'r> Responder<'r, 'static> for GraphQLResponse { - fn respond_to(self, _: &'r rocket::Request<'_>) -> response::Result<'static> { - let body = serde_json::to_string(&self.0).unwrap(); - - let mut response = rocket::Response::new(); - response.set_header(ContentType::new("application", "json")); - - if self.0.is_ok() { - if let Some(cache_control) = self.0.cache_control().value() { - response.set_header(Header::new("cache-control", cache_control)); - } - } - - for (name, value) in self.0.http_headers_iter() { - if let Ok(value) = value.to_str() { - response.adjoin_header(Header::new(name.as_str().to_string(), value.to_string())); - } - } - - response.set_sized_body(body.len(), Cursor::new(body)); - - Ok(response) - } -} From 8c29b0f15963f1363b089895244acca4eb9156cf Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Mon, 8 Sep 2025 15:06:35 -0700 Subject: [PATCH 4/6] Drop warp integration --- Cargo.lock | 202 +--------------- Cargo.toml | 1 - integrations/warp/Cargo.toml | 29 --- integrations/warp/LICENSE-APACHE | 201 ---------------- integrations/warp/LICENSE-MIT | 23 -- integrations/warp/src/batch_request.rs | 99 -------- integrations/warp/src/error.rs | 66 ----- integrations/warp/src/lib.rs | 15 -- integrations/warp/src/request.rs | 87 ------- integrations/warp/src/subscription.rs | 319 ------------------------- 10 files changed, 11 insertions(+), 1031 deletions(-) delete mode 100644 integrations/warp/Cargo.toml delete mode 100644 integrations/warp/LICENSE-APACHE delete mode 100644 integrations/warp/LICENSE-MIT delete mode 100644 integrations/warp/src/batch_request.rs delete mode 100644 integrations/warp/src/error.rs delete mode 100644 integrations/warp/src/lib.rs delete mode 100644 integrations/warp/src/request.rs delete mode 100644 integrations/warp/src/subscription.rs diff --git a/Cargo.lock b/Cargo.lock index 99363cc2..444ace49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -344,18 +344,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-graphql-warp" -version = "7.0.17" -dependencies = [ - "async-graphql", - "async-stream", - "futures-util", - "serde_json", - "tokio", - "warp", -] - [[package]] name = "async-h1" version = "2.3.4" @@ -585,9 +573,9 @@ dependencies = [ "form_urlencoded", "futures-util", "http 1.3.1", - "http-body 1.0.1", + "http-body", "http-body-util", - "hyper 1.7.0", + "hyper", "hyper-util", "itoa", "matchit", @@ -603,7 +591,7 @@ dependencies = [ "sha1 0.10.6", "sync_wrapper", "tokio", - "tokio-tungstenite 0.26.2", + "tokio-tungstenite", "tower", "tower-layer", "tower-service", @@ -619,7 +607,7 @@ dependencies = [ "bytes", "futures-core", "http 1.3.1", - "http-body 1.0.1", + "http-body", "http-body-util", "mime", "pin-project-lite 0.2.16", @@ -657,12 +645,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -1627,25 +1609,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "h2" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "half" version = "1.8.3" @@ -1700,30 +1663,6 @@ dependencies = [ "foldhash 0.2.0", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http 0.2.12", - "httpdate", - "mime", - "sha1 0.10.6", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.12", -] - [[package]] name = "heck" version = "0.5.0" @@ -1790,17 +1729,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite 0.2.16", -] - [[package]] name = "http-body" version = "1.0.1" @@ -1820,7 +1748,7 @@ dependencies = [ "bytes", "futures-core", "http 1.3.1", - "http-body 1.0.1", + "http-body", "pin-project-lite 0.2.16", ] @@ -1870,30 +1798,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite 0.2.16", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.7.0" @@ -1905,7 +1809,7 @@ dependencies = [ "futures-channel", "futures-core", "http 1.3.1", - "http-body 1.0.1", + "http-body", "httparse", "httpdate", "itoa", @@ -1928,8 +1832,8 @@ dependencies = [ "futures-core", "futures-util", "http 1.3.1", - "http-body 1.0.1", - "hyper 1.7.0", + "http-body", + "hyper", "ipnet", "libc", "percent-encoding", @@ -2866,9 +2770,9 @@ dependencies = [ "futures-core", "futures-util", "http 1.3.1", - "http-body 1.0.1", + "http-body", "http-body-util", - "hyper 1.7.0", + "hyper", "hyper-util", "js-sys", "log", @@ -2993,12 +2897,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "secrecy" version = "0.10.3" @@ -3244,16 +3142,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "socket2" version = "0.6.0" @@ -3726,18 +3614,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.21.0", -] - [[package]] name = "tokio-tungstenite" version = "0.26.2" @@ -3807,7 +3683,7 @@ dependencies = [ "bytes", "futures-util", "http 1.3.1", - "http-body 1.0.1", + "http-body", "iri-string", "pin-project-lite 0.2.16", "tower", @@ -3897,25 +3773,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.3.1", - "httparse", - "log", - "rand 0.8.5", - "sha1 0.10.6", - "thiserror 1.0.69", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.26.2" @@ -4076,34 +3933,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "warp" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "headers", - "http 0.2.12", - "hyper 0.14.32", - "log", - "mime", - "mime_guess", - "percent-encoding", - "pin-project", - "scoped-tls", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-tungstenite 0.21.0", - "tokio-util", - "tower-service", - "tracing", -] - [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -4312,15 +4141,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index 324d8741..fd75de4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,7 +138,6 @@ members = [ "value", "parser", "derive", - "integrations/warp", "integrations/axum", "integrations/tide", ] diff --git a/integrations/warp/Cargo.toml b/integrations/warp/Cargo.toml deleted file mode 100644 index 3b06a954..00000000 --- a/integrations/warp/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -authors = ["sunli ", "Koxiaet"] -categories = ["network-programming", "asynchronous"] -description = "async-graphql for warp" -documentation = "https://docs.rs/async-graphql-warp/" -edition = "2024" -homepage = "https://github.com/async-graphql/async-graphql" -keywords = ["futures", "async", "graphql"] -license = "MIT OR Apache-2.0" -name = "async-graphql-warp" -repository = "https://github.com/async-graphql/async-graphql" -version = "7.0.17" - -[dependencies] -async-graphql.workspace = true - -futures-util = { workspace = true, default-features = false, features = [ - "sink", -] } -serde_json.workspace = true -warp = { version = "0.3.6", default-features = false, features = ["websocket"] } - -[dev-dependencies] -async-stream = "0.3.5" -tokio = { version = "1.36.0", default-features = false, features = [ - "macros", - "rt-multi-thread", - "time", -] } diff --git a/integrations/warp/LICENSE-APACHE b/integrations/warp/LICENSE-APACHE deleted file mode 100644 index f8e5e5ea..00000000 --- a/integrations/warp/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/integrations/warp/LICENSE-MIT b/integrations/warp/LICENSE-MIT deleted file mode 100644 index 468cd79a..00000000 --- a/integrations/warp/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/integrations/warp/src/batch_request.rs b/integrations/warp/src/batch_request.rs deleted file mode 100644 index 15ac3441..00000000 --- a/integrations/warp/src/batch_request.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::{io, str::FromStr}; - -use async_graphql::{BatchRequest, Executor, http::MultipartOptions}; -use futures_util::TryStreamExt; -use warp::{ - Buf, Filter, Rejection, Reply, - http::{HeaderName, HeaderValue}, - reply::Response as WarpResponse, -}; - -use crate::GraphQLBadRequest; - -/// GraphQL batch request filter -/// -/// It outputs a tuple containing the `async_graphql::Executor` and -/// `async_graphql::BatchRequest`. -pub fn graphql_batch( - executor: E, -) -> impl Filter + Clone -where - E: Executor, -{ - graphql_batch_opts(executor, Default::default()) -} - -/// Similar to graphql_batch, but you can set the options with -/// :`async_graphql::MultipartOptions`. -pub fn graphql_batch_opts( - executor: E, - opts: MultipartOptions, -) -> impl Filter + Clone -where - E: Executor, -{ - warp::any() - .and(warp::get().and(warp::filters::query::raw()).and_then( - |query_string: String| async move { - async_graphql::http::parse_query_string(&query_string) - .map(Into::into) - .map_err(|e| warp::reject::custom(GraphQLBadRequest(e))) - }, - )) - .or(warp::post() - .and(warp::header::optional::("content-type")) - .and(warp::body::stream()) - .and_then(move |content_type, body| async move { - async_graphql::http::receive_batch_body( - content_type, - TryStreamExt::map_err(body, io::Error::other) - .map_ok(|mut buf| { - let remaining = Buf::remaining(&buf); - Buf::copy_to_bytes(&mut buf, remaining) - }) - .into_async_read(), - opts, - ) - .await - .map_err(|e| warp::reject::custom(GraphQLBadRequest(e))) - })) - .unify() - .map(move |res| (executor.clone(), res)) -} - -/// Reply for `async_graphql::BatchRequest`. -#[derive(Debug)] -pub struct GraphQLBatchResponse(pub async_graphql::BatchResponse); - -impl From for GraphQLBatchResponse { - fn from(resp: async_graphql::BatchResponse) -> Self { - GraphQLBatchResponse(resp) - } -} - -impl Reply for GraphQLBatchResponse { - fn into_response(self) -> WarpResponse { - let mut resp = warp::reply::with_header( - warp::reply::json(&self.0), - "content-type", - "application/json", - ) - .into_response(); - - if self.0.is_ok() { - if let Some(cache_control) = self.0.cache_control().value() { - if let Ok(value) = cache_control.try_into() { - resp.headers_mut().insert("cache-control", value); - } - } - } - - resp.headers_mut() - .extend(self.0.http_headers().iter().filter_map(|(name, value)| { - HeaderName::from_str(name.as_str()) - .ok() - .zip(HeaderValue::from_bytes(value.as_bytes()).ok()) - })); - resp - } -} diff --git a/integrations/warp/src/error.rs b/integrations/warp/src/error.rs deleted file mode 100644 index 590d0c7e..00000000 --- a/integrations/warp/src/error.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::{ - error::Error, - fmt::{self, Display, Formatter}, -}; - -use async_graphql::ParseRequestError; -use warp::{ - Reply, - http::{Response, StatusCode}, - hyper::Body, - reject::Reject, -}; - -/// Bad request error. -/// -/// It's a wrapper of `async_graphql::ParseRequestError`. It is also a `Reply` - -/// by default it just returns a response containing the error message in plain -/// text. -#[derive(Debug)] -pub struct GraphQLBadRequest(pub ParseRequestError); - -impl GraphQLBadRequest { - /// Get the appropriate status code of the error. - #[must_use] - pub fn status(&self) -> StatusCode { - match self.0 { - ParseRequestError::PayloadTooLarge => StatusCode::PAYLOAD_TOO_LARGE, - _ => StatusCode::BAD_REQUEST, - } - } -} - -impl Display for GraphQLBadRequest { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -impl Error for GraphQLBadRequest { - fn source(&self) -> Option<&(dyn Error + 'static)> { - Some(&self.0) - } -} - -impl Reject for GraphQLBadRequest {} - -impl Reply for GraphQLBadRequest { - fn into_response(self) -> Response { - Response::builder() - .status(self.status()) - .body(Body::from(self.0.to_string())) - .unwrap() - } -} - -impl From for GraphQLBadRequest { - fn from(e: ParseRequestError) -> Self { - Self(e) - } -} - -impl From for ParseRequestError { - fn from(e: GraphQLBadRequest) -> Self { - e.0 - } -} diff --git a/integrations/warp/src/lib.rs b/integrations/warp/src/lib.rs deleted file mode 100644 index edf5f3ab..00000000 --- a/integrations/warp/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Async-graphql integration with Warp - -#![allow(clippy::type_complexity)] -#![forbid(unsafe_code)] -#![warn(missing_docs)] - -mod batch_request; -mod error; -mod request; -mod subscription; - -pub use batch_request::{GraphQLBatchResponse, graphql_batch, graphql_batch_opts}; -pub use error::GraphQLBadRequest; -pub use request::{GraphQLResponse, graphql, graphql_opts}; -pub use subscription::{GraphQLWebSocket, graphql_protocol, graphql_subscription}; diff --git a/integrations/warp/src/request.rs b/integrations/warp/src/request.rs deleted file mode 100644 index c10934e6..00000000 --- a/integrations/warp/src/request.rs +++ /dev/null @@ -1,87 +0,0 @@ -use async_graphql::{BatchRequest, Executor, Request, http::MultipartOptions}; -use warp::{Filter, Rejection, Reply, reply::Response as WarpResponse}; - -use crate::{GraphQLBadRequest, GraphQLBatchResponse, graphql_batch_opts}; - -/// GraphQL request filter -/// -/// It outputs a tuple containing the `async_graphql::Schema` and -/// `async_graphql::Request`. -/// -/// # Examples -/// -/// *[Full Example]()* -/// -/// ```no_run -/// use std::convert::Infallible; -/// -/// use async_graphql::*; -/// use async_graphql_warp::*; -/// use warp::Filter; -/// -/// struct QueryRoot; -/// -/// #[Object] -/// impl QueryRoot { -/// async fn value(&self, ctx: &Context<'_>) -> i32 { -/// unimplemented!() -/// } -/// } -/// -/// type MySchema = Schema; -/// -/// # tokio::runtime::Runtime::new().unwrap().block_on(async { -/// let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription); -/// let filter = async_graphql_warp::graphql(schema).and_then( -/// |(schema, request): (MySchema, async_graphql::Request)| async move { -/// Ok::<_, Infallible>(async_graphql_warp::GraphQLResponse::from( -/// schema.execute(request).await, -/// )) -/// }, -/// ); -/// warp::serve(filter).run(([0, 0, 0, 0], 8000)).await; -/// # }); -/// ``` -pub fn graphql( - executor: E, -) -> impl Filter + Clone -where - E: Executor, -{ - graphql_opts(executor, Default::default()) -} - -/// Similar to graphql, but you can set the options -/// `async_graphql::MultipartOptions`. -pub fn graphql_opts( - executor: E, - opts: MultipartOptions, -) -> impl Filter + Clone -where - E: Executor, -{ - graphql_batch_opts(executor, opts).and_then(|(schema, batch): (_, BatchRequest)| async move { - >::Ok(( - schema, - batch - .into_single() - .map_err(|e| warp::reject::custom(GraphQLBadRequest(e)))?, - )) - }) -} - -/// Reply for `async_graphql::Request`. -#[derive(Debug)] -pub struct GraphQLResponse(pub async_graphql::Response); - -impl From for GraphQLResponse { - fn from(resp: async_graphql::Response) -> Self { - GraphQLResponse(resp) - } -} - -impl Reply for GraphQLResponse { - fn into_response(self) -> WarpResponse { - GraphQLBatchResponse(self.0.into()).into_response() - } -} diff --git a/integrations/warp/src/subscription.rs b/integrations/warp/src/subscription.rs deleted file mode 100644 index 10b3ff95..00000000 --- a/integrations/warp/src/subscription.rs +++ /dev/null @@ -1,319 +0,0 @@ -use std::{future::Future, str::FromStr, time::Duration}; - -use async_graphql::{ - Data, Executor, Result, - http::{ - DefaultOnConnInitType, DefaultOnPingType, WebSocketProtocols, WsMessage, - default_on_connection_init, default_on_ping, - }, -}; -use futures_util::{ - Sink, Stream, StreamExt, future, - stream::{SplitSink, SplitStream}, -}; -use warp::{Error, Filter, Rejection, Reply, filters::ws, ws::Message}; - -/// GraphQL subscription filter -/// -/// # Examples -/// -/// ```no_run -/// use std::time::Duration; -/// -/// use async_graphql::*; -/// use async_graphql_warp::*; -/// use futures_util::stream::{Stream, StreamExt}; -/// use warp::Filter; -/// -/// struct QueryRoot; -/// -/// #[Object] -/// impl QueryRoot { -/// async fn value(&self) -> i32 { -/// // A GraphQL Object type must define one or more fields. -/// 100 -/// } -/// } -/// -/// struct SubscriptionRoot; -/// -/// #[Subscription] -/// impl SubscriptionRoot { -/// async fn tick(&self) -> impl Stream { -/// async_stream::stream! { -/// let mut interval = tokio::time::interval(Duration::from_secs(1)); -/// loop { -/// let n = interval.tick().await; -/// yield format!("{}", n.elapsed().as_secs_f32()); -/// } -/// } -/// } -/// } -/// -/// # tokio::runtime::Runtime::new().unwrap().block_on(async { -/// let schema = Schema::new(QueryRoot, EmptyMutation, SubscriptionRoot); -/// let filter = -/// async_graphql_warp::graphql_subscription(schema).or(warp::any().map(|| "Hello, World!")); -/// warp::serve(filter).run(([0, 0, 0, 0], 8000)).await; -/// # }); -/// ``` -pub fn graphql_subscription( - executor: E, -) -> impl Filter + Clone -where - E: Executor, -{ - warp::ws() - .and(graphql_protocol()) - .map(move |ws: ws::Ws, protocol| { - let executor = executor.clone(); - - let reply = ws.on_upgrade(move |socket| { - GraphQLWebSocket::new(socket, executor, protocol).serve() - }); - - warp::reply::with_header( - reply, - "Sec-WebSocket-Protocol", - protocol.sec_websocket_protocol(), - ) - }) -} - -/// Create a `Filter` that parse [WebSocketProtocols] from -/// `sec-websocket-protocol` header. -pub fn graphql_protocol() -> impl Filter + Clone -{ - warp::header::optional::("sec-websocket-protocol").map(|protocols: Option| { - protocols - .and_then(|protocols| { - protocols - .split(',') - .find_map(|p| WebSocketProtocols::from_str(p.trim()).ok()) - }) - .unwrap_or(WebSocketProtocols::SubscriptionsTransportWS) - }) -} - -/// A Websocket connection for GraphQL subscription. -/// -/// # Examples -/// -/// ```no_run -/// use std::time::Duration; -/// -/// use async_graphql::*; -/// use async_graphql_warp::*; -/// use futures_util::stream::{Stream, StreamExt}; -/// use warp::{Filter, ws}; -/// -/// struct QueryRoot; -/// -/// #[Object] -/// impl QueryRoot { -/// async fn value(&self) -> i32 { -/// // A GraphQL Object type must define one or more fields. -/// 100 -/// } -/// } -/// -/// struct SubscriptionRoot; -/// -/// #[Subscription] -/// impl SubscriptionRoot { -/// async fn tick(&self) -> impl Stream { -/// async_stream::stream! { -/// let mut interval = tokio::time::interval(Duration::from_secs(1)); -/// loop { -/// let n = interval.tick().await; -/// yield format!("{}", n.elapsed().as_secs_f32()); -/// } -/// } -/// } -/// } -/// -/// # tokio::runtime::Runtime::new().unwrap().block_on(async { -/// let schema = Schema::new(QueryRoot, EmptyMutation, SubscriptionRoot); -/// -/// let filter = warp::ws() -/// .and(graphql_protocol()) -/// .map(move |ws: ws::Ws, protocol| { -/// let schema = schema.clone(); -/// -/// let reply = ws -/// .on_upgrade(move |socket| GraphQLWebSocket::new(socket, schema, protocol).serve()); -/// -/// warp::reply::with_header( -/// reply, -/// "Sec-WebSocket-Protocol", -/// protocol.sec_websocket_protocol(), -/// ) -/// }); -/// -/// warp::serve(filter).run(([0, 0, 0, 0], 8000)).await; -/// # }); -/// ``` -pub struct GraphQLWebSocket { - sink: Sink, - stream: Stream, - protocol: WebSocketProtocols, - executor: E, - data: Data, - on_init: OnInit, - on_ping: OnPing, - keepalive_timeout: Option, -} - -impl - GraphQLWebSocket< - SplitSink, - SplitStream, - E, - DefaultOnConnInitType, - DefaultOnPingType, - > -where - S: Stream> + Sink, - E: Executor, -{ - /// Create a [`GraphQLWebSocket`] object. - pub fn new(socket: S, executor: E, protocol: WebSocketProtocols) -> Self { - let (sink, stream) = socket.split(); - GraphQLWebSocket::new_with_pair(sink, stream, executor, protocol) - } -} - -impl GraphQLWebSocket -where - Sink: futures_util::sink::Sink, - Stream: futures_util::stream::Stream>, - E: Executor, -{ - /// Create a [`GraphQLWebSocket`] object with sink and stream objects. - pub fn new_with_pair( - sink: Sink, - stream: Stream, - executor: E, - protocol: WebSocketProtocols, - ) -> Self { - GraphQLWebSocket { - sink, - stream, - protocol, - executor, - data: Data::default(), - on_init: default_on_connection_init, - on_ping: default_on_ping, - keepalive_timeout: None, - } - } -} - -impl - GraphQLWebSocket -where - Sink: futures_util::sink::Sink, - Stream: futures_util::stream::Stream>, - E: Executor, - OnConnInit: FnOnce(serde_json::Value) -> OnConnInitFut + Send + 'static, - OnConnInitFut: Future> + Send + 'static, - OnPing: FnOnce(Option<&Data>, Option) -> OnPingFut + Clone + Send + 'static, - OnPingFut: Future>> + Send + 'static, -{ - /// Specify the initial subscription context data, usually you can get - /// something from the incoming request to create it. - #[must_use] - pub fn with_data(self, data: Data) -> Self { - Self { data, ..self } - } - - /// Specify a callback function to be called when the connection is - /// initialized. - /// - /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data - /// specified by [`with_data`]. - #[must_use] - pub fn on_connection_init( - self, - callback: F, - ) -> GraphQLWebSocket - where - F: FnOnce(serde_json::Value) -> R + Send + 'static, - R: Future> + Send + 'static, - { - GraphQLWebSocket { - sink: self.sink, - stream: self.stream, - executor: self.executor, - data: self.data, - on_init: callback, - on_ping: self.on_ping, - protocol: self.protocol, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Specify a ping callback function. - /// - /// This function if present, will be called with the data sent by the - /// client in the [`Ping` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#ping). - /// - /// The function should return the data to be sent in the [`Pong` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#pong). - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn on_ping(self, callback: F) -> GraphQLWebSocket - where - F: FnOnce(Option<&Data>, Option) -> R + Send + Clone + 'static, - R: Future>> + Send + 'static, - { - GraphQLWebSocket { - sink: self.sink, - stream: self.stream, - executor: self.executor, - data: self.data, - on_init: self.on_init, - on_ping: callback, - protocol: self.protocol, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Sets a timeout for receiving an acknowledgement of the keep-alive ping. - /// - /// If the ping is not acknowledged within the timeout, the connection will - /// be closed. - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn keepalive_timeout(self, timeout: impl Into>) -> Self { - Self { - keepalive_timeout: timeout.into(), - ..self - } - } - - /// Processing subscription requests. - pub async fn serve(self) { - let stream = self - .stream - .take_while(|msg| future::ready(msg.is_ok())) - .map(Result::unwrap) - .filter(|msg| future::ready(msg.is_text() || msg.is_binary())) - .map(ws::Message::into_bytes); - - let _ = async_graphql::http::WebSocket::new(self.executor.clone(), stream, self.protocol) - .connection_data(self.data) - .on_connection_init(self.on_init) - .on_ping(self.on_ping) - .keepalive_timeout(self.keepalive_timeout) - .map(|msg| match msg { - WsMessage::Text(text) => ws::Message::text(text), - WsMessage::Close(code, status) => ws::Message::close_with(code, status), - }) - .map(Ok) - .forward(self.sink) - .await; - } -} From 14353ecded67ba6ac0d018b2795ca989e923a61d Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Mon, 8 Sep 2025 15:06:47 -0700 Subject: [PATCH 5/6] Drop tide integration --- Cargo.lock | 1499 +------------------------ Cargo.toml | 1 - integrations/tide/Cargo.toml | 37 - integrations/tide/LICENSE-APACHE | 201 ---- integrations/tide/LICENSE-MIT | 23 - integrations/tide/src/lib.rs | 176 --- integrations/tide/src/subscription.rs | 169 --- integrations/tide/tests/graphql.rs | 219 ---- integrations/tide/tests/test_utils.rs | 11 - 9 files changed, 59 insertions(+), 2277 deletions(-) delete mode 100644 integrations/tide/Cargo.toml delete mode 100644 integrations/tide/LICENSE-APACHE delete mode 100644 integrations/tide/LICENSE-MIT delete mode 100644 integrations/tide/src/lib.rs delete mode 100644 integrations/tide/src/subscription.rs delete mode 100644 integrations/tide/tests/graphql.rs delete mode 100644 integrations/tide/tests/test_utils.rs diff --git a/Cargo.lock b/Cargo.lock index 444ace49..827b3f54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,60 +27,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "aead" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" -dependencies = [ - "generic-array", -] - -[[package]] -name = "aes" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" -dependencies = [ - "aes-soft", - "aesni", - "cipher", -] - -[[package]] -name = "aes-gcm" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "aes-soft" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" -dependencies = [ - "cipher", - "opaque-debug", -] - -[[package]] -name = "aesni" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" -dependencies = [ - "cipher", - "opaque-debug", -] - [[package]] name = "ahash" version = "0.8.12" @@ -130,12 +76,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" -[[package]] -name = "anyhow" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" - [[package]] name = "arrayvec" version = "0.7.6" @@ -148,27 +88,6 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - [[package]] name = "async-channel" version = "2.5.0" @@ -178,47 +97,7 @@ dependencies = [ "concurrent-queue", "event-listener-strategy", "futures-core", - "pin-project-lite 0.2.16", -] - -[[package]] -name = "async-dup" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2886ab563af5038f79ec016dd7b87947ed138b794e8dd64992962c9cca0411" -dependencies = [ - "async-lock 3.4.1", - "futures-io", -] - -[[package]] -name = "async-executor" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand 2.3.0", - "futures-lite 2.6.1", - "pin-project-lite 0.2.16", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.5.0", - "async-executor", - "async-io 2.5.0", - "async-lock 3.4.1", - "blocking", - "futures-lite 2.6.1", - "once_cell", - "tokio", + "pin-project-lite", ] [[package]] @@ -230,7 +109,7 @@ dependencies = [ "async-graphql-value", "async-stream", "async-trait", - "base64 0.22.1", + "base64", "bigdecimal", "blocking", "bson", @@ -245,7 +124,7 @@ dependencies = [ "futures-util", "handlebars", "hashbrown 0.16.0", - "http 1.3.1", + "http", "indexmap", "iso8601", "log", @@ -254,7 +133,7 @@ dependencies = [ "multer", "num-traits", "opentelemetry", - "pin-project-lite 0.2.16", + "pin-project-lite", "regex", "rust_decimal", "schemars", @@ -263,13 +142,13 @@ dependencies = [ "serde_cbor", "serde_json", "serde_urlencoded", - "sha2 0.10.9", + "sha2", "slab", "smol_str", "static_assertions_next", "tempfile", "thiserror 1.0.69", - "time 0.3.43", + "time", "tokio", "tracing", "tracing-futures", @@ -320,20 +199,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-graphql-tide" -version = "7.0.17" -dependencies = [ - "async-graphql", - "async-std", - "async-trait", - "futures-util", - "reqwest", - "serde_json", - "tide", - "tide-websockets", -] - [[package]] name = "async-graphql-value" version = "7.0.17" @@ -344,159 +209,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-h1" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1d1dae8cb2c4258a79d6ed088b7fb9b4763bf4e9b22d040779761e046a2971" -dependencies = [ - "async-channel 1.9.0", - "async-dup", - "async-global-executor", - "async-io 1.13.0", - "futures-lite 1.13.0", - "http-types", - "httparse", - "log", - "pin-project", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.28", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" -dependencies = [ - "async-lock 3.4.1", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite 2.6.1", - "parking", - "polling 3.10.0", - "rustix 1.0.8", - "slab", - "windows-sys 0.60.2", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-lock" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" -dependencies = [ - "event-listener 5.4.1", - "event-listener-strategy", - "pin-project-lite 0.2.16", -] - -[[package]] -name = "async-process" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00" -dependencies = [ - "async-channel 2.5.0", - "async-io 2.5.0", - "async-lock 3.4.1", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener 5.4.1", - "futures-lite 2.6.1", - "rustix 1.0.8", -] - -[[package]] -name = "async-signal" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1" -dependencies = [ - "async-io 2.5.0", - "async-lock 3.4.1", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 1.0.8", - "signal-hook-registry", - "slab", - "windows-sys 0.60.2", -] - -[[package]] -name = "async-sse" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bba003996b8fd22245cd0c59b869ba764188ed435392cf2796d03b805ade10" -dependencies = [ - "async-channel 1.9.0", - "async-std", - "http-types", - "log", - "memchr", - "pin-project-lite 0.1.12", -] - -[[package]] -name = "async-std" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" -dependencies = [ - "async-attributes", - "async-channel 1.9.0", - "async-global-executor", - "async-io 2.5.0", - "async-lock 3.4.1", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite 2.6.1", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite 0.2.16", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -505,7 +217,7 @@ checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", - "pin-project-lite 0.2.16", + "pin-project-lite", ] [[package]] @@ -536,19 +248,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "async-tungstenite" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b30ef0ea5c20caaa54baea49514a206308989c68be7ecd86c7f956e4da6378" -dependencies = [ - "futures-io", - "futures-util", - "log", - "pin-project-lite 0.2.16", - "tungstenite 0.13.0", -] - [[package]] name = "atomic-waker" version = "1.1.2" @@ -568,11 +267,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ "axum-core", - "base64 0.22.1", + "base64", "bytes", "form_urlencoded", "futures-util", - "http 1.3.1", + "http", "http-body", "http-body-util", "hyper", @@ -582,13 +281,13 @@ dependencies = [ "memchr", "mime", "percent-encoding", - "pin-project-lite 0.2.16", + "pin-project-lite", "rustversion", "serde", "serde_json", "serde_path_to_error", "serde_urlencoded", - "sha1 0.10.6", + "sha1", "sync_wrapper", "tokio", "tokio-tungstenite", @@ -606,11 +305,11 @@ checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" dependencies = [ "bytes", "futures-core", - "http 1.3.1", + "http", "http-body", "http-body-util", "mime", - "pin-project-lite 0.2.16", + "pin-project-lite", "rustversion", "sync_wrapper", "tower-layer", @@ -633,18 +332,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "base-x" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.22.1" @@ -679,12 +366,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.9.4" @@ -703,15 +384,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -727,10 +399,10 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.5.0", + "async-channel", "async-task", "futures-io", - "futures-lite 2.6.1", + "futures-lite", "piper", ] @@ -750,7 +422,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969a9ba84b0ff843813e7249eed1678d9b6607ce5a3b8f0a47af3fcf7978e6e" dependencies = [ "ahash", - "base64 0.22.1", + "base64", "bitvec", "chrono", "getrandom 0.2.16", @@ -759,11 +431,11 @@ dependencies = [ "indexmap", "js-sys", "once_cell", - "rand 0.9.2", + "rand", "serde", "serde_bytes", "serde_json", - "time 0.3.43", + "time", "uuid", ] @@ -773,12 +445,6 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.10.1" @@ -864,15 +530,6 @@ dependencies = [ "half 2.6.0", ] -[[package]] -name = "cipher" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" -dependencies = [ - "generic-array", -] - [[package]] name = "clap" version = "4.5.47" @@ -907,29 +564,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "const_fn" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e" - -[[package]] -name = "cookie" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" -dependencies = [ - "aes-gcm", - "base64 0.13.1", - "hkdf", - "hmac", - "percent-encoding", - "rand 0.8.5", - "sha2 0.9.9", - "time 0.2.27", - "version_check", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -945,12 +579,6 @@ dependencies = [ "libc", ] -[[package]] -name = "cpuid-bool" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" - [[package]] name = "criterion" version = "0.7.0" @@ -1026,25 +654,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "ctr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" -dependencies = [ - "cipher", -] - [[package]] name = "darling" version = "0.14.4" @@ -1227,31 +836,16 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "displaydoc" version = "0.2.5" @@ -1290,16 +884,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "erased-serde" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" -dependencies = [ - "serde", - "typeid", -] - [[package]] name = "errno" version = "0.3.13" @@ -1310,12 +894,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "event-listener" version = "5.4.1" @@ -1324,7 +902,7 @@ checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", - "pin-project-lite 0.2.16", + "pin-project-lite", ] [[package]] @@ -1333,8 +911,8 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.1", - "pin-project-lite 0.2.16", + "event-listener", + "pin-project-lite", ] [[package]] @@ -1358,18 +936,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" @@ -1458,32 +1027,14 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite 0.2.16", - "waker-fn", -] - [[package]] name = "futures-lite" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand 2.3.0", "futures-core", - "futures-io", - "parking", - "pin-project-lite 0.2.16", + "pin-project-lite", ] [[package]] @@ -1528,7 +1079,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.16", + "pin-project-lite", "pin-utils", "slab", ] @@ -1543,17 +1094,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.16" @@ -1581,34 +1121,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "ghash" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" -dependencies = [ - "opaque-debug", - "polyval", -] - [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "half" version = "1.8.3" @@ -1669,55 +1187,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hkdf" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" -dependencies = [ - "digest 0.9.0", - "hmac", -] - -[[package]] -name = "hmac" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.3.1" @@ -1736,7 +1211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http", ] [[package]] @@ -1747,43 +1222,9 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", + "http", "http-body", - "pin-project-lite 0.2.16", -] - -[[package]] -name = "http-client" -version = "6.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1947510dc91e2bf586ea5ffb412caad7673264e14bb39fb9078da114a94ce1a5" -dependencies = [ - "async-trait", - "cfg-if", - "http-types", - "log", -] - -[[package]] -name = "http-types" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" -dependencies = [ - "anyhow", - "async-channel 1.9.0", - "async-std", - "base64 0.13.1", - "cookie", - "futures-lite 1.13.0", - "infer", - "pin-project-lite 0.2.16", - "rand 0.7.3", - "serde", - "serde_json", - "serde_qs", - "serde_urlencoded", - "url", + "pin-project-lite", ] [[package]] @@ -1808,16 +1249,15 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "http 1.3.1", + "http", "http-body", "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.16", + "pin-project-lite", "pin-utils", "smallvec", "tokio", - "want", ] [[package]] @@ -1826,22 +1266,14 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ - "base64 0.22.1", "bytes", - "futures-channel", "futures-core", - "futures-util", - "http 1.3.1", + "http", "http-body", "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite 0.2.16", - "socket2 0.6.0", + "pin-project-lite", "tokio", "tower-service", - "tracing", ] [[package]] @@ -1992,68 +1424,17 @@ dependencies = [ "serde", ] -[[package]] -name = "infer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" - -[[package]] -name = "input_buffer" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" -dependencies = [ - "bytes", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "io-uring" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags 2.9.4", + "bitflags", "cfg-if", "libc", ] -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "iso8601" version = "0.6.3" @@ -2097,15 +1478,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -2124,12 +1496,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -2147,9 +1513,6 @@ name = "log" version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" -dependencies = [ - "value-bag", -] [[package]] name = "lru" @@ -2178,16 +1541,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -2217,7 +1570,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.3.1", + "http", "httparse", "memchr", "mime", @@ -2304,12 +1657,6 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "opentelemetry" version = "0.30.0" @@ -2319,7 +1666,7 @@ dependencies = [ "futures-core", "futures-sink", "js-sys", - "pin-project-lite 0.2.16", + "pin-project-lite", "thiserror 2.0.16", ] @@ -2376,7 +1723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" dependencies = [ "pest", - "sha2 0.10.9", + "sha2", ] [[package]] @@ -2417,12 +1764,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - [[package]] name = "pin-project-lite" version = "0.2.16" @@ -2442,7 +1783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.3.0", + "fastrand", "futures-io", ] @@ -2474,47 +1815,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite 0.2.16", - "windows-sys 0.48.0", -] - -[[package]] -name = "polling" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.5.2", - "pin-project-lite 0.2.16", - "rustix 1.0.8", - "windows-sys 0.60.2", -] - -[[package]] -name = "polyval" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" -dependencies = [ - "cpuid-bool", - "opaque-debug", - "universal-hash", -] - [[package]] name = "potential_utf" version = "0.1.3" @@ -2548,12 +1848,6 @@ dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.101" @@ -2590,58 +1884,14 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "rand_chacha", + "rand_core", ] [[package]] @@ -2651,25 +1901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", + "rand_core", ] [[package]] @@ -2681,15 +1913,6 @@ dependencies = [ "getrandom 0.3.3", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rayon" version = "1.11.0" @@ -2759,46 +1982,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" -[[package]] -name = "reqwest" -version = "0.12.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "http 1.3.1", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "js-sys", - "log", - "mime_guess", - "percent-encoding", - "pin-project-lite 0.2.16", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "route-recognizer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" - [[package]] name = "rust_decimal" version = "1.37.2" @@ -2815,39 +1998,16 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.37.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - [[package]] name = "rustix" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.4", + "bitflags", "errno", "libc", - "linux-raw-sys 0.9.4", + "linux-raw-sys", "windows-sys 0.60.2", ] @@ -2906,21 +2066,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.219" @@ -2971,15 +2116,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "serde_fmt" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" -dependencies = [ - "serde", -] - [[package]] name = "serde_json" version = "1.0.143" @@ -3003,17 +2139,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_qs" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror 1.0.69", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3026,28 +2151,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - [[package]] name = "sha1" version = "0.10.6" @@ -3056,26 +2159,7 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] @@ -3086,7 +2170,7 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -3095,15 +2179,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook-registry" -version = "1.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" -dependencies = [ - "libc", -] - [[package]] name = "siphasher" version = "1.0.1" @@ -3132,16 +2207,6 @@ dependencies = [ "serde", ] -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.6.0" @@ -3164,70 +2229,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check", -] - [[package]] name = "static_assertions_next" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7beae5182595e9a8b683fa98c4317f956c9a2dec3b9716990d20023cc60c766" -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1 0.6.1", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "strsim" version = "0.10.0" @@ -3262,90 +2269,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "sval" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9739f56c5d0c44a5ed45473ec868af02eb896af8c05f616673a31e1d1bb09" - -[[package]] -name = "sval_buffer" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f39b07436a8c271b34dad5070c634d1d3d76d6776e938ee97b4a66a5e8003d0b" -dependencies = [ - "sval", - "sval_ref", -] - -[[package]] -name = "sval_dynamic" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffcb072d857431bf885580dacecf05ed987bac931230736739a79051dbf3499b" -dependencies = [ - "sval", -] - -[[package]] -name = "sval_fmt" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f214f427ad94a553e5ca5514c95c6be84667cbc5568cce957f03f3477d03d5c" -dependencies = [ - "itoa", - "ryu", - "sval", -] - -[[package]] -name = "sval_json" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ed34b32e638dec9a99c8ac92d0aa1220d40041026b625474c2b6a4d6f4feb" -dependencies = [ - "itoa", - "ryu", - "sval", -] - -[[package]] -name = "sval_nested" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bae8fcb2f24fee2c42c1f19037707f7c9a29a0cda936d2188d48a961c4bb2a" -dependencies = [ - "sval", - "sval_buffer", - "sval_ref", -] - -[[package]] -name = "sval_ref" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4eaea3821d3046dcba81d4b8489421da42961889902342691fb7eab491d79e" -dependencies = [ - "sval", -] - -[[package]] -name = "sval_serde" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172dd4aa8cb3b45c8ac8f3b4111d644cd26938b0643ede8f93070812b87fb339" -dependencies = [ - "serde", - "sval", - "sval_nested", -] - [[package]] name = "syn" version = "1.0.109" @@ -3373,9 +2296,6 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] [[package]] name = "synstructure" @@ -3400,10 +2320,10 @@ version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ - "fastrand 2.3.0", + "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.8", + "rustix", "windows-sys 0.60.2", ] @@ -3447,60 +2367,6 @@ dependencies = [ "syn 2.0.106", ] -[[package]] -name = "tide" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c459573f0dd2cc734b539047f57489ea875af8ee950860ded20cf93a79a1dee0" -dependencies = [ - "async-h1", - "async-sse", - "async-std", - "async-trait", - "futures-util", - "http-client", - "http-types", - "kv-log-macro", - "log", - "pin-project-lite 0.2.16", - "route-recognizer", - "serde", - "serde_json", -] - -[[package]] -name = "tide-websockets" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3592c5cb5cb1b7a2ff3a0e5353170c1bb5b104b2f66dd06f73304169b52cc725" -dependencies = [ - "async-dup", - "async-std", - "async-tungstenite", - "base64 0.13.1", - "futures-util", - "pin-project", - "serde", - "serde_json", - "sha-1", - "tide", -] - -[[package]] -name = "time" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" -dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb", - "time-macros 0.1.1", - "version_check", - "winapi", -] - [[package]] name = "time" version = "0.3.43" @@ -3512,7 +2378,7 @@ dependencies = [ "powerfmt", "serde", "time-core", - "time-macros 0.2.24", + "time-macros", ] [[package]] @@ -3521,16 +2387,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" -[[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - [[package]] name = "time-macros" version = "0.2.24" @@ -3541,19 +2397,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "time-macros-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn 1.0.109", -] - [[package]] name = "tinystr" version = "0.8.1" @@ -3585,9 +2428,9 @@ dependencies = [ "io-uring", "libc", "mio", - "pin-project-lite 0.2.16", + "pin-project-lite", "slab", - "socket2 0.6.0", + "socket2", "tokio-macros", "windows-sys 0.59.0", ] @@ -3610,7 +2453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", - "pin-project-lite 0.2.16", + "pin-project-lite", "tokio", ] @@ -3623,7 +2466,7 @@ dependencies = [ "futures-util", "log", "tokio", - "tungstenite 0.26.2", + "tungstenite", ] [[package]] @@ -3636,7 +2479,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.16", + "pin-project-lite", "tokio", ] @@ -3665,7 +2508,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project-lite 0.2.16", + "pin-project-lite", "sync_wrapper", "tokio", "tower-layer", @@ -3673,24 +2516,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-http" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" -dependencies = [ - "bitflags 2.9.4", - "bytes", - "futures-util", - "http 1.3.1", - "http-body", - "iri-string", - "pin-project-lite 0.2.16", - "tower", - "tower-layer", - "tower-service", -] - [[package]] name = "tower-layer" version = "0.3.3" @@ -3710,7 +2535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", - "pin-project-lite 0.2.16", + "pin-project-lite", "tracing-attributes", "tracing-core", ] @@ -3747,32 +2572,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8dada8c1a3aeca77d6b51a4f1314e0f4b8e438b7b1b71e3ddaca8080e4093" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http 0.2.12", - "httparse", - "input_buffer", - "log", - "rand 0.8.5", - "sha-1", - "thiserror 1.0.69", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.26.2" @@ -3781,21 +2580,15 @@ checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ "bytes", "data-encoding", - "http 1.3.1", + "http", "httparse", "log", - "rand 0.9.2", - "sha1 0.10.6", + "rand", + "sha1", "thiserror 2.0.16", "utf-8", ] -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - [[package]] name = "typenum" version = "1.18.0" @@ -3808,28 +2601,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "universal-hash" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "url" version = "2.5.7" @@ -3866,54 +2643,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "value-bag" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" -dependencies = [ - "value-bag-serde1", - "value-bag-sval2", -] - -[[package]] -name = "value-bag-serde1" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35540706617d373b118d550d41f5dfe0b78a0c195dc13c6815e92e2638432306" -dependencies = [ - "erased-serde", - "serde", - "serde_fmt", -] - -[[package]] -name = "value-bag-sval2" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe7e140a2658cc16f7ee7a86e413e803fc8f9b5127adc8755c19f9fefa63a52" -dependencies = [ - "sval", - "sval_buffer", - "sval_dynamic", - "sval_fmt", - "sval_json", - "sval_ref", - "sval_serde", -] - [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - [[package]] name = "walkdir" version = "2.5.0" @@ -3924,21 +2659,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -3981,19 +2701,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.101" @@ -4036,22 +2743,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.11" @@ -4061,12 +2752,6 @@ dependencies = [ "windows-sys 0.61.0", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-core" version = "0.61.2" @@ -4132,15 +2817,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.59.0" @@ -4168,21 +2844,6 @@ dependencies = [ "windows-link 0.2.0", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -4216,12 +2877,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -4234,12 +2889,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -4252,12 +2901,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -4282,12 +2925,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -4300,12 +2937,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -4318,12 +2949,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -4336,12 +2961,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -4501,5 +3120,5 @@ dependencies = [ "lazy_static", "quick-error", "regex", - "time 0.3.43", + "time", ] diff --git a/Cargo.toml b/Cargo.toml index fd75de4d..5dee3203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,7 +139,6 @@ members = [ "parser", "derive", "integrations/axum", - "integrations/tide", ] [workspace.dependencies] diff --git a/integrations/tide/Cargo.toml b/integrations/tide/Cargo.toml deleted file mode 100644 index c432a0f6..00000000 --- a/integrations/tide/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -authors = ["vkill ", "sunli "] -categories = ["network-programming", "asynchronous"] -description = "async-graphql for tide" -documentation = "https://docs.rs/async-graphql-tide/" -edition = "2024" -homepage = "https://github.com/async-graphql/async-graphql" -keywords = ["futures", "async", "graphql"] -license = "MIT OR Apache-2.0" -name = "async-graphql-tide" -repository = "https://github.com/async-graphql/async-graphql" -version = "7.0.17" - -[features] -default = ["websocket"] -websocket = ["tide-websockets"] - -[dependencies] -async-graphql = { workspace = true } - -async-trait.workspace = true -futures-util.workspace = true -serde_json.workspace = true - -tide = { version = "0.16.0", default-features = false, features = [ - "h1-server", -] } -tide-websockets = { version = "0.4.0", optional = true } - -[dev-dependencies] -# Surf lacks multipart support -async-std = { version = "1.12.0", features = ["attributes", "tokio1"] } -reqwest = { version = "0.12.1", default-features = false, features = [ - "json", - "multipart", -] } -serde_json.workspace = true diff --git a/integrations/tide/LICENSE-APACHE b/integrations/tide/LICENSE-APACHE deleted file mode 100644 index f8e5e5ea..00000000 --- a/integrations/tide/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/integrations/tide/LICENSE-MIT b/integrations/tide/LICENSE-MIT deleted file mode 100644 index 468cd79a..00000000 --- a/integrations/tide/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/integrations/tide/src/lib.rs b/integrations/tide/src/lib.rs deleted file mode 100644 index 6b244ac4..00000000 --- a/integrations/tide/src/lib.rs +++ /dev/null @@ -1,176 +0,0 @@ -//! Async-graphql integration with Tide -//! -//! # Examples -//! *[Full Example]()* - -#![warn(missing_docs)] -#![allow(clippy::type_complexity)] -#![allow(clippy::needless_doctest_main)] -#![forbid(unsafe_code)] - -#[cfg(feature = "websocket")] -mod subscription; - -use async_graphql::{Executor, ParseRequestError, http::MultipartOptions}; -#[cfg(feature = "websocket")] -pub use subscription::GraphQLSubscription; -use tide::{ - Body, Request, Response, StatusCode, - http::{ - Method, - headers::{self, HeaderValue}, - }, - utils::async_trait, -}; - -/// Create a new GraphQL endpoint with the executor. -/// -/// Default multipart options are used and batch operations are supported. -pub fn graphql(executor: E) -> GraphQLEndpoint { - GraphQLEndpoint { - executor, - opts: MultipartOptions::default(), - batch: true, - } -} - -/// A GraphQL endpoint. -/// -/// This is created with the [`endpoint`](fn.endpoint.html) function. -#[non_exhaustive] -pub struct GraphQLEndpoint { - /// The graphql executor - pub executor: E, - /// The multipart options of the endpoint. - pub opts: MultipartOptions, - /// Whether to support batch requests in the endpoint. - pub batch: bool, -} - -impl GraphQLEndpoint { - /// Set the multipart options of the endpoint. - #[must_use] - pub fn multipart_opts(self, opts: MultipartOptions) -> Self { - Self { opts, ..self } - } - /// Set whether batch requests are supported in the endpoint. - #[must_use] - pub fn batch(self, batch: bool) -> Self { - Self { batch, ..self } - } -} - -// Manual impl to remove bounds on generics -impl Clone for GraphQLEndpoint { - fn clone(&self) -> Self { - Self { - executor: self.executor.clone(), - opts: self.opts, - batch: self.batch, - } - } -} - -#[async_trait] -impl tide::Endpoint for GraphQLEndpoint -where - E: Executor, - TideState: Clone + Send + Sync + 'static, -{ - async fn call(&self, request: Request) -> tide::Result { - respond( - self.executor - .execute_batch(if self.batch { - receive_batch_request_opts(request, self.opts).await - } else { - receive_request_opts(request, self.opts) - .await - .map(Into::into) - }?) - .await, - ) - } -} - -/// Convert a Tide request to a GraphQL request. -pub async fn receive_request( - request: Request, -) -> tide::Result { - receive_request_opts(request, Default::default()).await -} - -/// Convert a Tide request to a GraphQL request with options on how to receive -/// multipart. -pub async fn receive_request_opts( - request: Request, - opts: MultipartOptions, -) -> tide::Result { - receive_batch_request_opts(request, opts) - .await? - .into_single() - .map_err(|e| tide::Error::new(StatusCode::BadRequest, e)) -} - -/// Convert a Tide request to a GraphQL batch request. -pub async fn receive_batch_request( - request: Request, -) -> tide::Result { - receive_batch_request_opts(request, Default::default()).await -} - -/// Convert a Tide request to a GraphQL batch request with options on how to -/// receive multipart. -pub async fn receive_batch_request_opts( - mut request: Request, - opts: MultipartOptions, -) -> tide::Result { - if request.method() == Method::Get { - async_graphql::http::parse_query_string(request.url().query().unwrap_or_default()) - .map(Into::into) - .map_err(|err| tide::Error::new(StatusCode::BadRequest, err)) - } else if request.method() == Method::Post { - let body = request.take_body(); - let content_type = request - .header(headers::CONTENT_TYPE) - .and_then(|values| values.get(0)) - .map(HeaderValue::as_str); - - async_graphql::http::receive_batch_body(content_type, body, opts) - .await - .map_err(|e| { - tide::Error::new( - match &e { - ParseRequestError::PayloadTooLarge => StatusCode::PayloadTooLarge, - _ => StatusCode::BadRequest, - }, - e, - ) - }) - } else { - Err(tide::Error::from_str( - StatusCode::MethodNotAllowed, - "GraphQL only supports GET and POST requests", - )) - } -} - -/// Convert a GraphQL response to a Tide response. -pub fn respond(resp: impl Into) -> tide::Result { - let resp = resp.into(); - - let mut response = Response::new(StatusCode::Ok); - if resp.is_ok() { - if let Some(cache_control) = resp.cache_control().value() { - response.insert_header(headers::CACHE_CONTROL, cache_control); - } - } - - for (name, value) in resp.http_headers_iter() { - if let Ok(value) = value.to_str() { - response.append_header(name.as_str(), value); - } - } - - response.set_body(Body::from_json(&resp)?); - Ok(response) -} diff --git a/integrations/tide/src/subscription.rs b/integrations/tide/src/subscription.rs deleted file mode 100644 index 78051a64..00000000 --- a/integrations/tide/src/subscription.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::{future::Future, str::FromStr, time::Duration}; - -use async_graphql::{ - Data, Executor, Result, - http::{ - ALL_WEBSOCKET_PROTOCOLS, DefaultOnConnInitType, DefaultOnPingType, - WebSocket as AGWebSocket, WebSocketProtocols, WsMessage, default_on_connection_init, - default_on_ping, - }, -}; -use futures_util::{StreamExt, future}; -use tide::Endpoint; -use tide_websockets::{Message, tungstenite::protocol::CloseFrame}; - -/// A GraphQL subscription endpoint builder. -#[cfg_attr(docsrs, doc(cfg(feature = "websocket")))] -pub struct GraphQLSubscription { - executor: E, - on_connection_init: OnConnInit, - on_ping: OnPing, - keepalive_timeout: Option, -} - -impl GraphQLSubscription -where - E: Executor, -{ - /// Create a [`GraphQLSubscription`] object. - pub fn new(executor: E) -> Self { - GraphQLSubscription { - executor, - on_connection_init: default_on_connection_init, - on_ping: default_on_ping, - keepalive_timeout: None, - } - } -} - -impl GraphQLSubscription -where - E: Executor, - OnConnInit: Fn(serde_json::Value) -> OnConnInitFut + Clone + Send + Sync + 'static, - OnConnInitFut: Future> + Send + 'static, - OnPing: FnOnce(Option<&Data>, Option) -> OnPingFut - + Clone - + Send - + Sync - + 'static, - OnPingFut: Future>> + Send + 'static, -{ - /// Specify a callback function to be called when the connection is - /// initialized. - /// - /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data - /// specified by [`with_data`]. - #[must_use] - pub fn on_connection_init(self, callback: F) -> GraphQLSubscription - where - F: Fn(serde_json::Value) -> R + Clone + Send + Sync + 'static, - R: Future> + Send + 'static, - { - GraphQLSubscription { - executor: self.executor, - on_connection_init: callback, - on_ping: self.on_ping, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Specify a ping callback function. - /// - /// This function if present, will be called with the data sent by the - /// client in the [`Ping` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#ping). - /// - /// The function should return the data to be sent in the [`Pong` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#pong). - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn on_ping(self, callback: F) -> GraphQLSubscription - where - F: FnOnce(Option<&Data>, Option) -> R + Send + Sync + Clone + 'static, - R: Future>> + Send + 'static, - { - GraphQLSubscription { - executor: self.executor, - on_connection_init: self.on_connection_init, - on_ping: callback, - keepalive_timeout: self.keepalive_timeout, - } - } - - /// Sets a timeout for receiving an acknowledgement of the keep-alive ping. - /// - /// If the ping is not acknowledged within the timeout, the connection will - /// be closed. - /// - /// NOTE: Only used for the `graphql-ws` protocol. - #[must_use] - pub fn keepalive_timeout(self, timeout: impl Into>) -> Self { - Self { - keepalive_timeout: timeout.into(), - ..self - } - } - - /// Consumes this builder to create a tide endpoint. - pub fn build(self) -> impl Endpoint - where - S: Send + Sync + Clone + 'static, - { - tide_websockets::WebSocket::::new(move |request, connection| { - let executor = self.executor.clone(); - let on_connection_init = self.on_connection_init.clone(); - let on_ping = self.on_ping.clone(); - async move { - let protocol = match request - .header("sec-websocket-protocol") - .map(|value| value.as_str()) - .and_then(|protocols| { - protocols - .split(',') - .find_map(|p| WebSocketProtocols::from_str(p.trim()).ok()) - }) { - Some(protocol) => protocol, - None => { - // default to the prior standard - WebSocketProtocols::SubscriptionsTransportWS - } - }; - - let sink = connection.clone(); - let mut stream = AGWebSocket::new( - executor.clone(), - connection - .take_while(|msg| future::ready(msg.is_ok())) - .map(Result::unwrap) - .map(Message::into_data), - protocol, - ) - .on_connection_init(on_connection_init) - .on_ping(on_ping) - .keepalive_timeout(self.keepalive_timeout); - - while let Some(data) = stream.next().await { - match data { - WsMessage::Text(text) => { - if sink.send_string(text).await.is_err() { - break; - } - } - WsMessage::Close(code, msg) => { - let _ = sink - .send(Message::Close(Some(CloseFrame { - code: code.into(), - reason: msg.into(), - }))) - .await; - break; - } - } - } - - Ok(()) - } - }) - .with_protocols(&ALL_WEBSOCKET_PROTOCOLS) - } -} diff --git a/integrations/tide/tests/graphql.rs b/integrations/tide/tests/graphql.rs deleted file mode 100644 index 73b7923b..00000000 --- a/integrations/tide/tests/graphql.rs +++ /dev/null @@ -1,219 +0,0 @@ -#![allow(clippy::uninlined_format_args)] - -mod test_utils; - -use std::io::Read; - -use async_graphql::*; -use reqwest::{StatusCode, header}; -use serde_json::json; - -type Result = std::result::Result>; - -#[async_std::test] -async fn quickstart() -> Result<()> { - let listen_addr = "127.0.0.1:8081"; - - async_std::task::spawn(async move { - struct QueryRoot; - #[Object] - impl QueryRoot { - /// Returns the sum of a and b - async fn add(&self, a: i32, b: i32) -> i32 { - a + b - } - } - - let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish(); - - let mut app = tide::new(); - let endpoint = async_graphql_tide::graphql(schema); - app.at("/").post(endpoint.clone()).get(endpoint); - app.listen(listen_addr).await - }); - - test_utils::wait_server_ready().await; - - let client = test_utils::client(); - - let resp = client - .post(format!("http://{}", listen_addr)) - .json(&json!({"query":"{ add(a: 10, b: 20) }"})) - .send() - .await?; - - assert_eq!(resp.status(), StatusCode::OK); - let string = resp.text().await?; - println!("via post {}", string); - - assert_eq!(string, json!({"data": {"add": 30}}).to_string()); - - let resp = client - .get(format!("http://{}", listen_addr)) - .query(&[("query", "{ add(a: 10, b: 20) }")]) - .send() - .await?; - - assert_eq!(resp.status(), StatusCode::OK); - let string = resp.text().await?; - println!("via get {}", string); - - assert_eq!(string, json!({"data": {"add": 30}}).to_string()); - - Ok(()) -} - -#[async_std::test] -async fn hello() -> Result<()> { - let listen_addr = "127.0.0.1:8082"; - - async_std::task::spawn(async move { - struct Hello(String); - struct QueryRoot; - #[Object] - impl QueryRoot { - /// Returns hello - async fn hello<'a>(&self, ctx: &'a Context<'_>) -> String { - let name = ctx.data_opt::().map(|hello| hello.0.as_str()); - format!("Hello, {}!", name.unwrap_or("world")) - } - } - - let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish(); - - let mut app = tide::new(); - - app.at("/").post(move |req: tide::Request<()>| { - let schema = schema.clone(); - async move { - let name = req - .header("name") - .and_then(|values| values.get(0)) - .map(ToString::to_string); - let mut req = async_graphql_tide::receive_request(req).await?; - if let Some(name) = name { - req = req.data(Hello(name)); - } - async_graphql_tide::respond(schema.execute(req).await) - } - }); - app.listen(listen_addr).await - }); - - test_utils::wait_server_ready().await; - - let client = test_utils::client(); - - let resp = client - .post(format!("http://{}", listen_addr)) - .json(&json!({"query":"{ hello }"})) - .header("Name", "Foo") - .send() - .await?; - - assert_eq!(resp.status(), StatusCode::OK); - let string = resp.text().await?; - println!("{}", string); - - assert_eq!(string, json!({"data":{"hello":"Hello, Foo!"}}).to_string()); - - let resp = client - .post(format!("http://{}", listen_addr)) - .json(&json!({"query":"{ hello }"})) - .header(header::CONTENT_TYPE, "application/json") - .send() - .await?; - - assert_eq!(resp.status(), StatusCode::OK); - let string = resp.text().await?; - println!("{}", string); - - assert_eq!( - string, - json!({"data":{"hello":"Hello, world!"}}).to_string() - ); - - Ok(()) -} - -#[async_std::test] -async fn upload() -> Result<()> { - let listen_addr = "127.0.0.1:8083"; - - async_std::task::spawn(async move { - struct QueryRoot; - - #[Object] - impl QueryRoot { - async fn value(&self) -> i32 { - 10 - } - } - - #[derive(Clone, SimpleObject)] - pub struct FileInfo { - filename: String, - mime_type: Option, - } - - struct MutationRoot; - #[Object] - impl MutationRoot { - async fn single_upload(&self, ctx: &Context<'_>, file: Upload) -> FileInfo { - let upload_value = file.value(ctx).unwrap(); - println!("single_upload: filename={}", upload_value.filename); - println!( - "single_upload: content_type={:?}", - upload_value.content_type - ); - - let file_info = FileInfo { - filename: upload_value.filename.clone(), - mime_type: upload_value.content_type.clone(), - }; - - let mut content = String::new(); - upload_value - .into_read() - .read_to_string(&mut content) - .unwrap(); - assert_eq!(content, "test".to_owned()); - - file_info - } - } - - let schema = Schema::build(QueryRoot, MutationRoot, EmptySubscription).finish(); - - let mut app = tide::new(); - app.at("/").post(async_graphql_tide::graphql(schema)); - app.listen(listen_addr).await - }); - - test_utils::wait_server_ready().await; - - let client = test_utils::client(); - - let form = reqwest::multipart::Form::new() - .text("operations", r#"{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { filename, mimeType } }", "variables": { "file": null } }"#) - .text("map", r#"{ "0": ["variables.file"] }"#) - .part("0", reqwest::multipart::Part::stream("test").file_name("test.txt").mime_str("text/plain")?); - - let resp = client - .post(format!("http://{}", listen_addr)) - .multipart(form) - .send() - .await?; - - assert_eq!(resp.status(), StatusCode::OK); - let string = resp.text().await?; - println!("{}", string); - - assert_eq!( - string, - json!({"data": {"singleUpload": {"filename": "test.txt", "mimeType": "text/plain"}}}) - .to_string() - ); - - Ok(()) -} diff --git a/integrations/tide/tests/test_utils.rs b/integrations/tide/tests/test_utils.rs deleted file mode 100644 index 2cf2bf14..00000000 --- a/integrations/tide/tests/test_utils.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::time::Duration; - -use reqwest::Client; - -pub fn client() -> Client { - Client::builder().no_proxy().build().unwrap() -} - -pub async fn wait_server_ready() { - async_std::task::sleep(Duration::from_secs(1)).await; -} From 531e8b0ee4840e86405e66e05652bf26fc2cc8f9 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Mon, 8 Sep 2025 15:20:29 -0700 Subject: [PATCH 6/6] Fix docs tests --- docs/en/src/SUMMARY.md | 4 -- docs/en/src/context.md | 35 ------------- docs/en/src/integrations_to_actix_web.md | 49 ------------------ docs/en/src/integrations_to_poem.md | 39 -------------- docs/en/src/integrations_to_warp.md | 66 ------------------------ 5 files changed, 193 deletions(-) delete mode 100644 docs/en/src/integrations_to_actix_web.md delete mode 100644 docs/en/src/integrations_to_poem.md delete mode 100644 docs/en/src/integrations_to_warp.md diff --git a/docs/en/src/SUMMARY.md b/docs/en/src/SUMMARY.md index ac2b659a..69fd4345 100644 --- a/docs/en/src/SUMMARY.md +++ b/docs/en/src/SUMMARY.md @@ -32,10 +32,6 @@ - [Extensions](extensions.md) - [How extensions are working](extensions_inner_working.md) - [Available extensions](extensions_available.md) -- [Integrations](integrations.md) - - [Poem](integrations_to_poem.md) - - [Warp](integrations_to_warp.md) - - [Actix-web](integrations_to_actix_web.md) - [Advanced topics](advanced_topics.md) - [Custom scalars](custom_scalars.md) - [Optimizing N+1 queries](dataloader.md) diff --git a/docs/en/src/context.md b/docs/en/src/context.md index 0b338f13..925ec3c5 100644 --- a/docs/en/src/context.md +++ b/docs/en/src/context.md @@ -55,41 +55,6 @@ let schema = Schema::build(Query::default(), EmptyMutation, EmptySubscription) .finish(); ``` -### Request data - -You can put data inside the context at the execution of the request, it's useful for authentication data for instance. - -A little example with a `warp` route: - -```rust -# extern crate async_graphql; -# extern crate async_graphql_warp; -# extern crate warp; -# use async_graphql::*; -# use warp::{Filter, Reply}; -# use std::convert::Infallible; -# #[derive(Default, SimpleObject)] -# struct Query { name: String } -# struct AuthInfo { pub token: Option } -# let schema = Schema::build(Query::default(), EmptyMutation, EmptySubscription).finish(); -# let schema_filter = async_graphql_warp::graphql(schema); -let graphql_post = warp::post() - .and(warp::path("graphql")) - .and(warp::header::optional("Authorization")) - .and(schema_filter) - .and_then( |auth: Option, (schema, mut request): (Schema, async_graphql::Request)| async move { - // Do something to get auth data from the header - let your_auth_data = AuthInfo { token: auth }; - let response = schema - .execute( - request - .data(your_auth_data) - ).await; - - Ok::<_, Infallible>(async_graphql_warp::GraphQLResponse::from(response)) - }); -``` - ## Headers With the Context you can also insert and appends headers. diff --git a/docs/en/src/integrations_to_actix_web.md b/docs/en/src/integrations_to_actix_web.md deleted file mode 100644 index bd56518f..00000000 --- a/docs/en/src/integrations_to_actix_web.md +++ /dev/null @@ -1,49 +0,0 @@ -# Actix-web - -## Request example - -When you define your `actix_web::App` you need to pass in the Schema as data. - -```rust -# extern crate async_graphql_actix_web; -# extern crate async_graphql; -# extern crate actix_web; -# use async_graphql::*; -# #[derive(Default,SimpleObject)] -# struct Query { a: i32 } -# let schema = Schema::build(Query::default(), EmptyMutation, EmptySubscription).finish(); -use actix_web::{web, HttpRequest, HttpResponse}; -use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse}; -async fn index( - // Schema now accessible here - schema: web::Data>, - request: GraphQLRequest, -) -> web::Json { - web::Json(schema.execute(request.into_inner()).await.into()) -} -``` - -## Subscription example - -```rust -# extern crate async_graphql_actix_web; -# extern crate async_graphql; -# extern crate actix_web; -# use async_graphql::*; -# #[derive(Default,SimpleObject)] -# struct Query { a: i32 } -# let schema = Schema::build(Query::default(), EmptyMutation, EmptySubscription).finish(); -use actix_web::{web, HttpRequest, HttpResponse}; -use async_graphql_actix_web::GraphQLSubscription; -async fn index_ws( - schema: web::Data>, - req: HttpRequest, - payload: web::Payload, -) -> actix_web::Result { - GraphQLSubscription::new(Schema::clone(&*schema)).start(&req, payload) -} -``` - -## More examples - -[https://github.com/async-graphql/examples/tree/master/actix-web](https://github.com/async-graphql/examples/tree/master/actix-web) diff --git a/docs/en/src/integrations_to_poem.md b/docs/en/src/integrations_to_poem.md deleted file mode 100644 index 741edbe9..00000000 --- a/docs/en/src/integrations_to_poem.md +++ /dev/null @@ -1,39 +0,0 @@ -# Poem - -## Request example - -```rust -# extern crate async_graphql_poem; -# extern crate async_graphql; -# extern crate poem; -# use async_graphql::*; -# #[derive(Default, SimpleObject)] -# struct Query { a: i32 } -# let schema = Schema::build(Query::default(), EmptyMutation, EmptySubscription).finish(); -use poem::Route; -use async_graphql_poem::GraphQL; - -let app = Route::new() - .at("/ws", GraphQL::new(schema)); -``` - -## Subscription example - -```rust -# extern crate async_graphql_poem; -# extern crate async_graphql; -# extern crate poem; -# use async_graphql::*; -# #[derive(Default, SimpleObject)] -# struct Query { a: i32 } -# let schema = Schema::build(Query::default(), EmptyMutation, EmptySubscription).finish(); -use poem::{get, Route}; -use async_graphql_poem::GraphQLSubscription; - -let app = Route::new() - .at("/ws", get(GraphQLSubscription::new(schema))); -``` - -## More examples - -[https://github.com/async-graphql/examples/tree/master/poem](https://github.com/async-graphql/examples/tree/master/poem) diff --git a/docs/en/src/integrations_to_warp.md b/docs/en/src/integrations_to_warp.md deleted file mode 100644 index 62f7af55..00000000 --- a/docs/en/src/integrations_to_warp.md +++ /dev/null @@ -1,66 +0,0 @@ -# Warp - -For `Async-graphql-warp`, two `Filter` integrations are provided: `graphql` and `graphql_subscription`. - -The `graphql` filter is used for execution `Query` and `Mutation` requests. It extracts GraphQL request and outputs `async_graphql::Schema` and `async_graphql::Request`. -You can combine other filters later, or directly call `Schema::execute` to execute the query. - -`graphql_subscription` is used to implement WebSocket subscriptions. It outputs `warp::Reply`. - -## Request example - -```rust -# extern crate async_graphql_warp; -# extern crate async_graphql; -# extern crate warp; -# use async_graphql::*; -# use std::convert::Infallible; -# use warp::Filter; -# struct QueryRoot; -# #[Object] -# impl QueryRoot { async fn version(&self) -> &str { "1.0" } } -# async fn other() { -type MySchema = Schema; - -let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription); -let filter = async_graphql_warp::graphql(schema).and_then(|(schema, request): (MySchema, async_graphql::Request)| async move { - // Execute query - let resp = schema.execute(request).await; - - // Return result - Ok::<_, Infallible>(async_graphql_warp::GraphQLResponse::from(resp)) -}); -warp::serve(filter).run(([0, 0, 0, 0], 8000)).await; -# } -``` - -## Subscription example - -```rust -# extern crate async_graphql_warp; -# extern crate async_graphql; -# extern crate warp; -# use async_graphql::*; -# use futures_util::stream::{Stream, StreamExt}; -# use std::convert::Infallible; -# use warp::Filter; -# struct SubscriptionRoot; -# #[Subscription] -# impl SubscriptionRoot { -# async fn tick(&self) -> impl Stream { -# futures_util::stream::iter(0..10) -# } -# } -# struct QueryRoot; -# #[Object] -# impl QueryRoot { async fn version(&self) -> &str { "1.0" } } -# async fn other() { -let schema = Schema::new(QueryRoot, EmptyMutation, SubscriptionRoot); -let filter = async_graphql_warp::graphql_subscription(schema); -warp::serve(filter).run(([0, 0, 0, 0], 8000)).await; -# } -``` - -## More examples - -[https://github.com/async-graphql/examples/tree/master/warp](https://github.com/async-graphql/examples/tree/master/warp)