I'm using the unirest http wrapper (http://unirest.io/java.html) in a Java application to send http post requests. Unfortunately I keep getting a "broken pipe" error:
com.mashape.unirest.http.exceptions.UnirestException: java.net.SocketException: Broken pipe
com.mashape.unirest.http.exceptions.UnirestException: java.net.SocketException: Broken pipe
at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:145)
at com.mashape.unirest.request.BaseRequest.asString(BaseRequest.java:56)
The code I'm using to call it is as follows:
public static int doHTTPPostWithAdditionalHeaders(String data, String url, HashMap<String, String> additionalHeaders) {
try {
Unirest.setTimeouts(10000, 10000);
HttpResponse<String> jsonResponse = Unirest.post(url)
.headers(additionalHeaders)
.body(data)
.asString();
return jsonResponse.getStatus();
} catch (Exception e) {
System.out.println("doHTTPPostWithAdditionalHeaders failed: "+e.toString());
}
return 0;
}
It works most of the time but seems to fail when I'm hammering it with lots of requests. Have any of you got any ideas how I might solve this, or perhaps could you recommend a more robust solution? This post operation is mission critical to my application.
Looks like it was a simple case of the data I was posting being too large for the allocated timeouts.
Old
Unirest.setTimeouts(10000, 10000);
New
Unirest.setTimeouts(10000, 30000);
Related
I want to be able to verify that the connection is still alive (client not dead) when sending a response from a Jersey (jax-rs) resource. The reason is that if I just return the response object and the client is dead, the response is lost without knowing that the client did not receive it.
httpContext.getResponse().setResponse(myResponse)
try {
httpContext.getResponse().getOutputStream().write(new byte[]{})
} catch (Exception e) {
// writing of headers failed.
}
I am using Apache's HttpClient via httpclient-fluent-builder to download a http page.
This is the code:
...
try {
response = Http.get("http://fr3.ah.fm:9000/played.html")
.use(client) // use this HttpClient (required)
.charset("windows-1252") // set the encoding... (optional)
.asString();
} catch (IOException e) {
Log.d(TAG, "Error: "+e.toString());
e.printStackTrace();
}
Log.i(TAG, ""+ response );
...
Problem is that I get org.apache.http.client.ClientProtocolException
It's something with the host:port/url, beacause it works with urls without ports. I also get this same error with another Httphelper class than fluent-builder. Firewall is off.
Logcat: http://pastebin.com/yMMvvdQ3
Found out what it was via this post that it was the Shoutcast server...
You should be able to connect to 8000
with your web browser and get the DNAS
status page. If, on the other hand,
you connect to that port with a media
player, it'll return the direct MP3
stream. (Unfortunately, in an
incredibly boneheaded piece of design,
the way SHOUTcast decides which to
respond with is by sniffing your
User-Agent header for something
beginning with Mozilla, so if you're
using an alternative browser or
blocking your UA you'll not be able to
get the status, and if the stream's
down you might just get nothing.)
Drove me crazy.. But it's an easy fix. I just added.
.header("User-Agent", "UserAgent: Mozilla/5.0")
try to set the uri using HttpHost and use it in HttpClient.execute().
I have not tried it..
I have code similar to the following:
try {
HttpPost post = new HttpPost(httpsUrl);
setHeaders(post);
HttpEntity entity = new StringEntity(request, "UTF-8");
post.setEntity(entity);
HttpResponse response = httpclient.execute(post);
String result = EntityReader.readContent(response.getEntity());
checkAnswer(result);
return result;
} catch (Exception e) {
throw new ZapException("Error executing the http post request: "+e.getMessage(), e);
}
It sends the content of request to a server via POST using a httpclient instance that might have already been used before (it has persistent connections turned on, since we're sending quite some requests to the same server...).
This sometimes fails with a SocketTimeoutException with "Read timed out" as the message.
It's not clear to us, why it only fails at some times, when most times it doesn't. What gives?
In the following, I assume you are using Apache Commons HttpClient (org.apache.commons.httpclient.HttpClient).
Maybe you get thrown a SocketTimeoutException simply because, occasionally, the host your HttpClient instance is communicating with takes too long to respond, triggering HttpClient's cancellation routine.
You can increase the connection timeout and the socket timeout with the following
HttpConnectionParams params = httpclient.getHttpConnectionManager().getParams();
params.setConnectionTimeout(20000);
params.setSoTimeout(15000);
Aditionally, if you still face timeouts despite increasing the timeout limits, it is a good practice to handle the SocketTimeoutException gracefully - for example by retrying the connection a second and third time.
I was trying to use the Apache Ant Get task to get a list of WSDLs generated by another team in our company. They have them hosted on a weblogic 9.x server on http://....com:7925/services/. I am able to get to the page through a browser, but the get task gives me a FileNotFoundException when trying to copy the page to a local file to parse. I was still able to get (using the ant task) a URL without the non-standard port 80 for HTTP.
I looked through the Ant source code, and narrowed the error down to the URLConnection. It seems as though the URLConnection doesn't recognize the data is HTTP traffic, since it isn't on the standard port, even though the protocol is specified as HTTP. I sniffed the traffic using WireShark and the page loads correctly across the wire, but still gets the FileNotFoundException.
Here's an example where you will see the error (with the URL changed to protect the innocent). The error is thrown on connection.getInputStream();
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class TestGet {
private static URL source;
public static void main(String[] args) {
doGet();
}
public static void doGet() {
try {
source = new URL("http", "test.com", 7925,
"/services/index.html");
URLConnection connection = source.openConnection();
connection.connect();
InputStream is = connection.getInputStream();
} catch (Exception e) {
System.err.println(e.toString());
}
}
}
The response to my HTTP request returned with a status code 404, which resulted in a FileNotFoundException when I called getInputStream(). I still wanted to read the response body, so I had to use a different method: HttpURLConnection#getErrorStream().
Here's a JavaDoc snippet of getErrorStream():
Returns the error stream if the
connection failed but the server sent
useful data nonetheless. The typical
example is when an HTTP server
responds with a 404, which will cause
a FileNotFoundException to be thrown
in connect, but the server sent an
HTML help page with suggestions as to
what to do.
Usage example:
public static String httpGet(String url) {
HttpURLConnection con = null;
InputStream is = null;
try {
con = (HttpURLConnection) new URL(url).openConnection();
con.connect();
//4xx: client error, 5xx: server error. See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
boolean isError = con.getResponseCode() >= 400;
//In HTTP error cases, HttpURLConnection only gives you the input stream via #getErrorStream().
is = isError ? con.getErrorStream() : con.getInputStream();
String contentEncoding = con.getContentEncoding() != null ? con.getContentEncoding() : "UTF-8";
return IOUtils.toString(is, contentEncoding); //Apache Commons IO
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
//Note: Closing the InputStream manually may be unnecessary, depending on the implementation of HttpURLConnection#disconnect(). Sun/Oracle's implementation does close it for you in said method.
if (is != null) {
try {
is.close();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
if (con != null) {
con.disconnect();
}
}
}
This is an old thread, but I had a similar problem and found a solution that is not listed here.
I was receiving the page fine in the browser, but got a 404 when I tried to access it via the HttpURLConnection. The URL I was trying to access contained a port number. When I tried it without the port number I successfully got a dummy page through the HttpURLConnection. So it seemed the non-standard port was the problem.
I started thinking the access was restricted, and in a sense it was. My solution was that I needed to tell the server the User-Agent and I also specify the file types I expect. I am trying to read a .json file, so I thought the file type might be a necessary specification as well.
I added these lines and it finally worked:
httpConnection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
httpConnection.setRequestProperty("Accept","*/*");
check the response code being returned by the server
I know this is an old thread but I found a solution not listed anywhere here.
I was trying to pull data in json format from a J2EE servlet on port 8080 but was receiving the file not found error. I was able to pull this same json data from a php server running on port 80.
It turns out that in the servlet, I needed to change doGet to doPost.
Hope this helps somebody.
You could use OkHttp:
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
I've tried that locally - using the code provided - and I don't get a FileNotFoundException except when the server returns a status 404 response.
Are you sure that you're connecting to the webserver you intend to be connecting to? Is there any chance you're connecting to a different webserver? (I note that the port number in the code doesn't match the port number in the link)
I have run into a similar issue but the reason seems to be different, here is the exception trace:
java.io.FileNotFoundException: http://myhost1:8081/test/api?wait=1
at sun.reflect.GeneratedConstructorAccessor2.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1491)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1485)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
at com.doitnext.loadmonger.HttpExecution.getBody(HttpExecution.java:85)
at com.doitnext.loadmonger.HttpExecution.execute(HttpExecution.java:214)
at com.doitnext.loadmonger.ClientWorker.run(ClientWorker.java:126)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.io.FileNotFoundException: http://myhost1:8081/test/api?wait=1
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1434)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
at com.doitnext.loadmonger.HttpExecution.execute(HttpExecution.java:166)
... 2 more
So it would seem that just getting the response code will cause the URL connection to callGetInputStream.
I know this is an old thread but just noticed something on this one so thought I will just put it out there.
Like Jessica mentioned, this exception is thrown when using non-standard port.
It only seems to happen when using DNS though. If I use IP number I can specify the port number and everything works fine.
If it's any help, there is also a similar class in C#'s WebRequest. Although I do not want it in java or .NET, i am wondering how to implement this in native C/C++ code (for windows).
for reference:
try {
URL url=new URL("http://google.ca");
HttpURLConnection con=(HttpURLConnection)url.openConnection();
con.connect();
int code = con.getResponseCode();
System.out.println(code);
} catch (MalformedURLException e) {
System.err.println("Error reading URL.");
}
prints out:
200
meaning "OK"
I understand I probably need to use sockets and send a User-Agent string, but I haven't a clue where to begin. Whenever I learn a new language the first thing I like to do is try porting my code to it, but this one has stumped me.
Any help is appreciated
There is no HTTP support in standard C library.
So you have two options - use 3rd-party HTTP library, such ar libcurl, or handle HTTP yourself:
open socket
resolve hostname
connect to server
build HTTP request
send request to server
receive HTTP response
parse response and get response code from it.