I'm building something using Google App Engine and I'm trying to create a java Servlet that reads the raw POST data and does something with it. According to the servlet documentation, this should be possible using either the getReader() method or the getInputStream() method. However it appears that somehow, at least with the App Engine development server that runs locally on my dev box, getInputStream() has already been called before the doPost method is even entered.
My evidence for asserting this is as follows:
getReader throws a java.lang.IllegalStateException (see this)
getInputStream returns a valid input stream, but calling read() on that input stream returns -1 (see this).
I checked and I am not calling getParameter() before I call getInputStream. getInputStream() is the FIRST thing I call in the body of the doPost method.
What is wrong here?
Per this link from google app engine issue tracker :
That is because the content type was sent as
"application/x-www-form-urlencoded". In that case the stream is read
and mapped as key value pair so that you can access the data as
req.getParameter("ParameterName") and for the same reason stream is
empty. We will be able to access the req.getinputStream() when the
content-type is sent as "application/octet-stream".
Related
I'm trying to create a little test servlet (Tomcat 10) to accept simple "POST" messages, however no matter what I've tried the servlet never seems to get the body (json).
I'm using Postman to send the messages (http).
I've tried getReader() and getInputStream() and both keep returning nothing. I've read that this can happen when the buffer has already been read, but I'm not reading it twice (not that I am aware of).
Here are some debug values:
getContentLength() => -1
getContentType() => application/json
getReader().ready() => false.
So, either no body was recieved or it was already read - but where? I've been using Postman for other API's without issue, so I don't believe I've done something wrong there, what else can I try within the servlet?
Does anyone have any suggestions of what I could try to get this working?
Update
Thank you #parsifal, I tested the servlet using PowerShell's Invoke-WebRequest and it worked perfectly, so I took another look at all my Postman settings, tested several things and then finally found my error. The Header parameter Content-Length wasn't selected - I had incorrectly assumed that it would be automatically sent, but it wasn't.
I Have a Jersey RESTful webservice under Glassfish which accepts incoming POST requests for uploading images, consuming MediaType.MULTIPART_FORM_DATA which maps to mime type multipart.
When I receive the instance of FormDataContentDisposition fileDetail in my service and call fileDetail.getSize()
I always get -1
I wonder how is the appropriate way to fetch the correct file size using Jersey and Multipart file upload.
I also encountered this problem and I'm now seeking for RCA and solutions.
Just a workaround: save the file temporarily and use File#length() method to get the real size of uploaded file.
More update:
As complement of the above method, keep monitoring saved bytes' size, throw an exception (or do what the policy requires) when the file size threshold is reached.
What's more, don't trust the size given directly by client, which could be faked, unless the client is trusted.
I've created server filter, that counts response size. It does that by creating response wrapper, which wraps ServletOutputStream with Apache Commons CountingOutputStream. Also, wrapper creates PrintWriter with wrapped stream. So in theory, whatever method would be used to create actual output, it should go through CountingOutputStream.
The problem is that, while whole thing works for typical servlet requests, it fails for static content. To be precise, the request is being picked up by filter, response wrapper is created and chain.doFilter() called. However when it returns, the wrapped stream claims no data was sent, while in reality data was sent. After further debugging it appears that during serving static content neither getOutputStream() nor getWriter() are called on the response wrapper.
The filter and app are running on Jetty 8.1.x. I've skimmed through Jetty's default servlet and it appears static content is being served in the usual way (that is by obtaining output stream and writting to it).
So the question is: Why the wrapper methods are being ignored?
Are you sure you disabled all cache mechanisms?
The problem turned out to be me expecting something not really possible. I was making a request to non-existent static resource. I still expected some data to go through filter, because http client was getting bunch of headers and my filter was reporting 0 bytes which simply felt wrong. However, it turned out that filters only do see raw data produced by servlet (or in case of static content and jetty - handler). They can't see headers as they are added later by the server, when all of the app code was already executed. While I'd like to have total response size (headers and content) it appears I have to settle down with only content beng measured.
I have a servlet that accepts POST requests, and it works perfectly when I'm not trying to read parameters. The inputstream contains an XML file which parses just fine. However, when I try to read a parameter:
String account = request.getParameter("account");
It fails when reading the inputstream.
How can this possibly affect the inputstream?
I suppose you are using a HttpServletRequest and from the ServletRequest#getParameter() documentation:
If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly via getInputStream() or getReader() can interfere with the execution of this method.
Are you using either getInputStream() or getReader() prior to your getParameter() ?
A related answer here might help you solve your problem: https://stackoverflow.com/a/17129256/1524381
All,
I'm trying to find out, unambiguously, what method (GET or POST) Flash/AS2 uses with XML.sendAndLoad.
Here's what the help/docs (http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002340.html) say about the function
Encodes the specified XML object into
an XML document, sends it to the
specified URL using the POST method,
downloads the server's response, and
loads it into the resultXMLobject
specified in the parameters.
However, I'm using this method to send XML data to a Java Servlet developed and maintained by another team of developers. And they're seeing log entries that look like this:
GET /portal/delegate/[someService]?svc=setPayCheckInfo&XMLStr=[an encoded version of the XML I send]
After a Google search to figure out why the POST shows up as a GET in their log, I found this Adobe technote (http://kb2.adobe.com/cps/159/tn_15908.html). Here's what it says:
When loadVariables or getURL actions are
used to send data to Java servlets it
can appear that the data is being sent
using a GET request, when the POST
method was specified in the Flash
movie.
This happens because Flash sends the
data in a GET/POST hybrid format. If
the data were being sent using a GET
request, the variables would appear in
a query string appended to the end of
the URL. Flash uses a GET server
request, but the Name/Value pairs
containing the variables are sent in a
second transmission using POST.
Although this causes the servlet to
trigger the doGet() method, the
variables are still available in the
server request.
I don't really understand that. What is a "GET/POST hybrid format"?
Why does the method Flash uses (POST or GET) depend on whether the data is sent to a Java servlet or elsewhere (e.g., a PHP page?)
Can anyone make sense of this? Many thanks in advance!
Cheers,
Matt
Have you try doing something like that :
var sendVar=new LoadVars();
var xml=new XML("<r>test</r>");
sendVar.xml=xml;
sendVar.svc="setPayCheckInfo";
var receiveXML=new XML();
function onLoad(success) {
if (success) {
trace("receive:"+receiveXML);
} else {
trace('error');
}
}
receiveXML.onLoad=onLoad;
sendVar.sendAndLoad("http://mywebserver", receiveXML, "POST");
The hybrid format is just a term Macromedia invented to paint over its misuse of HTTP.
HTTP is very vague on what you can do with GET and POST. But the convention is that no message body is used in GET. Adobe violates this convention by sending parameters in the message body.
Flash sends the same request regardless of the server. You have problem in Servlet because most implementation (like Tomcat) ignores message body for GET. PHP doesn't care the verb and it processes the message body for GET too.