HttpServletRequest getParameter AND getReader - java

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

Related

Sample Request for a REST-API in Java or PHP

I am looking at extracting data from a survey tool using their API. Being fairly new to APIs, I went through their documentation, few videos and figured out a little of what's happening.
But along with the Method and Attributes, they also have a sample request in Java/PHP and a sample response. Now the sample response is the JSON file fomat I'm expecting back but what do I have to do with a sample response?
As in, from all the videos I have seen you call an API using a particular URL. What is this sample request used for? Is it for using it in your own code?
I know its quite a silly question but any input would be much appreciated.
Assume you have a system that manages "virtual machines" for you; and that offers an API like:
/system/create-new-virtual-machine
/system/{virtual-machine-id}/start
So: your client would first call the first API method to somehow define a new virtual machine (providing all the required data to create a configuration).
Obviously, when you create a new thing, that should result in a new URI; which you would use later on to make other calls. In our example, the create call would return 200 ... and give you the URI for the newly created vm within the result body.
Long story short: just think of your REST api as the interface of a component/module your code is dealing with. Some of the API operations just tell you "fine, I passed" ... but others will want to give you information back. And that is what you need the response body for.

In API design, should I put restriction on the HTTP method in which request parameters are sent?

My API endpoint accepts POST requests.
I use ServletRequest.getParameter to get request parameter value. getParameter can find parameter value in either requested string or POST form body. Given such behaviour, my API user can send a POST request passing parameters like a GET request:
/callApi?paramA=123&paramB=123
Although, the API should accpet form values instead of URL parameters.
I do not see any problem with it.
But from a good design perspective, should my API report an error when user attempts to make such requests?
Since this question is tagged under "REST", I will answer the question assuming that you consider REST, and specifically REST via HTTP as "good API design".
HTTP has a pretty clear definition of what a URI is. Above all other things, a URI should serve as an identifier. If your URI can change (and the query string is part of the URI), and have the same result, from a RESTful HTTP standpoint, this could indicate something is off.
In your example, /callApi?paramA=123&paramB=123 is the (partial) URI for your resource. If you can POST to /callApi with a different body and have the same effect, then that either means you have information that identifies your resource in the body of your request OR you have data (the query string) in your URI that serves a purpose other than identifying a resource (which is what a URI should do).
If you don't care about RESTful principles, then of course this may not be applicable. If that is the case you may want to retag the question. Regardless, treating a URI as an ID first and foremost can be helpful when it comes to questions like yours.
My instinct says "yes it's fine" on the basis that your server-side code should handle security the same way, regardless of the HTTP verb used, or the manner in which data is passed. Avoiding SQL injection by scrubbing the input, would be one such example.
I'm not familiar with the class and method you described but for consistency, I suppose I would use the POSTed form data rather than the query string data, assuming you have any way of distinguishing between the two.
I would say it would be fine, since in the end when you get a parameter theres no default way to determine if its Query String or in the Body. You would have to check the Query String to see if the parameter is present in there and then act accordingly.
I would just make your documentation specify to do it in the body as opposed to the query string and try and keep the URL you submit to as lean as possible.
I found this useful when providing an answer.

Setting Request Header in java

Is there any way to modify or set-header of request inside action class? I want to modify it or you can say i want to put flag inside request Header just like we put values in 'attribute' and parameters.
You can do this using HttpServletRequestWrapper. But it's quite dirty solution. Are there really no other ways to solve your problem?
You cannot. Request parameters returned from the servlet are unmodifiable Map. You cannot add/delete content returned from request (via servlet).
In order to set a flag, my suggestion is to store it in a session, and on another action, retrieve the flag & delete it from session.
I think you'd need to wrap the original request into a request class containing the change you wish to have.
It might be better design to have the request parameters parsed earlier in processing to such objects that make more sense to your application logic, and then set the state of those objects in the place where you now would like to modify the original header.
The answer to this depends on what problem you're trying to solve.
One of your comments suggests you're trying to test; if this is the case you have two basic options:
Use a mock request (unit-style testing).
Change the header from the client (integration-style testing).
For testing from real clients, set headers on the client side.
For mocking client interactions, you should be using some form of mock. StrutsTestCase, for example, provides MockStrutsTestCase (outside container) and CactusStrutsTestCase (inside container) classes allowing easy manipulation of request properties and characteristics.
If you are trying to open a URL connection using Java,
you can something like this What is the proper way of setting headers in a URLConnection?
If you can make requests with a browser,
You can use this Firefox plugin to add/modify any number of request headers.
https://addons.mozilla.org/en-US/firefox/addon/modify-headers/
Good Luck
You need to give more details. It sounds like you want to manipulate the request header once the server has received the request. I'm not sure I understand why you would want to do that. Modifying the response headers make sense. But not the request.
I think they only clean way you can do this is via an HttpServletRequestWrapper
Just override getHeader, getHeaders, getHeaderNames and you are good to go.

some clarifications regarding REST PUT verb and other none CRUD based actions

I have read this GREAT answer regarding REST. I have few questions regarding it:
According to the answer and what i read, new resource creation needs happen using the PUT verb but in most cases when you create a resource you need to provide parameters and sometimes binary data.
what is the way to do it with PUT? isn't it more natural to do it with multipart POST?
Can someone direct me to an example for use of PUT to send both binaries and String, preferably using the httpClient library.
What verb to use if i want something that is beyond the basic CRUD actions? like generate a report regarding one of the resources.
Thanks
You are confusing the HTTP Verb with the actual payload.
Nothing prevents you from using a multipart payload for PUT.
POST can be used to create new resources, but you are usually POSTing to a different URL.
As a side-effect, a new resource might get created and returned in the Location header.
PUT is used if you already have the URL to a resource.
REST != CRUD.
A restful architecture forces you to think in resources.
So 'report' might be a good candidate for a resource.
You could POST your report parameters to a resource like /..../reports (for example) and create a new report resource that way. Put the URL for the report in said Location header and use a GET to actually get the report data (or return the report data right away)

Avoiding IllegalStateException in Java/Servlet web stack

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..

Categories