2

I want to append some data to the incoming request. Like random generated token or uuid to the incoming request. And then I want to process it through the controller. I came to know about ClientHttpRequestInterceptor. But looking at this doc, it seems like it only intercept the response, it doesn't intercept the request. Which is what I am not looking. Is there any other way to do this ?

And how can I register this intercept in my RestController ? So that before controller process the request, the request should already has the data.

EDIT: I just found out, I can directly set the data in controller using set method in request body. And this is working. But I am not sure if this is recommended way. Because as far as I know the request has to be modified in dispatcher servlet.

Please advice.

Lokesh Pandey
  • 1,739
  • 23
  • 50

2 Answers2

2

You need to add your own OncePerRequestFilter implementation. In the next link you will be able to see an example of that:

Filter example

In this case, it uses TheadContext (MDC) to include the information you want to use in your controller layer (do not include "something similar" to MDC.remove(mdcTokenKey); in your code, you want to keep the information on MDC to access it in your controller).

PD: The internal server of Spring MVC: Tomcat, Jetty, etc reuses the threads so, if you don't want to have some problems it is important you include always a value in your "TheadContext cache". In that way, you will avoid to find "old values", I mean, values included in the current thread but in a "previous Http request".


UPDATE (modify the request body):

Take a look to the following link if you want to modify the request itself:

Modify request content before manage it in controller

doctore
  • 3,855
  • 2
  • 29
  • 45
  • I don't think this is allowing me to add the additional data to the incoming request. I am not trying to set the uuid for request. I am trying to set the uuid as a data in the request – Lokesh Pandey Jun 21 '20 at 10:07
  • In the above approach you will be able to do something similar, I mean, for every incomming request you will be able to include what you need in a ThreadContext cache and it wil be accesible in "every part" of your code (even reuse it to do another request to other microservice). However, I have updated the answer with an approach more similar you are looking for. – doctore Jun 21 '20 at 11:23
  • I just want to understand more, the way I did it is to set the value in controller. But I just want to know that if it's recommended to modify the data in controller ? I don't want that data to be accessible to other part of code or it's never going to reuse it – Lokesh Pandey Jun 21 '20 at 14:26
  • The answer depends of what you want to achieve. If you want to include the same information in all incoming requests, you have two options: `modify every incoming request body` (update section of my answer) or `create a filter to include what you need in the ThreadContext` (initial section of my answer). The advantage of the second approach is you don't need to prepare your Dtos (Java objects to store the information you receive in your controller methods), to work with those new properties. – doctore Jun 21 '20 at 15:51
  • However, if you only need that information in some of your controller methods, then there are more suitable approaches. Using the "setter method" you mention you will need to include it in every controller (or create a parent class for all of them) to manage it. – doctore Jun 21 '20 at 15:55
2

If you don't want to do it this way (How to modify request body before reaching controller in spring boot), you might do one of the following:

  1. OncePerRequestFilter (as mentioned in the @doctore answer) and add a parameter to the request. This would allow you to add data to the request, but not change anything sent by the client.
  2. Add a method in the controller and call it at the start of processing. I don't like this as much because unlike the filter approach, this requires you to call the method.
  3. [Note: I've never tried this, but it should work] Add a method [somewhere] and use Spring AOP to call it before entering the handler method in the controller. This is fine, but is essentially just you creating your own way of processing a OncePerRequestFilter.

There are surely other ways of doing this with Spring, I just don't know them.

DwB
  • 37,124
  • 11
  • 56
  • 82
  • I have gone through your answer mentioned in this answer :) +1. Now I know there are multiple ways to do that. But what I am really trying to understand that if it's recommended way to change the request body in controller ? – Lokesh Pandey Jun 24 '20 at 14:34
  • To the best of my knowledge, there is no "recommended" way to change the request body in a controller. The front end send the request body it wanted to send, changing it is, in a way, fraud. Here is an example, the user typed $12.00 payment. Your controller changes the value to $97.00 payment before it is logged in the handler method. That is not recommended. – DwB Jun 25 '20 at 17:04
  • I am generating uuid and password for a request which I don't want to do in client side. That's why I had to intercept the request. – Lokesh Pandey Jul 04 '20 at 09:17