I have the following code to perform a GET request on the following URL:
http://rt.hnnnglmbrg.de/server.php/someReferenceNumber
However, here is my output from Logcat:
java.io.FileNotFoundException: http://rt.hnnnglmbrg.de/server.php/6
Why does it return 404 when the URL is clearly valid?
Here is my connect code:
/**
* Performs an HTTP GET request that returns base64 data from the server
*
* #param ref
* The Accident's reference
* #return The base64 data from the server.
*/
public static String performGet(String ref) {
String returnRef = null;
try {
URL url = new URL(SERVER_URL + "/" + ref);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
returnRef = builder.toString();
} catch (IOException e) {
e.printStackTrace();
}
return returnRef;
}
When you request the URL, it actually return HTTP code 404 which mean not found. If you have control to the PHP script, set the header to 200 to indicate file is found.
You are getting a 404, as said above. To avoid an exception, try something like this:
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect () ;
int code = con.getResponseCode() ;
if (code == HttpURLConnection.HTTP_NOT_FOUND)
{
// Handle error
}
else
{
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
// etc...
}
Never trust what you see in your browser. Always try to mimic your request using something like curl, and you'll clearly see that you're getting an HTTP 404 response code.
java.net will translate the HTTP 404 code to a FileNotFoundException
curl -v http://rt.hnnnglmbrg.de/server.php/4
* About to connect() to rt.hnnnglmbrg.de port 80 (#0)
* Trying 217.160.115.112... connected
* Connected to rt.hnnnglmbrg.de (217.160.115.112) port 80 (#0)
> GET /server.php/4 HTTP/1.1
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
> Host: rt.hnnnglmbrg.de
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Mon, 11 Jun 2012 07:34:55 GMT
< Server: Apache
< X-Powered-By: PHP/5.2.17
< Transfer-Encoding: chunked
< Content-Type: text/html
<
* Connection #0 to host rt.hnnnglmbrg.de left intact
* Closing connection #0
0
From the javadocs at http://docs.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html
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.
Related
I would like to access the link http://www.nation.co.ke/business/seedsofgold/Egg-imports-from-Uganda-hatch-big-losses-for-farmers/-/2301238/2897930/-/dpeqesz/-/index.html
The link is publicly accessible, and can even load using curl
But in Java code it throws Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: http://www.nation.co.ke/business/seedsofgold/Egg-imports-from-Uganda-hatch-big-losses-for-farmers/-/2301238/2897930/-/dpeqesz/-/index.html
This is the code:
/**
*
* #param url the HTML page
* #throws IOException
*/
public static String getPage(String url) throws IOException {
URL u = new URL(url);
URLConnection conn = u.openConnection();
String mime = conn.getContentType();
if( !StringUtils.containsIgnoreCase(mime, "text/html") ) {
return null; // don't continue if not HTML
}
else {
// read the response body, using BufferedReader for performance
InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.defaultCharset()));
int n = 0, totalRead = 0;
char[] buf = new char[1024];
StringBuilder content = new StringBuilder();
// read until EOF or first 16384 characters
while (totalRead < 16384 && (n = reader.read(buf, 0, buf.length)) != -1) {
content.append(buf, 0, n);
totalRead += n;
}
reader.close();
}
The error is thrown at:
InputStream in = conn.getInputStream();
The same code works fine with other URLs.
try to add
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
to your connection right after URLConnection conn = u.openConnection();. Many websites block the site access when no correct agent is set.
If you are getting HTTP 403 status code, it means access to the resource identified by the URL is forbidden for some reason.
A web server may return a 403 Forbidden HTTP status code in response to a request from a client for a web page or resource to indicate that the server can be reached and understood the request, but refuses to take any further action.
You can refer HTTP 403 status code
I am trying to get response from HttpURLConnection but it throws java.io.FileNotFoundException.
HttpURLConnection :
/**
* Call URL using HttpURLConnection
*
* #param url - the URL to be called
**/
public static String getHUCResponse(String url) throws IOException {
InputStream inps = null;
String res = "";
try {
URL getURL = new URL(url);
HttpURLConnection huc = ( HttpURLConnection ) getURL.openConnection ();
huc.setConnectTimeout(60000); // 1 minute
huc.setReadTimeout(60000); // 1 minute
huc.setRequestMethod("GET");
inps = huc.getInputStream(); // throws java.io.FileNotFoundException
res = IOUtils.toString(inps,"UTF8");
}
catch (IOException except){
throw except;
}
finally {
IOUtils.closeQuietly(inps);
}
return res;
}
Error trace:
java.io.FileNotFoundException: url
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1401)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at HttpUtils.getHUCResponse(HttpUtils.java:440)
curl:
$ curl url
user not found
$ curl -I url
HTTP/1.1 404 Not Found
Server: nginx/1.4.2
Date: Sat, 26 Oct 2013 23:45:20 GMT
Content-Length: 14
Connection: keep-alive
I expected to get "user not found" as response from HttpURLConnection since this is what is being returned with 404 error.
What could I be missing?
Thanks.
When the error code is 400 or higher you will get the input stream of the response with getErrorStream rather than getInputStream (yes, I know, someone thought this would be a good idea somehow).
When you call getInputStream but the code is 400 or higher then I think I remember getting null in that case but it seems to be getting you a FileNotFoundException, you just need to add a check for the getResponseCode() and use the right method to get the stream.
Am, Java is doing things righ. 404 http code equals to FileNotFoundException. user not found is strange error message which you will never see from HttpURLConnection
I am able to send data to a sinatra server (Strings) but I'm not sure about how to actually receive it in the sinatra code. Could anyone help?
Java client (what i'm using to send data) code:
private static void contactServer() {
try {
String text = "This is a text please work";
Socket sock = new Socket("localhost", 4567);
OutputStream os = sock.getOutputStream();
URL url = new URL("http://localhost:4567/hello");
PrintWriter writer = new PrintWriter(os);
writer.flush();
writer.write(text);
url.openStream();
System.out.println("done");
String strTemp = "";
/*while(null != (strTemp = br.readLine())){
System.out.println(strTemp);
}*/
} catch (Exception e) {
e.printStackTrace();
}
}
That's not going to work. Sinatra's server understands and speaks a language called the http protocol, so sending the string:
"This is a text please work"
through a socket to a Sinatra app is a hopeless prayer.
A protocol is a set of rules that specify how the client and the server will speak to each other--then each party can understand exactly what other party is saying. For the http protocol, clients send something known as a request, and servers reply with something known as a response. The request and the response must be formatted precisely according to the rules specified by the http protocol. The gory details for a request are here:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
So your java program needs to send a request to Sinatra's server, which is simply a string formatted in a precise manner. Here is what a simple GET request looks like:
GET /path/to/page HTTP/1.1
Host: localhost:4567
If you want to make a GET request for the page:
http://localhost:4567/page1
(i.e. hit the Sinatra route get '/page1')
...then a simple GET request for that page would look like:
GET /page1 HTTP/1.1
Host: localhost:4567
Also, you must end every line in the http request with "\r\n" no matter what OS you are using. Those two characters are part of the http protocol. Furthermore, after the last header there must be a blank line signified by another "\r\n", like this:
GET /page1 HTTP/1.1\r\nHost: localhost:4567\r\n\r\n
Here is the java:
import java.io.*;
import java.net.*;
public class Sinatra {
private static void contactServer() {
try {
Socket sock = new Socket("localhost", 4567);
OutputStream os = sock.getOutputStream();
PrintWriter writer = new PrintWriter(os);
String[] text = {
"GET /page1 HTTP/1.1",
"Host: localhost:4567",
};
String request = "";
for(int i=0; i < text.length; ++i) {
request += text[i] + "\r\n";
}
request += "\r\n";
System.out.println(request);
writer.write(request);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Sinatra.contactServer();
}
}
Note: the first few times I ran that java program, the server(which I started with $ ruby myapp.rb) threw the following error:
[2013-08-19 20:10:11] ERROR Errno::ECONNRESET: Connection reset by peer
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpserver.rb:80:in `eof?'
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpserver.rb:80:in `run'
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'
But when I ran the java program a few more times, the server eventually behaved. I have no idea what is causing that error. When I entered the url in FireFox, the server never threw that error. So I used Firebug to look at the request that Firefox sends; then I used all the same request headers in the java program, but the server still threw that error.
Edit: I can get the server error to go away by making the java program sleep for 1 second before closing the socket. The socket closes when you explicitly close the socket or when the program ends. Without the sleep, I think the socket closes while the server is still processing the request. Because a browser keeps the socket open, a browser never causes the server to throw that error.
The same server error also occurs with a ruby client:
require 'socket'
port = 4567
host = 'localhost'
s = TCPSocket.new host, port
req = [
"GET /page1 HTTP/1.1",
"Host: localhost:4567",
"Accept: */*",
]
req = req.join("\r\n") << ("\r\n" * 2)
print req
s.write req
s.flush
#sleep(1)
s.close
And the fix is the same. The only niggling detail is why the curl unix command doesn't cause the server to throw that error:
$ curl -v http://localhost:4567/page1
* About to connect() to localhost port 4567 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 4567 (#0)
> GET /page1 HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8r zlib/1.2.3
> Host: localhost:4567
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 0
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20)
< Date: Tue, 20 Aug 2013 04:59:16 GMT
< Connection: Keep-Alive
<
* Connection #0 to host localhost left intact
* Closing connection #0
With the -v option, curl prints out the request and the response. Using curl to make the request, I never saw the sever throw that error. I wonder if curl does a sleep too?
I posted before but now I seem to actually see the problem, just having trouble fixing it.
I am trying to login to my schools grade website, maybe even make an app for it later, and when I use Chrome to inspect the cookies being created, I get all these,
Cookie:appName=chippewa_falls; tool=""; selection=""; districtID=1; endYear=2011; calendarID=0; permCalendarID=0; JSESSIONID=BE5AEF51EAA72975150FC2D0F77DDE13
But when my program prints all the cookies it received, I only get this
[version: 0][name: JSESSIONID][value: BC1BAA33BEB23DC27B7883AC24934A1D][domain: campus.chipfalls.k12.wi.us][path: /campus][expiry: null]
here is my code,
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("https://campus.chipfalls.k12.wi.us/campus/portal/chippewa_falls.jsp");
httpget.addHeader("Referer", "http://cfsd.chipfalls.k12.wi.us//high/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println("Login form get: " + response.getStatusLine());
if (entity != null) {
InputStream input = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String ln = "";
while((ln = reader.readLine()) != null) {
System.out.println("During Get - " + ln);
}
}
System.out.println("Initial set of cookies:");
List<Cookie> cookies = httpclient.getCookieStore().getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
}
Note that is just for the GET part of it,
Thanks for any help :)
Edit: I did forget to mention, it is using HTTPS, but to be honest, I don't know if that matters with apache client or not.
Those cookies must be getting set AFTER you login, not before. Looking at the output with wget of the URL you have above you see this:
Resolving campus.chipfalls.k12.wi.us... 205.213.253.11
Connecting to campus.chipfalls.k12.wi.us|205.213.253.11|:443... connected.
WARNING: Certificate verification error for campus.chipfalls.k12.wi.us: self signed certificate in certificate chain
HTTP request sent, awaiting response...
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=004549BDBCBDFB8289EBF859A4E743B2; Path=/campus; Secure
Content-Type: text/html;charset=utf-8
Content-Length: 6352
Date: Tue, 17 May 2011 06:00:38 GMT
Connection: keep-alive
Length: 6,352 (6.2K) [text/html]
which is the exact same thing you see. Until you actually log in you will not see the other cookies.
I am trying to connect to a URL from a desktop app, and I get the error indicated in the Title of my question, but when I tried to connect to the same URL from servlet, all works fine. When I load the URL from browser, all works fine. I am using the same code in the servlet. The code was in a library, when it didn't work, I pulled the code out to a class in the current project, yet it didn't work.
The URL https://graph.facebook.com/me.
The Code fragment.
public static String post(String urlSpec, String data) throws Exception {
URL url = new URL(urlSpec);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(data);
writer.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
StringBuilder builder = new StringBuilder();
while((line = reader.readLine()) != null) {
builder.append(line);
}
return builder.toString();
}
I'm a little bit confused here, is there something that is present is a servlet that is not a normal desktop app?
Thanks.
FULL STACK TRACE
Feb 8, 2011 9:54:14 AM com.trinisoftinc.jiraffe.objects.FacebookAlbum create
SEVERE: null
java.io.IOException: Server returned HTTP response code: 400 for URL: https://graph.facebook.com/me
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1313)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at com.jiraffe.helpers.Util.post(Util.java:49)
at com.trinisoftinc.jiraffe.objects.FacebookAlbum.create(FacebookAlbum.java:211)
at com.trinisoftinc.jiraffe.objects.FacebookAlbum.main(FacebookAlbum.java:261)
EDIT: You need to find the exact error message that facebook is sending in the response
You can modify your code to get the message from the error stream like so:
HttpURLConnection httpConn = (HttpURLConnection)connection;
InputStream is;
if (httpConn.getResponseCode() >= 400) {
is = httpConn.getErrorStream();
} else {
is = httpConn.getInputStream();
}
Take a look at how you are passing the user context
Here's some information that could help you out:
Look at the error message behind the 400 response code:
"Facebook Platform" "invalid_request" "An active access token must be used to query information about the current user*
You'll find the solution here
HTTP/1.1 400 Bad Request
...
WWW-Authenticate: OAuth "Facebook Platform" "invalid_request" "An active access token must be used to query information about the current user."
...
I finally found the problem. Of course it's my code. One part of the code I didn't post is the value of data. data must contain only name and description but I am passing more than name and description.