Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/com/retailsvc/http/OpenApiServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ record HandlerConfig(
for (Map.Entry<String, RequestHandler> e : handlerConfig.extras().entrySet()) {
HttpContext extraCtx = httpServer.createContext(e.getKey());
extraCtx.getFilters().add(new ExceptionFilter(exceptionHandler, renderer));
extraCtx.setHandler(new ExtraRouteAdapter(e.getValue(), renderer));
extraCtx.setHandler(new ExtraRouteAdapter(e.getKey(), e.getValue(), renderer));
}

if (!"/".equals(basePath)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.retailsvc.http.internal;

import com.retailsvc.http.NotFoundException;
import com.retailsvc.http.Request;
import com.retailsvc.http.RequestHandler;
import com.retailsvc.http.Response;
Expand All @@ -19,16 +20,22 @@
*/
public final class ExtraRouteAdapter implements HttpHandler {

private final String path;
private final RequestHandler handler;
private final ResponseRenderer renderer;

public ExtraRouteAdapter(RequestHandler handler, ResponseRenderer renderer) {
public ExtraRouteAdapter(String path, RequestHandler handler, ResponseRenderer renderer) {
this.path = path;
this.handler = handler;
this.renderer = renderer;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
String requested = exchange.getRequestURI().getPath();
if (!path.equals(requested)) {
throw new NotFoundException(exchange.getRequestMethod() + " " + requested);
}
byte[] body = exchange.getRequestBody().readAllBytes();
HttpMethod method = HttpMethod.parse(exchange.getRequestMethod());
var headers = exchange.getRequestHeaders();
Expand Down
100 changes: 100 additions & 0 deletions src/test/java/com/retailsvc/http/ExactUrlMatchingIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.retailsvc.http;

import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.net.HttpURLConnection.HTTP_OK;
import static org.assertj.core.api.Assertions.assertThat;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.Map;
import org.junit.jupiter.api.Test;

class ExactUrlMatchingIT extends ServerBaseTest {

@Test
void extraRouteRejectsTrailingSuffix() throws Exception {
try (var s =
newBuilder()
.spec(spec)
.handlers(stubAllHandlers(Map.of()))
.port(0)
.extraRoute("/alive", Handlers.aliveHandler())
.build();
var client = httpClient()) {

HttpResponse<String> resp = get(client, s, "/alive232");

assertThat(resp.statusCode()).isEqualTo(HTTP_NOT_FOUND);
}
}

@Test
void extraRouteRejectsSubPath() throws Exception {
try (var s =
newBuilder()
.spec(spec)
.handlers(stubAllHandlers(Map.of()))
.port(0)
.extraRoute("/alive", Handlers.aliveHandler())
.build();
var client = httpClient()) {

HttpResponse<String> resp = get(client, s, "/alive/34");

assertThat(resp.statusCode()).isEqualTo(HTTP_NOT_FOUND);
}
}

@Test
void extraRouteAcceptsExactPath() throws Exception {
try (var s =
newBuilder()
.spec(spec)
.handlers(stubAllHandlers(Map.of()))
.port(0)
.extraRoute("/alive", Handlers.aliveHandler())
.build();
var client = httpClient()) {

HttpResponse<String> resp = get(client, s, "/alive");

assertThat(resp.statusCode()).isEqualTo(204);
}
}

@Test
void specRouteRejectsTrailingSuffix() throws Exception {
Map<String, RequestHandler> handlers = Map.of("get-data", req -> Response.status(HTTP_OK));
try (var s = newBuilder().spec(spec).handlers(stubAllHandlers(handlers)).port(0).build();
var client = httpClient()) {

HttpResponse<String> resp = get(client, s, "/api/v1/data232");

assertThat(resp.statusCode()).isEqualTo(HTTP_NOT_FOUND);
}
}

@Test
void specRouteRejectsBasePathSuffix() throws Exception {
try (var s = newBuilder().spec(spec).handlers(stubAllHandlers(Map.of())).port(0).build();
var client = httpClient()) {

HttpResponse<String> resp = get(client, s, "/api/v1xyz/data");

assertThat(resp.statusCode()).isEqualTo(HTTP_NOT_FOUND);
}
}

private HttpResponse<String> get(HttpClient client, OpenApiServer s, String path)
throws Exception {
var req =
HttpRequest.newBuilder()
.uri(URI.create("http://localhost:" + s.listenPort() + path))
.GET()
.build();
return client.send(req, BodyHandlers.ofString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void buildsRequestWithMethodQueryHeadersAndBodyBytesAndNullOperationId() throws

Map<String, TypeMapper> mappers = Map.of("application/json", new GsonTypeMapper());
ResponseRenderer renderer = new ResponseRenderer(mappers);
ExtraRouteAdapter adapter = new ExtraRouteAdapter(handler, renderer);
ExtraRouteAdapter adapter = new ExtraRouteAdapter("/alive", handler, renderer);

HttpExchange ex = mock(HttpExchange.class);
Headers reqHeaders = new Headers();
Expand Down
Loading