ServletRequestWrapper or ServletResponseWrapper in production? - java

Hi have you seen anything really useful extending HttpServletResponseWrapper/HttpServletRequestWrapper or ServletRequestWrapper/ ServletResponseWrapper in production environment?

Trim whitespace from generated HTML, can save over 50% of bandwidth. I've had a project which displays large tabular data (with nicely indented HTML source), response size went from ~200KB to ~70KB by just trimming all whitespace away.
Process multipart/form-data requests transparently by putting multipart form data back in request parameter map so that you can use request.getParameter() and consorts the usual way again (Servlet <=2.5 example, Servlet >=3.0 example).
Capture the outputstream, either to have a copy or to MD5-hash it.
Disabling URL rewriting.
Etcetera.. Etcetera.. All just to override and change the default behaviour of certain HttpServletRequest/HttpServletResponse methods.

I've used it to "capture" the output of a JSP, so that it can be transformed by the forwarding controller. This was done by overriding the getWriter() / getOutputStream() methods.
SiteMesh does a similar thing, capturing the "target" in order to decorate the response.

We use it to
overwrite getRemoteAddr() to return values from X-Forwarded-For or X-Real-IP (set by our nginx proxy)
filter certain headers, e.g. to avoid content negotiation in 3rd party servlets
gzip response

Many frameworks (richfaces, myfaces on my current classpath at least) use a request wrapper to handle multipart requests
Spring has ContextExposingHttpServletRequest so that spring beans are accessible as request attributes.
myfaces orchestra uses the response wrapper to rewrite the URL in order to ensure multiple-window conversation context

I've used it just recently to capture outgoing response headers for debugging purposes (getHeaderNames() and getHeader() were only added on the response side in the Servlet 3.0 spec.
We've also used it for gathering metrics on our servlets, by overriding getOutputStream() to return an OutputStream implementation which increases a counter on every byte that passes through it so we can tell what our high-network-traffic servlets are.

Related

Jersey: How to redirect/forward WITHOUT URL changing in address bar

I am using Jerysey's implementation of JAX-RS to write a REST API. My POJO that handles the get requests eventually forwards it to a JSP. Everything is working fine, the problem is that the forwarding causes the URL in the browser's address bar to change to the URL that the request was forwarded to. How do I do a redirect WITHOUT this URL changing in the address bar? Current, I have tried 4 different ways:
return Response.seeOther(uri).build(),
return Response.temporaryRedirect(uri),
//thrown exception:
throw new WebApplicationException(response),
return Response.status(303).location(uri).build();
It doesn't sound like a Jersey issue per se. Jersey is doing its part to receive the request, do some processing, and return the response you are expecting.
It sounds more like a servlet container issue. Why don't you want the url to change in the browser?
Restful services can (and should) be built with no concern about templates/JSPs/consumers. Take a look at a library like RestAssured, write some tests for your work, and you will see that it is acting as expected.
Instead of rendering out to a JSP, consider using a rest client to make straight http requests against your service.
If you want the url to remain unchanged, consider making the http call using an AJAX library (JQuery or other Javascript-based solution).
I hope that helps!
A RESTful resource is identified by a URL. So if you redirect to another resource with another URL the URL in the address bar should change. That's good because you can e.g. bookmark this URL or send it per eMail.
The question here is are you really redirecting to another resource or do you only want to return a different representation (HTML instead of e.g. JSON). If the latter you should not redirect. Let your resource-class directly return text/html by using Jerseys Viewables.
You could make the entire website inside an iFrame and load the new site into that frame. It will maintain the page URL and load your content.
http://www.w3schools.com/tags/tag_iframe.asp

Max file size with resteasy and multipart/form-data request

How can I control the max file size and/or the max request size when using resteasy to handle a multipart/form-data request ?
My code looks like this:
#POST
#Path("/somerestresource")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response handleForm(#MultipartForm MyForm form) {
...
}
With a Servlet I can control stuff with the #MultipartConfig annotation.
So I'm thinking about bypassing resteasy and using #Context to inject a HttpServletRequest and having my servlet configured inside the web.xml but I'm unsure of the side effects.
With JAX-RS 2.0, you could use a ContainerRequestFilter bound to your upload method using a #NameBinding annotation. In this filter, you would look at the content-length request header and discard the request if the content length exceeds the maximum value you plan to accept (requestContext.abortWith(...))
With JAX-RS 1.1 and RESTEasy, you could probably do the same thing using a PreProcessInterceptor (http://docs.jboss.org/resteasy/docs/1.1.GA/userguide/html/Interceptors.html#PreProcessInterceptors) and follow a logic logic similar to the one described above.
In addition to the answer by Xavier, you can also get the content-length header from an injected #Context HttpServletRequest. Furthermore, this is not enough, because the header may not be available (e.g. when chunking is used for the POST body). You then have two options: let the call fail, because you don't know the length of the stream, or resort to using, e.g., BoundedInputStream to read the body of the upload part of the request.
Minor detail: the content-length header is usually sent along with the main request, and not with each part of the multipart data. It therefore does not accurately represent the size of the upload.

Starting point for converting jersey project to standard servlet app

I am trying to implement the example shown here.
The example seems to be for a jersey setup, which I am not using or familiar. How hard would it be to convert this to a standard java servlet project(idk how to name this)
What steps should I take. It seems most of the # annotations need to be changed to servlets.
This also seems very differnt from the standard appengine upload setup which all takes place in one servlet.
This would be a lot of work to rework the code to standard servlet and remove jersey. Jersey takes away so much boilerplate code. For example the JSON conversion is done by jersey, which otherwise would have to be custom implemented.
And you can for sure deploy more than one servlet to gae, in which way should this be standard?
Just look at the first method:
#GET
#Path("/url")
public Response getCallbackUrl() {
String url = blobstoreService.createUploadUrl("/rest/file");
return Response.ok(new FileUrl(url)).build();
}
When using only standard servlet you would need to do:
Servlet Definition and Mapping in web.xml to /url
Implement a HttpServlet, override doGet() method
Send Response Code 200 OK
Set appropriate HTTP Response Headers
Convert Response to JSON and write it to response

Is there a way to get post parameters from a http request in a filter but keep the input stream intact for servlet?

I am trying to fix a bug in sitebricks where it consumes the input stream in of the data of all servlets even those not using site bricks.
HiddenMethodFilter.java line:66
String methodName = httpRequest.getParameter(this.hiddenFieldName);
See http://code.google.com/p/google-sitebricks/issues/detail?id=45
Yes you can provide your own request, see Modify request parameter with servlet filter.
Furthermore may be extending the wrong sitebricks filter might be easier than chaining.
Obivously not, since the servlet container is required to read and consume the data in the InputStream before it is able to give you the request parameters. The other way around if you consume the InputStream first, the container won't have access to the request parameters later.
Why can't you fix the bug using the suggestion in the linked issue suggesting to configure the HiddenMethodFilter only for the URLs related to Site Bricks?

Custom annotations to set HTTP response headers in a JAX-RS service

I have a JAX-RS web service for which I would like to disable the same-origin policy via the new CORS HTTP headers. (I am fully aware of the security implications.)
I'd like to have a custom annotation that lets me set HTTP response headers. For example,
#ResponseHeaders({"Access-Control-Allow-Origin: *",
"Access-Control-Allow-Methods: GET"})
// Or, alternatively:
#AllowOrigins({"*"})
public String resourceMethod() { ... }
This approach minimizes boilerplate code, but I'm not sure if there's a subtle technical limitation; JAX-RS provides many annotations to handle the HTTP request but not the response, with #Produces seeming to be the sole exception.
I also prefer to stay away from too much web.xml configuration, if possible. Without explicitly needing to use a ResponseBuilder (it's OK if an annotation uses one), is there a clean way to set custom HTTP response headers?
To clarify, I'm looking for annotations that integrate with the various ways of setting HTTP response headers in order to minimize boilerplate code.
Perhaps the only spec driven approach is to use a custom MessageBodyWriter. In the writeTo() method, you are passed in a MultivaluedMap which you can set response headers on. You are also passed the annotations on the resource method invoked (so you can get whatever custom annotation you want). So read the annotations, set the headers via MultivaluedMap, and then use the OutputStream passed in to write the message body.
In Apache Wink and possibly other JAX-RS frameworks, you can create custom server side handlers that can also read the annotations on the resource method and do whatever you want (like setting response headers by default).

Categories

Resources