Search in sources :

Example 1 with WebInput

use of org.springframework.graphql.web.WebInput in project spring-graphql by spring-projects.

the class WebGraphQlClientBuilderTests method mutateDocumentSource.

@ParameterizedTest
@MethodSource("argumentSource")
void mutateDocumentSource(ClientBuilderSetup builderSetup) {
    DocumentSource documentSource = name -> name.equals("name") ? Mono.just(DOCUMENT) : Mono.error(new IllegalArgumentException());
    // Original
    WebGraphQlClient.Builder<?> builder = builderSetup.initBuilder().documentSource(documentSource);
    WebGraphQlClient client = builder.build();
    client.documentName("name").execute().block(TIMEOUT);
    WebInput input = builderSetup.getWebInput();
    assertThat(input.getDocument()).isEqualTo(DOCUMENT);
    // Mutate
    client = client.mutate().build();
    client.documentName("name").execute().block(TIMEOUT);
    input = builderSetup.getWebInput();
    assertThat(input.getDocument()).isEqualTo(DOCUMENT);
}
Also used : RouterFunctions(org.springframework.web.reactive.function.server.RouterFunctions) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) DecodingException(org.springframework.core.codec.DecodingException) WebClient(org.springframework.web.reactive.function.client.WebClient) HashMap(java.util.HashMap) TestWebSocketClient(org.springframework.graphql.web.TestWebSocketClient) ExecutionResult(graphql.ExecutionResult) DocumentSource(org.springframework.graphql.support.DocumentSource) MimeType(org.springframework.util.MimeType) Duration(java.time.Duration) Map(java.util.Map) TestWebSocketConnection(org.springframework.graphql.web.TestWebSocketConnection) HttpHandlerConnector(org.springframework.test.web.reactive.server.HttpHandlerConnector) WebInterceptor(org.springframework.graphql.web.WebInterceptor) Nullable(org.springframework.lang.Nullable) WebSocketHandler(org.springframework.web.reactive.socket.WebSocketHandler) URI(java.net.URI) ResolvableType(org.springframework.core.ResolvableType) ExecutionResultImpl(graphql.ExecutionResultImpl) MethodSource(org.junit.jupiter.params.provider.MethodSource) RouterFunctions.route(org.springframework.web.reactive.function.server.RouterFunctions.route) Jackson2JsonDecoder(org.springframework.http.codec.json.Jackson2JsonDecoder) WebGraphQlHandler(org.springframework.graphql.web.WebGraphQlHandler) Mono(reactor.core.publisher.Mono) DataBuffer(org.springframework.core.io.buffer.DataBuffer) HandlerStrategies(org.springframework.web.reactive.function.server.HandlerStrategies) ExecutionInput(graphql.ExecutionInput) Test(org.junit.jupiter.api.Test) ClientCodecConfigurer(org.springframework.http.codec.ClientCodecConfigurer) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Stream(java.util.stream.Stream) WebInput(org.springframework.graphql.web.WebInput) HttpHandler(org.springframework.http.server.reactive.HttpHandler) RouterFunction(org.springframework.web.reactive.function.server.RouterFunction) ServerResponse(org.springframework.web.reactive.function.server.ServerResponse) GraphQlWebSocketHandler(org.springframework.graphql.web.webflux.GraphQlWebSocketHandler) Collections(java.util.Collections) RequestOutput(org.springframework.graphql.RequestOutput) GraphQlHttpHandler(org.springframework.graphql.web.webflux.GraphQlHttpHandler) Assert(org.springframework.util.Assert) DocumentSource(org.springframework.graphql.support.DocumentSource) WebInput(org.springframework.graphql.web.WebInput) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 2 with WebInput

use of org.springframework.graphql.web.WebInput in project spring-graphql by spring-projects.

the class WebGraphQlTesterBuilderTests method mutateDocumentSource.

@ParameterizedTest
@MethodSource("argumentSource")
void mutateDocumentSource(TesterBuilderSetup builderSetup) {
    DocumentSource documentSource = name -> name.equals("name") ? Mono.just(DOCUMENT) : Mono.error(new IllegalArgumentException());
    // Original
    WebGraphQlTester.Builder<?> builder = builderSetup.initBuilder().documentSource(documentSource);
    WebGraphQlTester tester = builder.build();
    tester.documentName("name").execute();
    WebInput input = builderSetup.getWebInput();
    assertThat(input.getDocument()).isEqualTo(DOCUMENT);
    // Mutate
    tester = tester.mutate().build();
    tester.documentName("name").execute();
    input = builderSetup.getWebInput();
    assertThat(input.getDocument()).isEqualTo(DOCUMENT);
}
Also used : Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) DecodingException(org.springframework.core.codec.DecodingException) HashMap(java.util.HashMap) TestWebSocketClient(org.springframework.graphql.web.TestWebSocketClient) ExecutionResult(graphql.ExecutionResult) DocumentSource(org.springframework.graphql.support.DocumentSource) WebTestClient(org.springframework.test.web.reactive.server.WebTestClient) MimeType(org.springframework.util.MimeType) Duration(java.time.Duration) Map(java.util.Map) TestWebSocketConnection(org.springframework.graphql.web.TestWebSocketConnection) WebInterceptor(org.springframework.graphql.web.WebInterceptor) Nullable(org.springframework.lang.Nullable) WebSocketHandler(org.springframework.web.reactive.socket.WebSocketHandler) URI(java.net.URI) ResolvableType(org.springframework.core.ResolvableType) ExecutionResultImpl(graphql.ExecutionResultImpl) MethodSource(org.junit.jupiter.params.provider.MethodSource) RouterFunctions.route(org.springframework.web.reactive.function.server.RouterFunctions.route) Jackson2JsonDecoder(org.springframework.http.codec.json.Jackson2JsonDecoder) WebGraphQlHandler(org.springframework.graphql.web.WebGraphQlHandler) Mono(reactor.core.publisher.Mono) DataBuffer(org.springframework.core.io.buffer.DataBuffer) ExecutionInput(graphql.ExecutionInput) Test(org.junit.jupiter.api.Test) ClientCodecConfigurer(org.springframework.http.codec.ClientCodecConfigurer) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Stream(java.util.stream.Stream) WebInput(org.springframework.graphql.web.WebInput) RouterFunction(org.springframework.web.reactive.function.server.RouterFunction) ServerResponse(org.springframework.web.reactive.function.server.ServerResponse) GraphQlWebSocketHandler(org.springframework.graphql.web.webflux.GraphQlWebSocketHandler) Collections(java.util.Collections) RequestOutput(org.springframework.graphql.RequestOutput) GraphQlHttpHandler(org.springframework.graphql.web.webflux.GraphQlHttpHandler) Assert(org.springframework.util.Assert) DocumentSource(org.springframework.graphql.support.DocumentSource) WebInput(org.springframework.graphql.web.WebInput) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 3 with WebInput

use of org.springframework.graphql.web.WebInput in project spring-graphql by spring-projects.

the class GraphQlWebSocketHandler method handle.

@Override
public Mono<Void> handle(WebSocketSession session) {
    HandshakeInfo handshakeInfo = session.getHandshakeInfo();
    if ("graphql-ws".equalsIgnoreCase(handshakeInfo.getSubProtocol())) {
        if (logger.isDebugEnabled()) {
            logger.debug("apollographql/subscriptions-transport-ws is not supported, nor maintained. " + "Please, use https://github.com/enisdenjo/graphql-ws.");
        }
        return session.close(GraphQlStatus.INVALID_MESSAGE_STATUS);
    }
    // Session state
    AtomicReference<Map<String, Object>> connectionInitPayloadRef = new AtomicReference<>();
    Map<String, Subscription> subscriptions = new ConcurrentHashMap<>();
    Mono.delay(this.initTimeoutDuration).then(Mono.defer(() -> connectionInitPayloadRef.compareAndSet(null, Collections.emptyMap()) ? session.close(GraphQlStatus.INIT_TIMEOUT_STATUS) : Mono.empty())).subscribe();
    session.closeStatus().doOnSuccess(closeStatus -> {
        Map<String, Object> connectionInitPayload = connectionInitPayloadRef.get();
        if (connectionInitPayload == null) {
            return;
        }
        int statusCode = (closeStatus != null ? closeStatus.getCode() : 1005);
        this.webSocketInterceptor.handleConnectionClosed(session.getId(), statusCode, connectionInitPayload);
    }).subscribe();
    return session.send(session.receive().flatMap(webSocketMessage -> {
        GraphQlMessage message = this.codecDelegate.decode(webSocketMessage);
        String id = message.getId();
        Map<String, Object> payload = message.getPayload();
        switch(message.resolvedType()) {
            case SUBSCRIBE:
                if (connectionInitPayloadRef.get() == null) {
                    return GraphQlStatus.close(session, GraphQlStatus.UNAUTHORIZED_STATUS);
                }
                if (id == null) {
                    return GraphQlStatus.close(session, GraphQlStatus.INVALID_MESSAGE_STATUS);
                }
                WebInput input = new WebInput(handshakeInfo.getUri(), handshakeInfo.getHeaders(), payload, id, null);
                if (logger.isDebugEnabled()) {
                    logger.debug("Executing: " + input);
                }
                return this.graphQlHandler.handleRequest(input).flatMapMany((output) -> handleWebOutput(session, id, subscriptions, output)).doOnTerminate(() -> subscriptions.remove(id));
            case PING:
                return Flux.just(this.codecDelegate.encode(session, GraphQlMessage.pong(null)));
            case COMPLETE:
                if (id != null) {
                    Subscription subscription = subscriptions.remove(id);
                    if (subscription != null) {
                        subscription.cancel();
                    }
                    return this.webSocketInterceptor.handleCancelledSubscription(session.getId(), id).thenMany(Flux.empty());
                }
                return Flux.empty();
            case CONNECTION_INIT:
                if (!connectionInitPayloadRef.compareAndSet(null, payload)) {
                    return GraphQlStatus.close(session, GraphQlStatus.TOO_MANY_INIT_REQUESTS_STATUS);
                }
                return this.webSocketInterceptor.handleConnectionInitialization(session.getId(), payload).defaultIfEmpty(Collections.emptyMap()).map(ackPayload -> this.codecDelegate.encodeConnectionAck(session, ackPayload)).flux().onErrorResume(ex -> GraphQlStatus.close(session, GraphQlStatus.UNAUTHORIZED_STATUS));
            default:
                return GraphQlStatus.close(session, GraphQlStatus.INVALID_MESSAGE_STATUS);
        }
    }));
}
Also used : GraphQlMessage(org.springframework.graphql.web.support.GraphQlMessage) Arrays(java.util.Arrays) WebSocketSession(org.springframework.web.reactive.socket.WebSocketSession) CloseStatus(org.springframework.web.reactive.socket.CloseStatus) WebOutput(org.springframework.graphql.web.WebOutput) AtomicReference(java.util.concurrent.atomic.AtomicReference) ExecutionResult(graphql.ExecutionResult) Duration(java.time.Duration) Map(java.util.Map) WebSocketHandler(org.springframework.web.reactive.socket.WebSocketHandler) WebGraphQlHandler(org.springframework.graphql.web.WebGraphQlHandler) HandshakeInfo(org.springframework.web.reactive.socket.HandshakeInfo) Publisher(org.reactivestreams.Publisher) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Mono(reactor.core.publisher.Mono) CodecConfigurer(org.springframework.http.codec.CodecConfigurer) Flux(reactor.core.publisher.Flux) List(java.util.List) WebInput(org.springframework.graphql.web.WebInput) CollectionUtils(org.springframework.util.CollectionUtils) Subscription(org.reactivestreams.Subscription) WebSocketMessage(org.springframework.web.reactive.socket.WebSocketMessage) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Collections(java.util.Collections) WebSocketInterceptor(org.springframework.graphql.web.WebSocketInterceptor) Assert(org.springframework.util.Assert) GraphQlMessage(org.springframework.graphql.web.support.GraphQlMessage) WebInput(org.springframework.graphql.web.WebInput) AtomicReference(java.util.concurrent.atomic.AtomicReference) Subscription(org.reactivestreams.Subscription) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HandshakeInfo(org.springframework.web.reactive.socket.HandshakeInfo)

Example 4 with WebInput

use of org.springframework.graphql.web.WebInput in project spring-graphql by spring-projects.

the class GraphQlHttpHandler method handleRequest.

/**
 * Handle GraphQL requests over HTTP.
 * @param request the incoming HTTP request
 * @return the HTTP response
 * @throws ServletException may be raised when reading the request body, e.g.
 * {@link HttpMediaTypeNotSupportedException}.
 */
public ServerResponse handleRequest(ServerRequest request) throws ServletException {
    WebInput input = new WebInput(request.uri(), request.headers().asHttpHeaders(), readBody(request), this.idGenerator.generateId().toString(), LocaleContextHolder.getLocale());
    if (logger.isDebugEnabled()) {
        logger.debug("Executing: " + input);
    }
    Mono<ServerResponse> responseMono = this.graphQlHandler.handleRequest(input).map((output) -> {
        if (logger.isDebugEnabled()) {
            logger.debug("Execution complete");
        }
        ServerResponse.BodyBuilder builder = ServerResponse.ok();
        builder.headers(headers -> headers.putAll(output.getResponseHeaders()));
        return builder.body(output.toSpecification());
    });
    return ServerResponse.async(responseMono);
}
Also used : ServerResponse(org.springframework.web.servlet.function.ServerResponse) WebInput(org.springframework.graphql.web.WebInput)

Example 5 with WebInput

use of org.springframework.graphql.web.WebInput in project spring-graphql by spring-projects.

the class GraphQlWebSocketHandler method handleTextMessage.

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage webSocketMessage) throws Exception {
    GraphQlMessage message = decode(webSocketMessage);
    String id = message.getId();
    Map<String, Object> payload = message.getPayload();
    SessionState sessionState = getSessionInfo(session);
    switch(message.resolvedType()) {
        case SUBSCRIBE:
            if (sessionState.getConnectionInitPayload() == null) {
                GraphQlStatus.closeSession(session, GraphQlStatus.UNAUTHORIZED_STATUS);
                return;
            }
            if (id == null) {
                GraphQlStatus.closeSession(session, GraphQlStatus.INVALID_MESSAGE_STATUS);
                return;
            }
            URI uri = session.getUri();
            Assert.notNull(uri, "Expected handshake url");
            HttpHeaders headers = session.getHandshakeHeaders();
            WebInput input = new WebInput(uri, headers, payload, id, null);
            if (logger.isDebugEnabled()) {
                logger.debug("Executing: " + input);
            }
            this.graphQlHandler.handleRequest(input).flatMapMany((output) -> handleWebOutput(session, input.getId(), output)).publishOn(// Serial blocking send via single thread
            sessionState.getScheduler()).subscribe(new SendMessageSubscriber(id, session, sessionState));
            return;
        case PING:
            session.sendMessage(encode(GraphQlMessage.pong(null)));
            return;
        case COMPLETE:
            if (id != null) {
                Subscription subscription = sessionState.getSubscriptions().remove(id);
                if (subscription != null) {
                    subscription.cancel();
                }
                this.webSocketInterceptor.handleCancelledSubscription(session.getId(), id).block(Duration.ofSeconds(10));
            }
            return;
        case CONNECTION_INIT:
            if (!sessionState.setConnectionInitPayload(payload)) {
                GraphQlStatus.closeSession(session, GraphQlStatus.TOO_MANY_INIT_REQUESTS_STATUS);
                return;
            }
            this.webSocketInterceptor.handleConnectionInitialization(session.getId(), payload).defaultIfEmpty(Collections.emptyMap()).publishOn(// Serial blocking send via single thread
            sessionState.getScheduler()).doOnNext(ackPayload -> {
                TextMessage outputMessage = encode(GraphQlMessage.connectionAck(ackPayload));
                try {
                    session.sendMessage(outputMessage);
                } catch (IOException ex) {
                    throw new IllegalStateException(ex);
                }
            }).onErrorResume(ex -> {
                GraphQlStatus.closeSession(session, GraphQlStatus.UNAUTHORIZED_STATUS);
                return Mono.empty();
            }).block(Duration.ofSeconds(10));
            return;
        default:
            GraphQlStatus.closeSession(session, GraphQlStatus.INVALID_MESSAGE_STATUS);
    }
}
Also used : GraphQlMessage(org.springframework.graphql.web.support.GraphQlMessage) Arrays(java.util.Arrays) ByteArrayOutputStream(java.io.ByteArrayOutputStream) WebOutput(org.springframework.graphql.web.WebOutput) Scheduler(reactor.core.scheduler.Scheduler) AtomicReference(java.util.concurrent.atomic.AtomicReference) WebSocketSession(org.springframework.web.socket.WebSocketSession) CloseStatus(org.springframework.web.socket.CloseStatus) ExecutionResult(graphql.ExecutionResult) TextMessage(org.springframework.web.socket.TextMessage) TextWebSocketHandler(org.springframework.web.socket.handler.TextWebSocketHandler) ByteArrayInputStream(java.io.ByteArrayInputStream) GraphQLError(graphql.GraphQLError) Duration(java.time.Duration) Map(java.util.Map) Schedulers(reactor.core.scheduler.Schedulers) Nullable(org.springframework.lang.Nullable) URI(java.net.URI) OutputStream(java.io.OutputStream) WebGraphQlHandler(org.springframework.graphql.web.WebGraphQlHandler) HttpHeaders(org.springframework.http.HttpHeaders) ExceptionWebSocketHandlerDecorator(org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator) Publisher(org.reactivestreams.Publisher) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) IOException(java.io.IOException) Mono(reactor.core.publisher.Mono) GraphqlErrorBuilder(graphql.GraphqlErrorBuilder) BaseSubscriber(reactor.core.publisher.BaseSubscriber) Flux(reactor.core.publisher.Flux) List(java.util.List) GraphQlMessageType(org.springframework.graphql.web.support.GraphQlMessageType) HttpInputMessage(org.springframework.http.HttpInputMessage) WebInput(org.springframework.graphql.web.WebInput) HttpMessageConverter(org.springframework.http.converter.HttpMessageConverter) CollectionUtils(org.springframework.util.CollectionUtils) Subscription(org.reactivestreams.Subscription) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Collections(java.util.Collections) WebSocketInterceptor(org.springframework.graphql.web.WebSocketInterceptor) SubProtocolCapable(org.springframework.web.socket.SubProtocolCapable) InputStream(java.io.InputStream) HttpOutputMessage(org.springframework.http.HttpOutputMessage) GenericHttpMessageConverter(org.springframework.http.converter.GenericHttpMessageConverter) Assert(org.springframework.util.Assert) HttpHeaders(org.springframework.http.HttpHeaders) GraphQlMessage(org.springframework.graphql.web.support.GraphQlMessage) IOException(java.io.IOException) URI(java.net.URI) WebInput(org.springframework.graphql.web.WebInput) Subscription(org.reactivestreams.Subscription) TextMessage(org.springframework.web.socket.TextMessage)

Aggregations

WebInput (org.springframework.graphql.web.WebInput)8 Map (java.util.Map)7 WebGraphQlHandler (org.springframework.graphql.web.WebGraphQlHandler)7 Assert (org.springframework.util.Assert)7 Mono (reactor.core.publisher.Mono)7 ExecutionResult (graphql.ExecutionResult)6 Duration (java.time.Duration)6 Collections (java.util.Collections)6 URI (java.net.URI)5 Nullable (org.springframework.lang.Nullable)5 ServerResponse (org.springframework.web.reactive.function.server.ServerResponse)5 WebSocketHandler (org.springframework.web.reactive.socket.WebSocketHandler)5 ExecutionInput (graphql.ExecutionInput)4 ExecutionResultImpl (graphql.ExecutionResultImpl)4 HashMap (java.util.HashMap)4 Stream (java.util.stream.Stream)4 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)4 Test (org.junit.jupiter.api.Test)4 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)4 MethodSource (org.junit.jupiter.params.provider.MethodSource)4