add headers to a response fired by ChannelHandlerContext (Netty) - java

I have a jar, that I can't edit, that adds several headers to an http response. It then takes the response andctx.writeAndFlush(resp)
Is there a way to catch this response elsewhere (like a middleware) and edit it (add/remove headers, etc)?
The code uses Netty http tranport

If you have access to the ChannelHandlerContext (ctx), the Channel or the Pipeline through which the response propagates. Then you can access the response by adding a ChannelOutboundHandler to the Pipeline and overriding the write or the flush method of this handler. In these methods you can modify the response.

Sure you can add your own ChannelOutboundHandlerAdapter and override write(...). Here you can adjust the response on the fly before you call ctx.write(...) again and pass it on.
Just ensure you put your handler before the other handler in the ChannelPipeline.

Related

Wiremock capture response body for later reuse

I'm facing a particular use case while using Wiremock standalone API.
I would like to be able to reuse a response body generated by stubbing for a another request (stubbed as well) as a context model. The purpose is to store for a generated Id the entire response data, that would allow me to serve it again simply knowing the Id, in a get method particularly (where there is no request body).
Is there a way while defining a stub of response to capture the generated response, in order to store it?
Or if you have other better idea.
Finally I solved the problem by using an okhttp interceptor (which depends on your client solution).
In the interceptor, I store every response data (e.g.: a generated ID) and set them in every next request headers when it matches with part of the the response stored.
adding them to the request headers allows me to access them in a json template file for instance

Apache-Camel: How to control the scope of the exchange headers?

I'm using the exchange headers to store any variables in the route. But, looks like these headers will be carried on to the other routes which are called from this route.
In the below sample, I'm calling a getContact route which will call a http endpoint. But, it will also send the headers, variable1 & variable2, it got from the initial route, direct:start.
from("direct:start")
.setHeader("variable1", constant("value1"))
.setHeader("variable2", constant("value2"))
.to("direct:getContact");
from("direct:getContact")
.setHeader("Content-Type", constant("application/json"))
.setHeader("Accept", constant("application/json"))
.setHeader(Exchange.HTTP_METHOD, constant("GET"))
.to("http://<host>:<port>/contact/3")
.unmarshal().json(JsonLibrary.Jackson);
Is there a way to avoid this? In contrast, a method call in java will hide all the existing variables by context switch.
I've run into the problem before when sending a webservice call using http4. Tt's rather annoying that Camel seems to send send the entire exchange when you're using the http4/http endpoint. I got around this by using a content enricher. I placed the actual call using http4 in the enrich route and had an simple aggregation strategy combine the two messages afterwards.
Alternatively, you can make the call in a bean. This way you lose some of the benefits of camel but you have complete control over the call body.
There is no direct way to avoid this. If you are setting the headers to a hard-coded value then you might be able to move the header to a URI property on your endpoint. If not then you only really have 2 other options. The first option is to remove all of the headers using a remove header call after your HTTP call so they don't go downstream. The second is to set all of the headers in the same route as the http call and have a different route call that endpoint with an enrich statement and in the aggregation back to the main route you can customize the returned exchange.
Here is an camel http reference page for all of the allowed headers to see if you can put it in the URI http://camel.apache.org/http4.html
Sample of a route removing headers
from("direct:start")
.setHeader("variable1", constant("value1"))
.setHeader("variable2", constant("value2"))
.setHeader("Content-Type", constant("application/json"))
.setHeader("Accept", constant("application/json"))
.setHeader(Exchange.HTTP_METHOD, constant("GET"))
.to("http://<host>:<port>/contact/3")
.unmarshal().json(JsonLibrary.Jackson)
.removeHeaders("variable*")
.to("Anything I call now won't have the variable headers");
enrichment call
AggregationStrategy aggregationStrategy = new ExampleAggregationStrategy();
from("direct:start")
.enrich("direct:getContact", aggregationStrategy)
.to("You can have no additional headers here");
public class ExampleAggregationStrategy implements AggregationStrategy {
public Exchange aggregate(Exchange original, Exchange resource) {
Object originalBody = original.getIn().getBody();
Object resourceResponse = resource.getIn().getBody();
Object mergeResult = //TODO implement this however you want. You can remove any headers here you like
if (original.getPattern().isOutCapable()) {
original.getOut().setBody(mergeResult);
} else {
original.getIn().setBody(mergeResult);
}
return original;
}
}
Actually 1 more option came to mind when going through the camel documentation I found an interesting property. Disclaimer I have never tried this property myself since I am still running camel 2.15 atm, but feel free to test it really quick it might just be what you need.
copyHeaders
default: true
Camel 2.16: If this option is true then IN exchange headers will be copied to OUT exchange headers according to copy strategy. Setting this to false, allows to only include the headers from the HTTP response (not propagating IN headers).
Just use:
.removeHeaders("variable*")
to remove headers of any pattern.

Using Spring, Tomcat, and Java, how do I redirect a request with HTTP headers?

So I have a org.springframework.stereotype.Controller and what I want to do is process the request normally if HTTP headers HA and HB are specified. But if the request has query parameters QA and QB specified, I want to redirect the request WITHOUT QA or QB, but WITH HTTP headers HA and HB such that HA has the value of QA and HB has the value of QB.
For example, if the incoming request is HTTP GET ~/rest/mortgage with HTTP headers x-name=foo and x-date=bar, I would process that request as is. But if the incoming request is HTTP GET ~/rest/mortgage?x-name=foo&x-date=bar, I want to redirect to myself with the request HTTP GET ~/rest/mortgage with HTTP headers x-name=foo and x-date=bar.
By doing this, I can have a single code path dealing with both styles of making the HTTP request just by adding a simple check at the controller level. This is because I pass the HttpServletRequest around to various parts of the code, so if I have the consistency of always having HA and HB instead of QA and QB, it reduces the cyclomatic complexity of the code.
Is this possible? And if so, how?
If this is not possible, I can achieve my desired result by defining my own wrapper for HttpServletRequest that does the transformation for me, but that's not as elegant of a solution.
If you want to intercept the HTTP request you need to use a Servlet Filter.
In order to replace the URL you have to get the Dispatcher for the new URL, and then dispatch the request again with the forward() method.
Something like this:
servletRequest.getRequestDispatcher(modifiedURL)
.forward(servletRequest, servletResponse);
However, you are not explicitly allowed to modify the HTTP headers. The way around this is to wrap the request and have a proxy object that handles this, by extending HttpServletRequestWrapper. It already implements the HttpServletRequest so you shouldn't have any issues using it wherever you are interacting with the original servlet request.
You can simply extend it and add your own method like addHeader() and keep an internal Map or something of the extra artificial headers you are adding. Then you have to just override getHeaderNames() and getHeader() to also combine the original headers with your own extra ones.
The last thing you will need to do is wrap your original servletRequest in your new wrappedServletRequest in your Filter. So something like this (where WrappedServletRequest is your new implementation that extends HttpServletRequestWrapper):
WrappedServletRequest wrappedServletRequest =
new WrappedServletRequest(servletRequest);
wrappedServletRequest.addHeader("yourHeader", "yourValue");
wrappedServletRequest.getRequestDispatcher(modifiedURL)
.forward(wrappedServletRequest, servletResponse);
Remember to add your <filter> and <filter-mapping> of your Filter in your web.xml for it to work.
You might want to have a look at this article for more details. It has some more information as to why you have to do it this way.
I didn't try it myself, so comment below and confirm if you manage to get it to work.

I need to broadcost Httprequest in diffrent sources in java

I need to create child http-request(broadcost) on the basis of single client request, and when child request will end then it inform to main request.
how could i implement this . will you all provide the better idea in java .
Regards
Nilay Tiwari
Assuming you have a method which handles the client HTTP request, then you would make the child HTTP request synchronously in that method. The child request will return response and you can then choose what response to return to the client.
To make the HTTP request, you could use HttpURLConnection in the JDK, or the Apache HTTP Client library.

Servlet include swallows HTTP headers in Tomcat

I have a servlet that does a request dispatcher include of another servlet.
The included servlet sets headers that I would like to read in the including servlet. So I pass in a custom HTTPResponse object in the include() method which captures all feedback activity from the servlet.
The problem is that the headers are not being set in my custom response. I've run in debug and examined what looks like Tomcat wrapping my custom response object with its own response object. The setHeader calls go to this wrapping class and never propagate to my custom response object.
I imagine Tomcat does this to protect the client from headers being set in the wrong place. The funny thing is that the same approach works the way I'd expect in Jetty.
It's been a while since I've done Servlets seriously so I'm struggling a bit here. I'm trying to figure out how to read the response headers from a servlet that's invoked via dispatcher.include().
From the Servlet specifications section SRV.8.3:
The include method of the RequestDispatcher interface may be called at any time.
The target servlet of the include method has access to all aspects of the request
object, but its use of the response object is more limited.
It can only write information to the ServletOutputStream or Writer of the
response object and commit a response by writing content past the end of the
response buffer, or by explicitly calling the flushBuffer method of the
ServletResponse interface.
It cannot set headers or call any method that affects
the headers of the response. Any attempt to do so must be ignored.
How about setting your values for the calling servlet in request scope, with request.setAttribute(...) and then reading it from there once you return? Could that work?

Categories