如何使用graphql java从请求头设置上下文

如何使用graphql java从请求头设置上下文,java,graphql,graphql-java,Java,Graphql,Graphql Java,我希望能够根据从请求接收到的http请求头设置上下文变量。这将是一个jwt令牌,因此我可以在每个查询中识别我的用户 package br.com.b2breservas.api; import com.google.common.base.Charsets; import com.google.common.io.Resources; import graphql.GraphQL; import graphql.schema.GraphQLSchema; import graphql.sche

我希望能够根据从请求接收到的http请求头设置上下文变量。这将是一个jwt令牌,因此我可以在每个查询中识别我的用户

package br.com.b2breservas.api;

import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.URL;

import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring;

@Component
public class GraphQLProvider   {


    @Autowired
    GraphQLDataFetchers graphQLDataFetchers;

    private GraphQL graphQL;

    @PostConstruct
    public void init() throws IOException {
        URL url = Resources.getResource("schema.graphqls");
        String sdl = Resources.toString(url, Charsets.UTF_8);
        GraphQLSchema graphQLSchema = buildSchema(sdl);
        this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
    }

    private GraphQLSchema buildSchema(String sdl) {
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
        RuntimeWiring runtimeWiring = buildWiring();
        SchemaGenerator schemaGenerator = new SchemaGenerator();
        return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
    }

    private RuntimeWiring buildWiring() {
        return RuntimeWiring.newRuntimeWiring()
                .type(newTypeWiring("Query")
                        .dataFetcher("books", graphQLDataFetchers.getBooks()))
                .type(newTypeWiring("Query")
                        .dataFetcher("bookById", graphQLDataFetchers.getBookByIdDataFetcher()))
                .type(newTypeWiring("Book")
                        .dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher()))
                .build();
    }

    @Bean
    public GraphQL graphQL() {
        return graphQL;
    }

}

您可以创建内部包含JWT或HttpServletRequest的自定义对象:

执行GraphQL查询时,创建此上下文对象并将其设置为ExecutionInput。大多数web框架应该提供一些方法来轻松访问当前的HttpServletRequest:

然后,在数据获取程序中,可以通过以下方式获取上下文:

@Override
public Object get(DataFetchingEnvironment env) throws Exception {

    GraphQLContext context = env.getContext();
    HttpServletRequest httpServletRequest = context.getHttpServletRequest();

}

您可以创建内部包含JWT或HttpServletRequest的自定义对象:

执行GraphQL查询时,创建此上下文对象并将其设置为ExecutionInput。大多数web框架应该提供一些方法来轻松访问当前的HttpServletRequest:

然后,在数据获取程序中,可以通过以下方式获取上下文:

@Override
public Object get(DataFetchingEnvironment env) throws Exception {

    GraphQLContext context = env.getContext();
    HttpServletRequest httpServletRequest = context.getHttpServletRequest();

}

您可以注入或自动连接自定义GraphQLInvocation实例,该实例可以充当GraphQL处理的所有请求的拦截器


您可以注入或自动连接自定义GraphQLInvocation实例,该实例可以充当GraphQL处理的所有请求的拦截器


我不明白。客户机是Apollo客户机,它将根据que请求发送Auth头。我想以某种方式从spring boot读取这个令牌,并将其设置为上下文变量,以便在数据获取程序上使用它。我应该把这个代码放在哪里呢?那么现在如何接收GraphQLHTTP请求呢?如果您使用的是MVC控制器,那么只需将HttpServletRequest参数放入控制器方法..Spring boot@ken chanit也是一样,很可能springboot在幕后使用mvc。但是如果您使用webflux,只需将请求参数类型更改为ServerHttpRequest,而不是Head,我想我使用的是一个dependencie,它在幕后处理HTTPPOST请求。我可能必须覆盖它,以便将上下文注入其中。这有意义吗?我不明白。客户机是Apollo客户机,它将根据que请求发送Auth头。我想以某种方式从spring boot读取这个令牌,并将其设置为上下文变量,以便在数据获取程序上使用它。我应该把这个代码放在哪里呢?那么现在如何接收GraphQLHTTP请求呢?如果您使用的是MVC控制器,那么只需将HttpServletRequest参数放入控制器方法..Spring boot@ken chanit也是一样,很可能springboot在幕后使用mvc。但是如果您使用webflux,只需将请求参数类型更改为ServerHttpRequest,而不是Head,我想我使用的是一个dependencie,它在幕后处理HTTPPOST请求。我可能必须覆盖它,以便将上下文注入其中。这有意义吗?您好,在哪里导入类或接口?GraphQLDataFetchers来自?我在internet上找不到任何相关的类,因为许多库似乎都有它…@maxyme是您编写代码的类。只需在任意位置创建并导入它。只要在上面使用spring组件装饰器,就可以开始了。这很奇怪,因为使用GraphQLJava工具,我不必编写这样的类,也不需要编写这样的提供程序……您好,在哪里导入类或接口?GraphQLDataFetchers来自?我在internet上找不到任何相关的类,因为许多库似乎都有它…@maxyme是您编写代码的类。只需在任意位置创建并导入它。只要在上面使用spring组件装饰器,就可以开始了。这很奇怪,因为使用GraphQL Java工具,我不必编写这样的类,也不需要编写这样的提供程序。。。
@Override
public Object get(DataFetchingEnvironment env) throws Exception {

    GraphQLContext context = env.getContext();
    HttpServletRequest httpServletRequest = context.getHttpServletRequest();

}
import graphql.ExecutionInput
import graphql.ExecutionResult
import graphql.GraphQL
import graphql.spring.web.servlet.GraphQLInvocation
import graphql.spring.web.servlet.GraphQLInvocationData
import org.springframework.context.annotation.Primary
import org.springframework.stereotype.Component
import org.springframework.web.context.request.WebRequest
import java.util.concurrent.CompletableFuture

@Component
@Primary // <= Mark it as Primary to override the default one
class ErsanGraphQLInvocation(private val graphQL: GraphQL) : GraphQLInvocation {
    override fun invoke(invocationData: GraphQLInvocationData,
        webRequest: WebRequest): CompletableFuture<ExecutionResult> {

        val context = "Context" //Basically any class you want <=====

        val executionInput = ExecutionInput.newExecutionInput()
            .query(invocationData.query)
            .operationName(invocationData.operationName)
            .variables(invocationData.variables)
            .context(context)
            .build()
        return graphQL.executeAsync(executionInput)
    }
}
fun appVersionFetcher(): DataFetcher<Boolean> {
    return DataFetcher { dataFetchingEnvironment ->
        val context = dataFetchingEnvironment.getContext<String>()
        println("Context $context")
        false
    }
}