micronaut-core icon indicating copy to clipboard operation
micronaut-core copied to clipboard

Custom Http response status codes

Open hernancerm opened this issue 3 years ago • 1 comments

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

hernancerm avatar Jun 18 '21 20:06 hernancerm

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Jun 18 '21 20:06 CLAassistant

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 ?

yawkat avatar Oct 11 '22 10:10 yawkat

can the constants not exist within the HttpStatus interface? Why is HttpStatusStandard necessary?

graemerocher avatar Oct 11 '22 11:10 graemerocher

@graemerocher we can only use enum constants inside annotations, so we need some enum (unless we want to switch to strings...)

yawkat avatar Oct 11 '22 12:10 yawkat

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.

yawkat avatar Oct 12 '22 09:10 yawkat