Handle context path in GraphiQlHandler

Prior to this commit, the MVC `GraphiQlHandler` variant would not
generate a redirect link with the context path prefix.

This commit takes the context path into account and adds test coverage
to both variants.

Fixes gh-231
This commit is contained in:
Brian Clozel
2022-01-07 20:33:09 +01:00
parent fcb86e00d3
commit 1dc328cf65
3 changed files with 210 additions and 1 deletions

View File

@@ -69,7 +69,9 @@ public class GraphiQlHandler {
}
private URI getRedirectUrl(ServerRequest request) {
return request.uriBuilder().queryParam("path", this.graphQlPath).build();
String contextPath = request.requestPath().contextPath().toString();
String path = request.requestPath().pathWithinApplication().toString();
return request.uriBuilder().replacePath(contextPath).path(path).queryParam("path", this.graphQlPath).build();
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2020-2022 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.graphql.web.webflux;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.core.codec.ResourceEncoder;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GraphiQlHandler}.
* @author Brian Clozel
*/
class GraphiQlHandlerTests {
private static final List<HttpMessageReader<?>> MESSAGE_READERS = Collections.emptyList();
private final GraphiQlHandler handler = new GraphiQlHandler("/graphql",
new ByteArrayResource("GRAPHIQL".getBytes(StandardCharsets.UTF_8)));
@Test
void shouldRedirectWithPathQueryParameter() {
MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/graphiql").build();
MockServerWebExchange exchange = MockServerWebExchange.from(httpRequest);
ServerRequest request = ServerRequest.create(exchange, MESSAGE_READERS);
ServerResponse response = this.handler.handleRequest(request).block();
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
assertThat(response.headers().getLocation()).isNotNull();
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo("/graphiql?path=/graphql");
}
@Test
void shouldServeGraphiQlHtmlResource() {
MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/graphiql").queryParam("path", "/graphql").build();
MockServerWebExchange exchange = MockServerWebExchange.from(httpRequest);
ServerRequest request = ServerRequest.create(exchange, MESSAGE_READERS);
ServerResponse response = this.handler.handleRequest(request).block();
assertThat(response.statusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.headers().getContentType()).isEqualTo(MediaType.TEXT_HTML);
assertThat(getResponseContent(exchange, response)).isEqualTo("GRAPHIQL");
}
@Test
void shouldConsiderContextPathWhenRedirecting() {
MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/context/graphiql").contextPath("/context").build();
MockServerWebExchange exchange = MockServerWebExchange.from(httpRequest);
ServerRequest request = ServerRequest.create(exchange, MESSAGE_READERS);
assertThat(request.requestPath().contextPath().toString()).isEqualTo("/context");
assertThat(request.requestPath().pathWithinApplication().toString()).isEqualTo("/graphiql");
ServerResponse response = this.handler.handleRequest(request).block();
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
assertThat(response.headers().getLocation()).isNotNull();
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo("/context/graphiql?path=/graphql");
}
private String getResponseContent(MockServerWebExchange exchange, ServerResponse response) {
response.writeTo(exchange, new DefaultContext()).block();
return exchange.getResponse().getBodyAsString().block();
}
private static class DefaultContext implements ServerResponse.Context {
@Override
public List<HttpMessageWriter<?>> messageWriters() {
return Collections.singletonList(new EncoderHttpMessageWriter<>(new ResourceEncoder()));
}
@Override
public List<ViewResolver> viewResolvers() {
return Collections.emptyList();
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2020-2022 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.graphql.web.webmvc;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import javax.servlet.ServletException;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GraphiQlHandler}.
* @author Brian Clozel
*/
class GraphiQlHandlerTests {
private static final List<HttpMessageConverter<?>> MESSAGE_READERS = Collections.emptyList();
private GraphiQlHandler handler = new GraphiQlHandler("/graphql",
new ByteArrayResource("GRAPHIQL".getBytes(StandardCharsets.UTF_8)));
@Test
void shouldRedirectWithPathQueryParameter() {
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/graphiql");
ServerRequest request = ServerRequest.create(servletRequest, MESSAGE_READERS);
ServerResponse response = this.handler.handleRequest(request);
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
assertThat(response.headers().getLocation()).isNotNull();
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo("http://localhost/graphiql?path=/graphql");
}
@Test
void shouldServeGraphiQlHtmlResource() throws Exception {
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/graphiql");
servletRequest.addParameter("path", "/graphql");
ServerRequest request = ServerRequest.create(servletRequest, MESSAGE_READERS);
ServerResponse response = this.handler.handleRequest(request);
assertThat(response.statusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.headers().getContentType()).isEqualTo(MediaType.TEXT_HTML);
assertThat(getResponseContent(servletRequest, response)).isEqualTo("GRAPHIQL");
}
@Test
void shouldConsiderContextPathWhenRedirecting() {
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/context/graphiql");
servletRequest.setContextPath("/context");
ServerRequest request = ServerRequest.create(servletRequest, MESSAGE_READERS);
ServerResponse response = this.handler.handleRequest(request);
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
assertThat(response.headers().getLocation()).isNotNull();
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo("http://localhost/context/graphiql?path=/graphql");
}
private String getResponseContent(MockHttpServletRequest servletRequest, ServerResponse response) throws ServletException, IOException {
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
response.writeTo(servletRequest, servletResponse, new DefaultContext());
return servletResponse.getContentAsString();
}
private static class DefaultContext implements ServerResponse.Context {
@Override
public List<HttpMessageConverter<?>> messageConverters() {
return Collections.singletonList(new ResourceHttpMessageConverter());
}
}
}