I want to route requests based on some values in requestBody in spring cloud, for example:
if value of firstField in requestBody is chagre, I want to route this request to /chagre api
else if value of firstField in requestBody is package, I want to route this request to /package api
Any help would be appreciated.
Best practice is not to route according to request body, but use different attributes of the HTTP request instead. Spring Cloud Gateway includes many built-in route predicate factories based on those attributes.
The problem is request body can be read only once. moreover you need to know the object class it contains in order to properly read it.
In order to construct a solution to your question, we can use Spring Cloud Gateway ModifyRequestBody to rewrite the request body after you read it and before it send to the downstream.
Read more about ModifyRequestBody
Related
I am trying to intercept all incoming HTTP requests and process the body attached to these requests in my Spring MVC (not Spring Boot) app. To implement this "inbound-interceptor", I am using Spring's HandlerInterceptor interface. Once the request is intercepted, I am trying to retrieve the body as follows:
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
Map<String, String[]> params = requestWrapper.getParameterMap();
byte[] body = requestWrapper.getContentAsByteArray();
Referring to this article, the limitations of trying to extract the body this way are:
Content-type of the request must be x-www-form-urlencoded
Method-type must be POST
For the application I am building, I cannot enforce either of these constraints as the calls come from heterogeneous sources beyond my control. Is there some way to override this behavior to allow extraction of the body for requests not supported by default? Or, alternatively, is there another approach to performing this task?
P.S. I am performing logging + some custom processing on the body. So solutions such as the ones mentioned in this answer are not too helpful
Have you tried Logbook? https://github.com/zalando/logbook Works with pure Spring.
Their Default Log Writer looks promising: https://github.com/zalando/logbook/blob/main/logbook-core/src/main/java/org/zalando/logbook/DefaultHttpLogWriter.java
And you may just want to extend this class to log to all Loggers you want.
You can even do something completely different with the request besides logging.
I'm trying to use apollo-android library to communicate with graphql server. The problem is that backend uses headers to authenticate requests and I found no ways to add them. Also in auth request the token is sent in headers and I found no ways to read it from the response.
People advise to set auth headers via interceptors in OkHttpClient but this approach is not applicable in my situation because client have to send different sets of headers in different requests.
So, is there any workaround in this situation? Should I use simple rest client like Retrofit or maybe create new ApolloClient and OkHttpClient instances on each new request with desired set of headers? Or maybe there is another workarounds?
People advise to set auth headers via interceptors in OkHttpClient but this approach is not applicable in my situation because client have to send different sets of headers in different requests.
Have setter methods and fields on your interceptors that accept the varying headers. Call those setter methods prior to making an ApolloClient request that needs the headers.
Or, teach the interceptor how to apply different headers for different requests based on the request characteristics visible to the interceptor (e.g., URL).
My requirement is to call siebel soap webservice, In the process handle request and response on a same method call, so that I can add token to the request header from the apache common pool and once get the response with token, grab the token from response and send it to pool. Here I have mechanism to verify old token too,
I need request token and response token on same class.
Future planning to add retry mechanism.
Currently I am using SI Http outbound gateway.
Any thoughts, appreciate it.
Thanks
So, what you need is named pre- and post-process. Not sure why you don't use Spring Integration WS support for calling that Siegel service, but even with the HTTP you can get a gain via Interceptor abstraction.
What I mean that you can inject RestTemplate into HTTP Outbound Gateway supplied with the ClientHttpRequestInterceptor implementation to provide a desired logic.
If you'd use WS Outbound Gateway, you could do that in the similar ClientInterceptor abstraction.
Of course, you can achieve that via HeaderMapper implementation, but that has different responsibility...
I found the way to achieve this,
Created a class to extends HttpRequestExecutingMessageHandler than overrided handleRequestMessage()
http://docs.spring.io/spring-integration/reference/html/http.html#http-outbound
I need to access a HTTPS Resource which is using Basic Authentication and It is a GET Resource. I have written a code in java using URIBuilder and adding the username, password etc as Headers to the URIBuilder and using Apache HTTPClient to access the resource and it is working well.
Now my requirement is to implement the same functionality using Apache Camel, Well I tried using Camel HTTP component and by using Java DSL.
The problem is I am just able to provide the URI. But how can I add various Headers to this URI ?.
I suggest you use the http4 component as a way to consume this secure resource. From reading the docs of the component you can see it's possible to set the query parameters, path and even uri at runtime.
In answer to your specific question, the headers on the exchange at the point it reaches the .to() will be sent as headers in the HTTP request so you may want to define a header filter strategy. It has support for http basic auth and you can set your credentials via the authUsername and authPassword headers. You may need to provide a custom HttpContext because you're authenticating via https as it suggests at the bottom of the docs. For example:
from("direct:in")
.process(new Processor() {
public void process(Exchange exchange) {
//These headers you set here will get sent with the http request in the to() after this processor
exchange.getIn().setHeader("authUsername", "username");
exchange.getIn().setHeader("authPassword", "password");
}
})
.to("https4://uri.com);
Use the simple language to add headers if you are using blueprint or the java dsl if its pure java. Simple example:
from("direct:start")
.setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http4.HttpMethods.POST))
.to("http4://www.google.com")
.to("mock:results");
I tried to pull the body out of request.getReader() but it was already read.
How can I get my hand on the requestbody within the interceptor?
As you say, the request body can only be read from the Reader once. This is not specific to interceptors, but for all users of the Servlet API.
If you need to access the body a second time, then you need to store the data somewhere, such as in a request attribute (using request.setAttribute() and request.getAttribute()).
How and where you do this depends on your interceptor, and you told us nothing about your specific case.