micronaut-core: Provide a way to read the request body in a filter when the route does not read it

This is a enhancement request

I want to implement a custom HttpServerFilter, to get POST request and body (json format). But i have the issue when try to read body with method request.getBody it’s always empty, to solve a have defined an action with @Post and @Body annotation into controller. But i don’t want to create action for each api i need. regs

I need a filter this a method like this:

Publisher<HttpHttpResponse<T>> readBody(HttpRequest<?> pRequest, ServerFilterChain pChain, Class<T> type)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 8
  • Comments: 31 (12 by maintainers)

Commits related to this issue

Most upvoted comments

I have this problem too 😦 We want to do request forwarding on our gateway with minimal side effects, and service discovery, which works just fine, unless we want to forward a request with body.

There is a not so nice workaround, you have to provide fake controller actions for every request with a body:

@Controller("/")
class FakeController {

    @Put("/full-path-to-match/user/{userId}/search-agent")
    fun upsertSearchAgent(userId: String, @Valid @Body searchAgent: Any): Single<Any> {
        return Single.just(null)
    }
}

Big +1 for this feature request, I think it would be super helpful in a lot of cases, if we could use the request body in HttpServerFilter without the @Body annotation.

PR submitted including an API to proxy requests from a filter https://github.com/micronaut-projects/micronaut-core/pull/3068

My current view on this issue is that there are 2 distinct use cases:

  • Low level access to the raw request / response bytes
  • Proxying gateway

Filters are not really designed for either of these on their own. They work at the level of objects that have already been decoded or are to be encoded.

To support these use cases my current intention is to allow users to extend Micronaut’s Netty pipeline so that low level access to the raw byte buffers can be obtained for use cases like caching, tracing etc.

For proxying / gateway a new interface ProxyClient or GatewayClient will be introduced which will allow filters and/or controllers to proxy requests to another service or services.

I have the same problem, i want to proxy any request using filter but the body of request it was empty. To solve I have added a fake controller and action to have the body available at filter level.

On Tue, Nov 12, 2019 at 11:01 AM Graeme Rocher notifications@github.com wrote:

@nhoughto https://github.com/nhoughto So again that sounds like a limitation which should take away rather than trying to add something that can break downstream controllers. Something like:

@Controllerclass CatchAllController { @Any(“{+path}”) void handle(HttpRequest request) { … } }

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/micronaut-projects/micronaut-core/issues/1113?email_source=notifications&email_token=AAG74DZ7KRK6S6D4O2WE7RTQTJ5GDA5CNFSM4GQC5BTKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDZWKWA#issuecomment-552822104, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAG74D3DBRSEOT5IVY5KMODQTJ5GDANCNFSM4GQC5BTA .

– Claudio Degioanni Skype: claudiodegio

Working on a similar use case. An example on how to build a transparent API Gateway that forwards requests and responses and logs the request and response bodies would go a long way.

https://github.com/micronaut-projects/micronaut-core/pull/3068 should not close this issue.

In our case, we have a webhook which we would like to log any requests that are not in conformity with the data class specified with @Body.

If the data class cannot be created, we end up with an empty body.

Can this be reopened?

Well another use case is for a Caching HttpServerFilter. If say we wanted to use the post body as the cache key (well an MD5 of the post body bytes), it would be nice to be able to always get that post body as bytes in a consistent way. Currently for application/json the body is available as an ObjectNode, but for a application/json-rpc the body is available as a CompositeByteBuf. It really should be possible to always get it as bytes (or ByteBuffer etc) via an Optional.