Skip to content
New issue

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

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

Already on GitHub? # to your account

JuniperRequest and Response are not seen as implementors of axum 0.8.x Extractors #1305

Closed
jonasrichard opened this issue Jan 8, 2025 · 3 comments · Fixed by #1306
Closed
Assignees
Labels
k::integration Related to integration with third-party libraries or systems lib::axum Related to `axum` crate integration support
Milestone

Comments

@jonasrichard
Copy link

I hate to write things like this because it should work, but I don't have any idea why it says that JuniperRequest doesn't implement FromRequest even if it is a last param of the axum handler, and the similar issue with JuniperResponse. I am using everything up to date in Cargo.toml, but I can paste here, too.

use axum::{debug_handler, routing::post, Extension, Router};
use juniper::{
    graphql_object, EmptyMutation, EmptySubscription, RootNode,
};
use juniper_axum::{extract::JuniperRequest, response::JuniperResponse};
use std::{net::SocketAddr, sync::Arc};
use tokio::net::TcpListener;

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

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

#[graphql_object(context = Context)]
impl Query {
    fn add(a: i32, b: i32) -> i32 {
        a + b
    }
}
type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;

#[debug_handler]
async fn graphql_handler(
    Extension(schema): Extension<Arc<Schema>>,
    Extension(context): Extension<Context>,
    JuniperRequest(req): JuniperRequest,
) -> JuniperResponse {
    req.execute(schema, todo!()).await
}

#[tokio::main]
async fn main() {
    let schema = Schema::new(
        Query,
        EmptyMutation::<Context>::new(),
        EmptySubscription::<Context>::new(),
    );

    let app = Router::new()
        .route("/graphql", post(graphql_handler))
        .layer(Extension(Arc::new(schema)))
        .layer(Extension(Context));

    let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
    let listener = TcpListener::bind(addr)
        .await
        .unwrap_or_else(|e| panic!("failed to listen on {addr}: {e}"));

    axum::serve(listener, app)
        .await
        .unwrap_or_else(|e| panic!("failed to serve: {e}"));
}

Error is:

error[E0308]: mismatched types
   --> src/main.rs:41:17
    |
41  |     req.execute(schema, todo!()).await
    |         ------- ^^^^^^ expected `&RootNode<'_, _, _, _>`, found `Arc<RootNode<'_, Query, ..., ...>>`
    |         |
    |         arguments to this method are incorrect
    |
    = note: expected reference `&RootNode<'_, _, _, _, _>`
                  found struct `Arc<RootNode<'_, Query, EmptyMutation<Context>, EmptySubscription<Context>, _>>`
note: method defined here
   --> /Users/richard.jonas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/juniper-0.16.1/src/http/mod.rs:297:18
    |
297 |     pub async fn execute<'a, QueryT, MutationT, SubscriptionT>(
    |                  ^^^^^^^
help: consider borrowing here
    |
41  |     req.execute(&schema, todo!()).await
    |                 +

warning: unreachable call
  --> src/main.rs:41:9
   |
41 |     req.execute(schema, todo!()).await
   |         ^^^^^^^         ------- any code following this expression is unreachable
   |         |
   |         unreachable call
   |
   = note: `#[warn(unreachable_code)]` on by default

error[E0308]: mismatched types
  --> src/main.rs:41:5
   |
41 |     req.execute(schema, todo!()).await
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `JuniperResponse`, found `GraphQLBatchResponse`
   |
   = note: expected struct `JuniperResponse`
                found enum `GraphQLBatchResponse`
help: try wrapping the expression in `juniper_axum::response::JuniperResponse`
   |
41 |     juniper_axum::response::JuniperResponse(req.execute(schema, todo!()).await)
   |     ++++++++++++++++++++++++++++++++++++++++                                  +

error[E0277]: the trait bound `JuniperResponse: IntoResponse` is not satisfied
  --> src/main.rs:40:6
   |
40 | ) -> JuniperResponse {
   |      ^^^^^^^^^^^^^^^ the trait `IntoResponse` is not implemented for `JuniperResponse`
   |
   = help: the following other types implement trait `IntoResponse`:
             &'static [u8; N]
             &'static [u8]
             &'static str
             ()
             (R,)
             (Response<()>, R)
             (Response<()>, T1, R)
             (Response<()>, T1, T2, R)
           and 120 others
note: required by a bound in `__axum_macros_check_graphql_handler_into_response::{closure#0}::check`
  --> src/main.rs:40:6
   |
40 | ) -> JuniperResponse {
   |      ^^^^^^^^^^^^^^^ required by this bound in `check`

error[E0308]: mismatched types
   --> src/main.rs:41:17
    |
41  |     req.execute(schema, todo!()).await
    |         ------- ^^^^^^ expected `&RootNode<'_, _, _, _>`, found `Arc<RootNode<'_, Query, ..., ...>>`
    |         |
    |         arguments to this method are incorrect
    |
    = note: expected reference `&RootNode<'_, _, _, _, _>`
                  found struct `Arc<RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>, _>>`
note: method defined here
   --> /Users/richard.jonas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/juniper-0.16.1/src/http/mod.rs:297:18
    |
297 |     pub async fn execute<'a, QueryT, MutationT, SubscriptionT>(
    |                  ^^^^^^^
help: consider borrowing here
    |
41  |     req.execute(&schema, todo!()).await
    |                 +

error[E0277]: the trait bound `JuniperRequest: FromRequest<(), axum_core::extract::private::ViaParts>` is not satisfied
  --> src/main.rs:39:26
   |
39 |     JuniperRequest(req): JuniperRequest,
   |                          ^^^^^^^^^^^^^^ the trait `FromRequestParts<()>` is not implemented for `JuniperRequest`, which is required by `JuniperRequest: FromRequest<(), _>`
   |
   = note: Function argument is not a valid axum extractor. 
           See `https://docs.rs/axum/0.8/axum/extract/index.html` for details
   = help: the following other types implement trait `FromRequestParts<S>`:
             `()` implements `FromRequestParts<S>`
             `(T1, T2)` implements `FromRequestParts<S>`
             `(T1, T2, T3)` implements `FromRequestParts<S>`
             `(T1, T2, T3, T4)` implements `FromRequestParts<S>`
             `(T1, T2, T3, T4, T5)` implements `FromRequestParts<S>`
             `(T1, T2, T3, T4, T5, T6)` implements `FromRequestParts<S>`
             `(T1, T2, T3, T4, T5, T6, T7)` implements `FromRequestParts<S>`
             `(T1, T2, T3, T4, T5, T6, T7, T8)` implements `FromRequestParts<S>`
           and 27 others
   = note: required for `JuniperRequest` to implement `FromRequest<(), axum_core::extract::private::ViaParts>`
note: required by a bound in `__axum_macros_check_graphql_handler_2_from_request_check`
  --> src/main.rs:39:26
   |
39 |     JuniperRequest(req): JuniperRequest,
   |                          ^^^^^^^^^^^^^^ required by this bound in `__axum_macros_check_graphql_handler_2_from_request_check`

error[E0277]: the trait bound `fn(Extension<Arc<RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>>>, Extension<Context>, JuniperRequest) -> impl std::future::Future<Output = JuniperResponse> {graphql_handler}: Handler<_, _>` is not satisfied
   --> src/main.rs:53:33
    |
53  |         .route("/graphql", post(graphql_handler))
    |                            ---- ^^^^^^^^^^^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn(Extension<Arc<RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>>>, Extension<Context>, JuniperRequest) -> ... {graphql_handler}`
    |                            |
    |                            required by a bound introduced by this call
    |
    = note: the full name for the type has been written to '/Users/richard.jonas/projects/try-new-things/rust-offer-graphql/target/debug/deps/rust_offer_graphql-6f31c9da0ab7a774.long-type-10051857777317374710.txt'
    = note: consider using `--verbose` to print the full type name to the console
    = note: Consider using `#[axum::debug_handler]` to improve the error message
    = help: the following other types implement trait `Handler<T, S>`:
              `Layered<L, H, T, S>` implements `Handler<T, S>`
              `MethodRouter<S>` implements `Handler<(), S>`
note: required by a bound in `post`
   --> /Users/richard.jonas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.8.1/src/routing/method_routing.rs:444:1
    |
444 | top_level_handler_fn!(post, POST);
    | ^^^^^^^^^^^^^^^^^^^^^^----^^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `post`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
warning: `rust-offer-graphql` (bin "rust-offer-graphql") generated 1 warning
error: could not compile `rust-offer-graphql` (bin "rust-offer-graphql") due to 9 previous errors; 1 warning emitted
@jonasrichard
Copy link
Author

Sorry not mentioning that I used axum 0.8.1, and after browsing the source code of juniper I saw that it uses axum 0.7. Once I downgraded to axum 0.7 everything compiled.

@jonasrichard jonasrichard changed the title JuniperRequest and Response are not seen as implementors of axum Extractors JuniperRequest and Response are not seen as implementors of axum 0.8.x Extractors Jan 9, 2025
@tyranron
Copy link
Member

@jonasrichard sorry for your confusion. There were some delays in merging #1303. I'll release the juniper_axum 0.2.0 shortly, so it can be used with axum 0.8.

@tyranron tyranron self-assigned this Jan 13, 2025
@tyranron tyranron added support k::integration Related to integration with third-party libraries or systems lib::axum Related to `axum` crate integration labels Jan 13, 2025
@tyranron tyranron added this to the 0.17.0 milestone Jan 13, 2025
tyranron added a commit that referenced this issue Jan 13, 2025
Signed-off-by: Joe Grund <jgrund@whamcloud.io>
Co-authored-by: Joe Grund <jgrund@whamcloud.io>
tyranron added a commit that referenced this issue Jan 13, 2025
…#1305)

Signed-off-by: Joe Grund <jgrund@whamcloud.io>
Co-authored-by: Joe Grund <jgrund@whamcloud.io>
@tyranron
Copy link
Member

@jonasrichard released in juniper_axum 0.2.0.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
k::integration Related to integration with third-party libraries or systems lib::axum Related to `axum` crate integration support
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants