Reputation: 1578
I am hosting a webpage from home. I made my own HTTP server using Java. This is an SSCCE:
if(command.startsWith("GET"))
{
//client is a socket on which I reply.
PrintWriter pw = new PrintWriter(client.getOutputStream(), true);
String commule = command.split(" ");
if(commule[0].equals("GET"))
{
if(commule[1].contains("."))
{
File file = new File(GEQO_SERVER_ROOT + commule[1].substring(1).replaceAll("%20", " "));
if(file.exists())
{
OutputStream out = client.getOutputStream();
InputStream stream = new FileInputStream(file);
String response = new String();
response += "HTTP/1.1 200 OK\r\n";
response += "Date: Thu, 08 Aug 2013 08:49:37 GMT\r\n";
response += "Content-Type: text/html\r\n";
response += "Content-Length: " + file.length() + "\r\n";
response += "Connection: keep-alive\r\n";
response += "\r\n";
pw.write(response); //Assume I already initialized pw as a PrintWriter
pw.flush();
copy(stream, out);
stream.close();
out.close();
}
else
{
pw.write("<html><h1>The request 404ed.</h1>");
pw.write("<body>The requested URL <b>" + commule[1] + "</b> could not be found on this server.</body></html>");
pw.flush();
}
}
else
{
BufferedReader br = new BufferedReader(new FileReader(GEQO_SERVER_ROOT + commule[1].substring(1) + "main.html"));
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null)
{
pw.print(sCurrentLine);
}
br.close();
}
}
else
{
pw.println("Unrecognized HTTP command.");
}
}
This is the main.html source :
<html>
<title>Geqo Server</title>
<body>Geqo server online and functioning!</body>
</html>
The issue is that when I try to access this page using Chrome, it displays correctly (At least when using 127.0.0.1). But when I tried accessing it on Firefox on 127.0.0.1, it works, but just gives me the html source. IE also only gives me the source. Can anyone tell me why Firefox and IE only show the source, instead of parsing it?
I think this contains some clues (Firebug screenshot) :
My source seems to be coming in a <pre>
tag. I donno why, but isn't that sort of the problem?
I port-forwarded. Here's the page guys : http://110.172.170.83:17416/
(Sorry, Stackoverflow doesn't allows numerical links.)
EDIT : I found the problem. But before I explain, thanks to Bart for the SSCCE, which I used to compare with my code. This is the problem : The if
statement on the eighth line if(commule[1].contains("."))
causes the code to skip the most of the code here. In that respective else
block, there is even no command to send the headers. Thanks to artbristol for pointing that out.
Thanks in advance.
Upvotes: 8
Views: 2938
Reputation: 32407
Your printwriter isn't flushing (as Ernest pointed out), so no HTTP headers are being sent. Look at the result of connecting directly - it just returns the raw data, with no headers.
nc 110.172.170.83 17416
GET /
<html><title>Geqo Server</title><body>Geqo server online and functioning!</body></html>
Writing an HTTP server is hard work. Unless this is for an exercise, you should use a lightweight existing one, such as Jetty, or the built in Sun HTTP server in the JDK.
Edit - A PrintWriter
really isn't appropriate for doing HTTP. It's designed to deal with line-by-line data such as a file being written to disk. It's also dependent on platform-specific settings for text encoding and line endings. Check the HTTP spec for more details on how a proper HTTP server ought to work.
Upvotes: 5
Reputation: 17361
You enabled autoFlush
with the second argument to
new PrintWriter(client.getOutputStream(), true)
http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output. These methods use the platform's own notion of line separator rather than the newline character.
So basically your pw.write()
did not flush to the output stream. So all you need to do is replace
pw.write(response);
with
pw.println(response);
Upvotes: 1
Reputation: 136
You do not send any response header.
I can't find the definition of pw
in your source code?
Upvotes: 0
Reputation: 81684
There would appear to be some potential issues with buffering. You write some of your output to a PrintWriter
wrapper around out
, and other output directly to out
. I would definitely add a call to pw.flush()
after the pw.write()
call.
Upvotes: 1