#RequestHeader in spring not accepting fake headers - spring

I am using
#RequestHeader(value = "channel") String channel
in Spring application controller to get headers and it works fine for normal headers, however, in some cases, I need to trap a request using filter and use HttpServletRequestWrapper to add some extra headers. The new headers added by overriding getHeader method are not being accepted by #RequestHeader annotation and throws error. However, if I manually get headers using
HttpServletRequest.getHeader("channel")
the new headers work fine. Is there any bug in #RequestHeader implementation? If so, is there any work-around so that I wouldn't have to change the same thing in 50+ APIs.

When resolving #RequestHeader, Spring is using getHeaders(), not getHeader(). You need to override this one.

Related

Reactive rest client headers injection in Quarkus

I am following the guide of the new quarkus-resteasy-reactive-jackson extension to use it in an existing Quarkus application deployed in production.
In the Custom headers support section it's introduced the ClientHeadersFactory interface to allow injecting headers in a request, but you are forced to return a sync response. One can not use Uni<MultivaluedMap<String, String>>, which is of what is desired in my case, because I need to add a token in the header, and this token is retrieved by a request to another rest endpoint that returns a Uni<Token>.
How can I achieve this in the new implementation? If not possible, is there a workaround?
It's not possible to use Uni<MultivaluedMap<...>> in ClientHeadersFactory in Quarkus 2.2.x (and older versions). We may add such a feature in the near future.
Currently, you can #HeaderParam directly. Your code could probably look as follows:
Uni<String> token = tokenService.getToken();
token.onItem().transformToUni(tokenValue -> client.doTheCall(tokenValue));
Where the client interface would be something like:
#Path("/")
public interface MyClient {
#GET
Uni<Foo> doTheCall(#HeaderParam("token") String tokenValue);
}

Content type 'application/merge-patch+json' not supported when using spring webclient

using spring webclient to make http call. But found no MediaType defined for application/merge-patch+json. Anyway I hard injected the header Content-Type by headers.add("Content-Type", "application/merge-patch+json"); or .contentType(MediaType.valueOf("application/merge-patch+json")). Got same runtime error Content type 'application/merge-patch+json' not supported for bodyType=com.test.Account
I think the webclient block the call. Suggest to have a compatible way to not check headers.

Spring boot with SpringFox Swagger UI Generates all Verbs

I enabled API documentation using Swagger 2.6.1 in my spring boot app. The page(swagger-ui.html) loads fine but controller documentation contains all the verbs(PUT, GET, PATCH, POST, etc) even if my controller only has a GET operation. How can I disable the other verbs in the UI doc?
This happens when you have mapping like this in your controller
#RequestMapping(value = "/productDetails")
Springfox cannot identify what is the requestMethod hence it provides all mapping.(Eventhough the default is GET)
If you change this to
#RequestMapping(value = "/productDetails", method = RequestMethod.GET)
Then you will see only GET mapping and not others.
If you use newer versions of Sprinboot, you can use #GetMapping or #PostMapping instead of #RequestMapping

InterceptingAsyncClientHttpRequestFactory Use

I was trying to understand the use of InterceptingAsyncClientHttpRequestFactory. When run test with MockRestServiceServer I saw requestFactory is decorated with this ResquestFactory. Is there any other use of this requestFactory? Basically I want to know the idea behind InterceptingAsyncClientHttpRequestFactory. As I couldn't find any examples to use it.
Below code doesn't work.
AsyncClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsAsyncClientHttpRequestFactory(
httpAsyncClient);
List<AsyncClientHttpRequestInterceptor> interceptors = new ArrayList<>(1);
interceptors.add(asyncRestReqResInterceptor());
AsyncClientHttpRequestFactory interceptorFactory = new InterceptingAsyncClientHttpRequestFactory(
clientHttpRequestFactory, interceptors);
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(interceptorFactory);
Please let me know the correct implementation.
The general idea behind request factory is that you can customize how HttpAccessor implementations, like RestTemplate, makes requests. If you don't specify anything you get non-pooled HttpURLConnection, but spring offers factories for Appache HttpClient and other 3rd part libraries.
InterceptingAsyncClientHttpRequestFactory is a decorator, which allows you to plug-in Interceptors that modify the request befor it is sent. One such Interceptor is the BasicAuthorizationInterceptor which adds the Authorization header to every request. If you have stuff you need to do to every request you can create your own ClientHttpRequestInterceptor.

Spring Data REST CORS - how to handle preflight OPTIONS request?

I'm using Spring Data REST to build a RESTful API. Until now my HTML GUI for this RESTful service was served from the same Tomcat and I had no problems wit Cross Origin requests.
Now I want to serve the static files from a different server. This means the API is on another domain/port. Browsers will send the OPTIONS request to get the Access-Control headers from the server. Unfortunately Spring Data REST does not handle those OPTIONS requests and even returns a HTTP 500.
I tried creating a custom controller that handles all OPTIONS requests
#Controller
#RequestMapping(value = "/**", method = RequestMethod.OPTIONS)
public class OptionsController {
#RequestMapping
public ResponseEntity options() {
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
Which worked for OPTIONS, but then all other requests (like GET) ceased to work.
OPTIONS requests are switched on via the dispatchOptionsRequest dispatcher servlet parameter.
tl;dr: currently Spring Data REST does not answer OPTIONS requests at all.
It might be worth opening a ticket in our JIRA.
Browsers will send the OPTIONS request to get the Access-Control headers from the server.
Is that specified somewhere? If so, it would be cool if the ticket description included a link to that spec.
A few comments regarding your approach for a workaround:
#RequestMapping on the controller method overrides the method attribute and expectedly now matches all HTTP methods, which is why you see all requests intercepted. So you need to define OPTIONS as HTTP method there, too (or maybe instead of in the class mapping).
You're not returning any Allow header which is the whole purpose of OPTIONS in the first place.
I wonder if the approach in general makes sense as it'll be hard to reason about the supported HTTP methods in general.
Just set the parameter dispatchOptionsRequest to true into the dispatcher to process the Options method calls, into the implementation of the WebApplicationInitializer.
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(applicationContext));
dispatcher.setInitParameter("dispatchOptionsRequest", "true");
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");

Resources