Skip to content

Commit

Permalink
Additional headers and status change implementation changed; addition…
Browse files Browse the repository at this point in the history
…al tests added;
  • Loading branch information
steel-judoka committed Sep 18, 2021
1 parent 69ebd69 commit 1c65d6d
Show file tree
Hide file tree
Showing 14 changed files with 189 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@ public ServerHttpResponse setStatusCode(int code) {
return this;
}

@Override
public int getStatusCode() {
return response.getStatus();
}

@Override
public ServerHttpResponse end() {
try {
Expand Down Expand Up @@ -388,6 +393,13 @@ public ServerHttpResponse setResponseHeader(CharSequence name, Iterable<CharSequ
return this;
}

@Override
public void clearResponseHeaders() {
for (String header : response.getHeaderNames()){
response.setHeader(header, null);
}
}

@Override
public Iterable<Map.Entry<String, String>> getAllResponseHeaders() {
List<Map.Entry<String, String>> ret = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public List<HandlerChainCustomizer> scan(MethodInfo method, ClassInfo actualEndp
ResponseStatusHandler handler = new ResponseStatusHandler();
handler.setStatus(responseStatusValue.asInt());
return Collections.singletonList(new FixedHandlerChainCustomizer(handler,
HandlerChainCustomizer.Phase.AFTER_METHOD_INVOKE));
HandlerChainCustomizer.Phase.BEFORE_METHOD_INVOKE));
}
});
}
Expand Down Expand Up @@ -223,7 +223,7 @@ public List<HandlerChainCustomizer> scan(MethodInfo method, ClassInfo actualEndp
ResponseHeaderHandler handler = new ResponseHeaderHandler();
handler.setHeaders(headers);
return Collections.singletonList(new FixedHandlerChainCustomizer(handler,
HandlerChainCustomizer.Phase.AFTER_METHOD_INVOKE));
HandlerChainCustomizer.Phase.BEFORE_METHOD_INVOKE));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static org.junit.jupiter.api.Assertions.*;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
Expand Down Expand Up @@ -52,6 +54,32 @@ public void should_return_added_headers_multi() {
.headers(expectedHeaders);
}

@Test
public void should_return_added_headers_completion() {
Map<String, String> expectedHeaders = Map.of(
"Access-Control-Allow-Origin", "*",
"Keep-Alive", "timeout=5, max=997");
RestAssured
.given()
.get("/test/completion")
.then()
.statusCode(200)
.headers(expectedHeaders);
}

@Test
public void should_return_added_headers_plain() {
Map<String, String> expectedHeaders = Map.of(
"Access-Control-Allow-Origin", "*",
"Keep-Alive", "timeout=5, max=997");
RestAssured
.given()
.get("/test/plain")
.then()
.statusCode(200)
.headers(expectedHeaders);
}

@Test
public void should_throw_exception_without_headers_uni() {
Headers headers = RestAssured.given().get("/test/exception_uni")
Expand All @@ -67,6 +95,20 @@ public void should_throw_exception_without_headers_multi() {
assertFalse(headers.hasHeaderWithName("Access-Control-Allow-Origin"));
}

@Test
public void should_throw_exception_without_headers_completion() {
Headers headers = RestAssured.given().get("/test/exception_completion")
.then().extract().headers();
assertFalse(headers.hasHeaderWithName("Access-Control-Allow-Origin"));
}

@Test
public void should_throw_exception_without_headers_plain() {
Headers headers = RestAssured.given().get("/test/exception_plain")
.then().extract().headers();
assertFalse(headers.hasHeaderWithName("Access-Control-Allow-Origin"));
}

@Path("/test")
public static class TestResource {

Expand All @@ -90,6 +132,26 @@ public Multi<String> getTestMulti() {
return Multi.createFrom().item("test");
}

@ResponseHeader(headers = {
@Header(name = "Access-Control-Allow-Origin", value = "*"),
@Header(name = "Keep-Alive", value = "timeout=5, max=997"),
})
@GET
@Path("/completion")
public CompletionStage<String> getTestCompletion() {
return CompletableFuture.supplyAsync(() -> "test");
}

@ResponseHeader(headers = {
@Header(name = "Access-Control-Allow-Origin", value = "*"),
@Header(name = "Keep-Alive", value = "timeout=5, max=997"),
})
@GET
@Path("/plain")
public String getTestPlain() {
return "test";
}

@ResponseHeader(headers = {
@Header(name = "Access-Control-Allow-Origin", value = "*")
})
Expand All @@ -107,5 +169,22 @@ public Uni<String> throwExceptionUni() {
public Multi<String> throwExceptionMulti() {
return Multi.createFrom().failure(new IllegalArgumentException());
}

@ResponseHeader(headers = {
@Header(name = "Access-Control-Allow-Origin", value = "*")
})
@Path("/exception_completion")
public CompletionStage<String> throwExceptionCompletion() {
return CompletableFuture.failedFuture(new IllegalArgumentException());
}

@ResponseHeader(headers = {
@Header(name = "Access-Control-Allow-Origin", value = "*")
})
@GET
@Path("/exception_plain")
public String throwExceptionPlain() {
throw new IllegalArgumentException();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.quarkus.resteasy.reactive.server.test.responsestatus;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

Expand Down Expand Up @@ -40,6 +43,26 @@ public void should_return_changed_status_multi() {
.statusCode(expectedStatus);
}

@Test
public void should_return_changed_status_completion() {
int expectedStatus = 201;
RestAssured
.given()
.get("/test/completion")
.then()
.statusCode(expectedStatus);
}

@Test
public void should_return_changed_status_plain() {
int expectedStatus = 201;
RestAssured
.given()
.get("/test/plain")
.then()
.statusCode(expectedStatus);
}

@Test
public void should_not_change_status_uni() {
int expectedStatus = 500;
Expand All @@ -60,6 +83,26 @@ public void should_not_change_status_multi() {
.statusCode(expectedStatus);
}

@Test
public void should_not_change_status_completion() {
int expectedStatus = 500;
RestAssured
.given()
.get("/test/exception_completion")
.then()
.statusCode(expectedStatus);
}

@Test
public void should_not_change_status_plain() {
int expectedStatus = 500;
RestAssured
.given()
.get("/test/exception_plain")
.then()
.statusCode(expectedStatus);
}

@Path("/test")
public static class TestResource {

Expand All @@ -77,6 +120,20 @@ public Multi<String> getTestMulti() {
return Multi.createFrom().item("test");
}

@Status(201)
@GET
@Path("/completion")
public CompletionStage<String> getTestCompletion() {
return CompletableFuture.supplyAsync(() -> "test");
}

@Status(201)
@GET
@Path("/plain")
public String getTestPlain() {
return "test";
}

@Status(201)
@GET
@Path(("/exception_uni"))
Expand All @@ -91,5 +148,19 @@ public Multi<String> throwExceptionMulti() {
return Multi.createFrom().failure(new IllegalArgumentException());
}

@Status(201)
@GET
@Path("/exception_completion")
public CompletionStage<String> throwExceptionCompletion() {
return CompletableFuture.failedFuture(new IllegalArgumentException());
}

@Status(201)
@GET
@Path("/exception_plain")
public String throwExceptionPlain() {
throw new IllegalArgumentException();
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public Map<String, String> getHeaders() {
@Override
public void handle(ResteasyReactiveRequestContext requestContext) throws Exception {
if (headers != null) {
requestContext.setResponseHeaders(headers);
for (Map.Entry<String, String> header : headers.entrySet()) {
requestContext.serverResponse().setResponseHeader(header.getKey(), header.getValue());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public int getStatus() {

@Override
public void handle(ResteasyReactiveRequestContext requestContext) throws Exception {
requestContext.setResponseStatus(status);
requestContext.serverResponse().setStatusCode(status);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.regex.Matcher;
import javax.ws.rs.core.Cookie;
Expand Down Expand Up @@ -133,9 +132,6 @@ public abstract class ResteasyReactiveRequestContext
*/
private List<UriMatch> matchedURIs;

private Map<String, String> responseHeaders;
private Integer responseStatus;

private AsyncResponseImpl asyncResponse;
private SseEventSinkImpl sseEventSink;
private List<PathSegment> pathSegments;
Expand Down Expand Up @@ -234,22 +230,6 @@ public void setMaxPathParams(int maxPathParams) {
}
}

public Map<String, String> getResponseHeaders() {
return responseHeaders;
}

public void setResponseHeaders(Map<String, String> responseHeaders) {
this.responseHeaders = responseHeaders;
}

public Integer getResponseStatus() {
return responseStatus;
}

public void setResponseStatus(Integer responseStatus) {
this.responseStatus = responseStatus;
}

public String getPathParam(int index) {
return doGetPathParam(index, pathParamValues);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.ws.rs.RuntimeType;
Expand Down Expand Up @@ -77,15 +76,11 @@ public static void setHeaders(ResteasyReactiveRequestContext context, ServerHttp
// FIXME: spec says we should flush the headers when first message is sent or when the resource method returns, whichever
// happens first
if (!response.headWritten()) {
response.setStatusCode(
context.getResponseStatus() != null ? context.getResponseStatus() : Response.Status.OK.getStatusCode());
if (response.getStatusCode() == 0) {
response.setStatusCode(Response.Status.OK.getStatusCode());
}
response.setResponseHeader(HttpHeaders.CONTENT_TYPE, context.getResponseContentType().toString());
response.setChunked(true);
if (context.getResponseHeaders() != null) {
for (Map.Entry<String, String> header : context.getResponseHeaders().entrySet()) {
response.addResponseHeader(header.getKey(), header.getValue());
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public void handle(ResteasyReactiveRequestContext requestContext) throws Excepti

result.handle((v, t) -> {
if (t != null) {
requestContext.serverResponse().clearResponseHeaders();
requestContext.handleException(t);
} else {
requestContext.setResult(v);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class ExceptionHandler implements ServerRestHandler {

@Override
public void handle(ResteasyReactiveRequestContext requestContext) throws Exception {
requestContext.serverResponse().clearResponseHeaders();
requestContext.mapExceptionIfPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public void onError(Throwable t) {
protected void handleException(ResteasyReactiveRequestContext requestContext, Throwable t) {
// in truth we can only send an exception if we haven't sent the headers yet, otherwise
// it will appear to be an SSE value, which is incorrect, so we should only log it and close the connection
requestContext.serverResponse().clearResponseHeaders();
if (requestContext.serverResponse().headWritten()) {
log.error("Exception in SSE server handling, impossible to send it to client", t);
} else {
Expand Down
Loading

0 comments on commit 1c65d6d

Please sign in to comment.