Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

Open
jonasrichard opened this issue Jan 8, 2025 · 1 comment

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant