This question already has answers here:
How to read request.getInputStream() multiple times
(6 answers)
Closed 5 years ago.
When you try to access the raw InputStream of a x-www-form-urlencoded servlet request, the stream could have already been indirectly consumed by a prior access to the parameters (e.g., via ServletRequest#getParameterMap()) of the request. This feature (bug?) has already been documented in the section SRV.3.1.1 of the Servlet spec and there are other people who have been bitten by this as well.
This indirect stream consumption makes it, to the best of my knowledge, impossible to mirror the InputStream, which is exactly what we are trying to achieve in HRRS. Hence, I try to re-construct the InputStream from request parameters. This, as you can imagine, a really nasty hack which I am not fond of either. Further, to make the things worse, when servlet pushes the form parameters into request parameter map, it merges them with query parameters too. Now you need to manually parse both request and query parameters to figure out the initial form parameters. A total shipwreck.
Any ideas on how to replace this hack with a proper solution?
Edit: Dear SO Java-badge owners, this is not a duplicate question. Please see the Tomcat bug report before marking the post as duplicate.
Even if HRRS is the first filter in the list, it is not consuming InputStream, it is just wrapping the InputStream and passing along the wrapped request along the chain. Problem is, getParameter() calls in Tomcat is using an internal reference to the InputStream (that is, o.a.c.connector.Request#getStream()) and not calling javax.servlet.ServletRequest#getInputStream(). Hence, InputStream gets indirectly consumed without the wrapped one getting used at all. (See o.a.c.connector.Request#readPostBody() source code for details.)
I don't think it is possible to completely recreate the original request in all cases. The order of request parameters will be lost for example.
For a tool like this I think it is perfectly acceptable to expect to be the outermost filter. That way you shouldn't have the problem in the first place. But maybe I'm missing something?
Related
I am developing a REST web service in Java which on clients' request processes the request body and gives the output to the client. The request body sent by the client consists of a GO(programing language) program which the server executes(runs) on the server machine and returns the standard output of the program back to the client. Now since the request body contains some text(program), I cannot use HTTP GET method to do that. I can use PUT or POST, but I have learnt that they(PUT and POST) are generally used for updating/creating a resource. Since, I am not creating any resource here, is it conceptually correct to use PUT or POST. If not, which is the HTTP method that I need to use?
Looking at the problem you are solving and comparing to an existing production solution , I suggest that you can use POST in your scenario.
Reasoning - Example Production code solving similar problem:-
Assuming that the problem you are trying to solve is this:-
Clients submit code in Go programming language, Your server compiles it, runs it and then gives the output. Assuming also that, it is somewhat similar to many online coding websites like hackerEarth, their API documentation page and the sample python code provided show that we can use HTTP:POST to submit code to the server for its processing.
Reasoning - RFC for HTTP POST, PUT :-
POST is designed to allow a uniform method to cover the following functions:
Providing a block of data, such as the result of submitting a
form, to a data-handling process;
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server.
Referring to the above statements, we can conclude that in the context of this problem which you are solving, you are requesting the server to do some data-handling for the enclosed entity, so you can use POST.
This question already has answers here:
What is the use of filter and chain in servlet?
(3 answers)
Closed 9 years ago.
I inherited a Struts 1 app that heavily utilizes FilterChain and I don't understand the benefit of this extremely obfuscating code.
"In the Servlet API, you normally use a Servlet when you want to control, preprocess and/or postprocess specific requests. But when you want to filter/modify common requests and/or responses based on specific conditions, then a Filter is much more suitable."
Every request in my app is based on specific conditions, e.g., a merchant id or a search term. But it seems like placing a request inside a whole chain of stuff that completely hides what is going on from the developer trying to trace the cause of an error, is nuts.
The FilterChain#doFilter() call just continues the HTTP request to the destination, following exactly the same path as if you didn't use a filter in first place. This is usually a servlet class or even a JSP file. So, in order to debug problematic code, better put a breakpoint in the target code, not in the filter if it doesn't contain any code of interest.
My coworker (who's not registered on SO) explained that it's for applying global functionality to an app that you don't want to do in every single controller, such as checking if the user is logged in.
My problem is this, in Java, I have occasion to redirect a user elsewhere, where elsewhere is user definable. The code looks like:
response.sendRedirect(redirectURL).
My focus is on the string represented in the variable redirectURL.
My understanding is this, specifying response.setCharacterEncoding affects the content written to the response writer, not affecting the sendRedirect contents.
It would seem reasonable that by adding URIEncoding= on the connector, in tomcat based containers, should handle the case where the path of a URL is in, simplified Chinese, or Japanese, or non-ascii characters but it does not. Part of my question is why.
There have been many responses on here stating use URLEncode. However in issue 4571346
how to encode URL to avoid special characters in java
Wyzard states that shouldn't be used, rather
create a URI object
create proper URL string via toASCIIString.
In my for-instance use case, this works fine, albeit this code needs to be performed prior to every response.sendRedirect(), which are many.
As more and more applications have global use I see this issue effectively rendering insufficient the straight HTTPResponse method sendRedirect because, by itself, it may not work properly.
I refer all to RFC3490 which deals with Internationalized Domain Names in Applications, which discusses toASCII as one of two operations, the other being toUnicode.
Why, then, does URIEncoding= on the connector, not handle this, should it, and is there a more preferred way to deal with URLs where the path is internationalized?
I just believe, by way of separation of concern, this issue is and should be an container issue, not an application issue. My hope is this will provide a forum for discussion on this issue, not HTML, not forms, not anything other than the URL itself.
I am developing a HttpServlet that handles a POST request from an application that includes parameters on the query string, and a JSON object in the body. It is not a form post, the entire body is the JSON object. I understand that I need to use HttpServletRequest.getReader() to read the body. But I also need to use HttpServletRequest.getParameter() to get the query parameters. And I understand that both can not be used.
I think the intended solution is to create a HttpServletRequestWrapper and override getReader() in such a way as to allow it to be called more than once. But I can't figure out how to do that. Or maybe this is not the intended approach. All the examples of HttpServletRequestWrapper that I can find seem to be related to creating filters and modifying the contents of the request.
Any help is greatly appreciated.
BTW, this is hosted on Google App Engine, but I don't think that will affect the solution.
I think you can implement multiple-callable getReader() in your HttpServletRequestWrapper :
save the HTTP-request body into a temporary file.
when HttpServletRequestWrapper.getReader() is called, open the temporary file.
delete the temporary file at the end of request processing.
to implement (1) and (3), ServletFilter may be useful.
I would suggest reading the query string parameters directly by parsing the query string. This way you won't touch the message body and you can use HttpServletRequest.getReader().
Parsing the query string is tricky but there it can be done safely using URLEncodedUtils from Apache Http Client package as discussed here:
Parsing query strings in Java
I don't know, but I feel that IllegalStateException is causing undo headache. If I have a request say a JSP or some other servlet and need to associate a filter with that request. I can't do any other modifications to the output to the client if the response has already been committed?
For example, I see in JSP code that sets the mimetype to response.setContent("html") and then I have a filter associated with the JSP that needs to set the mimetype to something
else. setContent("image") or "xhtml". But I get an IllegalStateException?
Is there a way to clear the previous response that has been committed or is there something to avoid this issue.
This is on websphere.
I think you need to rethink how you're preparing and returning your responses. You can't write to the response (which may write to the client) and then change your mind.
Leaving aside the question of why your solution has to change the return type, I would write to some dummy container object with the return date + type, and make this mutable. Only once your servlet has completed all its work would you then write this object (type+content) to the outputstream.
(to clarify, I don't think servlet filters are the right approach for this. They will intercept the request, and the response, but the response population is the responsibility of the servlet)
I agree with the other posters that this is ugly but you can create an HttpServletResponseWrapper in your filter that would hijack the output and pass that wrapper to the chain instead of the original response object.
Your premise to execute a jsp outputting HTML and then have a filter changing the content type to something else like image all in the same response makes no sense. A response can only return a single artefact be it a HTML file or image. There is no way to return both within the same response- any attempt to do so is nonsense . It makes no sense to send some HTML with image binary tacked on the end. The content type is for the entire response. You cannot package multiple thingos in the one response.
Sometimes you can resetBuffer() if the output as not exceeded the buffersize. The best approach is to avoid this facility and deyermi e what to do before you start outputting a response..