micronaut-core
micronaut-core copied to clipboard
Custom Http response status codes
Related issue: #4791
Changes
Add custom response status support for implementations of HttpResponse
:
-
NettyMutableHttpResponse
-
SimpleHttpResponse
Also for implementations of HttpResponseFactory
:
-
NettyHttpResponseFactory
-
SimpleHttpResponseFactory
The previous changes allow invocations such as the following, creating custom response statuses:
HttpResponse.status(480); // Response status: 480 Client Error (480)
HttpResponse.status(480, "My Reason"); // Response status: 480 My Reason
HttpResponse.ok().status(480); // Response status: 480 Client Error (480)
HttpResponse.ok().status(480, "My Reason"); // Response status: 480 My Reason
Implement tests for the changes, in CustomResponseStatusSpec.groovy
Servlet runtimes
My changes work on the Netty runtime, however the response status is not consistent in Tomcat and Jetty. I haven't tested the other servlet runtimes but I'm thinking they wouldn't be consistent as well.
Tomcat
HttpResponse |
Expected status | Actual status |
---|---|---|
.status(480) |
480 Client Error (480) |
480 |
.status(480, "My Reason") |
480 My Reason |
480 |
.ok().status(480) |
480 Client Error (480) |
480 |
.ok().status(480, "My Reason") |
480 My Reason |
480 |
Jetty
HttpResponse |
Expected status | Actual status |
---|---|---|
.status(480) |
480 Client Error (480) |
480 480 |
.status(480, "My Reason") |
480 My Reason |
480 480 |
.ok().status(480) |
480 Client Error (480) |
480 480 |
.ok().status(480, "My Reason") |
480 My Reason |
480 480 |
This PR changes HttpStatus to be an interface, with the enum HttpStatusStandard containing the standard codes. For convenience, HttpStatus
has fields for the standard codes also, that are initialized similar to: HttpStatus OK = HttpStatusStandard.OK
.
This circular dependency will cause deadlocks. If one thread loads HttpStatus while another loads HttpStatusStandard, they will wait for each other forever. We can't use this approach.
Additionally, there seem to be some issues in kotlin with using an enum constant when the superinterface has a field of the same name.
This PR could still be "rescued" by going with a interface BaseHttpStatus, enum HttpStatus, class CustomHttpStatus structure instead. BaseHttpStatus would not have any constants for the standard status codes. WDYT @graemerocher ?
can the constants not exist within the HttpStatus
interface? Why is HttpStatusStandard
necessary?
@graemerocher we can only use enum constants inside annotations, so we need some enum (unless we want to switch to strings...)
Sorry it took so long. We decided not to go with this approach due to the problems introduced by the enum split. There seems to be no satisfactory approach that involves changing the HttpStatus api.
I've made a PR with a more limited solution in #8147.