I'm trying to implement the following:
Open a POST connection.
Read response code.
Write content.
Read response code.
The second step throws a following exception:
Caused by: java.io.IOException: content-length promised 345286 bytes, but received 0
I understand that 'getResponseCode' will close the writing stream, but i need to find a way of how to read the response code before actually writing anything. I would like to skip the process of writing content to the request body (100 MB) due to the (for an example) 401 code.
HTTP Doesn't work like that. You need to send the full request and only then to read the response code. In your case, your response had promised a request body of 345286 bytes, but you have sent nothing.
The correct way is to do the following:
Open a POST connection.
Write content.
Read response code.
In case you want to verify that the server permits to do it (to avoid 401s) you can add a small GET request first to verify the authentication.
Related
Consider the following code.
try {
httpURLConnection = (HttpURLConnection) new URL(strings[0]).openConnection();
httpURLConnection.setConnectTimeout(Config.HTTP_CONNECTION_TIMEOUT);
httpURLConnection.setReadTimeout(Config.HTTP_CONNECTION_TIMEOUT);
httpURLConnection.connect();
responseCode = httpURLConnection.getResponseCode();
httpURLConnection.getHeaderFields();
}
finally {
httpURLConnection.disconnect();
}
The issue is even when I don't use the InputStream to read the response, in my Internet/Wifi connection logs I can see the response-body. What I want is simply to check a field in the header and based upon that field I will continue reading the InputStream.
My questions are these:
Is it correct behavior for the connected stream to automatically download all/partial file even before a BufferedInputStream is created and read from?
If yes, then is it possible to stop the file download until an InputStream is used to read the response?
If not then is there something I am doing wrong or missing?
The response includes both the header and the body, the server does not stop for the client to acknowledge the headers before sending the body.
At the time the client is able to read the response code from the headers, a part of the body has already been sent, the size of which depends on the network latency, buffering, ....
The current implementation of HttpURLConnection.getResponseCode() even use getInputStream() to ensure that the connection is in the correct state.
The client can choose to ignore the body, but it's usually not recommended, because it may prevent a persistent connection to be reused.
I am not sure about Android but since Java 6, a background thread is automatically used to read the remaining data.
If If-Modified-Since is not an option, why not use a HEAD request ? :
The HTTP HEAD method requests the headers that are returned if the
specified resource would be requested with an HTTP GET method. Such a
request can be done before deciding to download a large resource to
save bandwidth, for example.
Is it necessary to read request data before calling the close method of response inside a http server in java?
I have a http server written by sun's http server. When I receive a http request, I just simply do the following steps:
write my text to response body
close the response
Does it matter to read the request body before closing the response?
Note that I have too many http requests on my server. (10000 call/sec.)
My benchmark says if request body does not have too much data, there is no big difference between two methods. I didn't get any timeout and other type of exceptions using both methods.
This is the time benchmark result for 1M request using 100 concurrent threads (10000 request per thread) on both methods:
Don't read request body: 210,581ms
Read request body: 206,599ms
In HttpServlet.doGet(...) I get the OutputStream from the HttpServletResponse with
resp.getOutputStream();
While writing to that output stream an exception occurs, and instead of the data, I want to send an error back
resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "My error message");
How should I handle the output stream then?
I must probably close it. Does the already written data get sent to the client? Can I somehow discard that data so the client gets only the error?
The output stream will be send to client with content type as text/html.
As per the Java doc.
Sends an error response to the client using the specified status and clears the buffer. The server defaults to creating the response to look like an HTML-formatted server error page containing the specified message, setting the content type to "text/html".
If the response has already been committed, this method throws an IllegalStateException. After using this method, the response should be considered to be committed and should not be written to.
You can set error pages also for predefined response.sendError() codes in web.xml.
Edit: i have added a picture.
When some exception occurs, it will not go to client. because you send an Error to client instead of data.
From Java doc.
Sends an error response to the client using the specified status code and clearing the buffer.
so the client will not see any of the written data, and you should not care about the already written data. it will be cleaned up.
im writing a java application that sends a post request to a server and expect a json from the server. Now when i need to get the response from the server do i only need to get it from the inputStream when the http code is 200 (HTTP OK) or is there any other cases ? , example :
//...
if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
// only here try to get the response
}
//...
It depends on how the server is implemented. Check the API, if the server has one. If it's internal, ask your server guy.
Generally speaking, if your response code is either 2xx or 3xx, I would check the response anyway...
If the server your communicating with is following the spec then either 200 or 201 responses are valid to contain an entity. A 204 response is successful but has no data in the response.
See section 9.5 here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5 for details of acceptable responses to a POST. Extract below:
The action performed by the POST method might not result in a resource
that can be identified by a URI. In this case, either 200 (OK) or 204
(No Content) is the appropriate response status, depending on whether
or not the response includes an entity that describes the result.
If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header (see section 14.30).
There are three things to consider:
All 2xx codes denote success of some sort. But depending on the exact code, your reading code might be different. (204 for example means success but no content.)
There are redirecting codes (3xx). These are usually automatically followed by the http client library but you can also set them not to, in which case you need to have custom code that handles these cases.
There can be valuable information returned in the stream even if you get a code that denotes an error. Whether you want to process it depends on your exact needs.
I'm an experienced Java programmer but a newbie web developer. I'm trying to put together a simple web service using the HttpServer class that ships with JDK 1.6. From the examples I've viewed, some typical code from an HttpHandler's handle method would look something like this:
Headers responseHeaders = exchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/plain");
exchange.sendResponseHeaders(200, 0);
OutputStream responseBody = exchange.getResponseBody();
responseBody.write(createMyResponseAsBytes());
responseBody.close();
My question: What happens if I send a response header to indicate success (i.e. response code 200) and perhaps begin to stream back data and then encounter an exception, which would necessitate sending an "internal server error" response code along with some error content? In other words, what action should I take given that I've already sent a partial "success" response back to the client at the point where I encounter the exception?
200 is not sent until you either flush the stream or close it.
But once it is sent, there is nothing you can do about it.
Usually it may happen only when you have a really large amount of data and you use chunking.