How-to Test/"Drive" HttpRequest.java (Web Server)? - java

I am writing simple, unsophisticated web-server code in java. It seems to be finished, but I'm not quite sure how to test it. Could someone point me in the right direction? All the coding is finished, I just need to test the code. I tried running it from the terminal, and then connecting to localhost with a specified port, but I only get 404 NOT FOUNDs. I reiterate, I don't think this is a problem with the code, but with my guessing at methods by which to test drive said code. Ideas?
import java.io.*;
import java.net.*;
import java.util.*;
final class HttpRequest implements Runnable {
final static String CRLF = "\r\n";
Socket socket;
// Constructor
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
// Implement the run() method of the Runnable interface.
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private static void sendBytes(FileInputStream fis, OutputStream os)
throws Exception {
// Construct a 1K buffer to hold bytes on their way to the socket.
byte[] buffer = new byte[1024];
int bytes = 0;
// Copy requested file into the socket's output stream.
while((bytes = fis.read(buffer)) != -1 ) {
os.write(buffer, 0, bytes);
}
}
private static String contentType(String fileName) {
if(fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")) {
return "image/jpeg";
}
if(fileName.endsWith(".gif")) {
return "image/gif";
}
return "application/octet-stream";
}
private void processRequest() throws Exception {
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input stream filters.
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// Get the request line of the HTTP request message.
String requestLine = new String(br.readLine());
// Display the request line.
System.out.println();
System.out.println(requestLine);
// Get and display the header lines.
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
// Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
tokens.nextToken(); // skip over the method, which should be "GET"
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
// Open the requested file.
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
// Construct the response message.
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "200 OK" + CRLF;
contentTypeLine = "Content-type: " +
contentType( fileName ) + CRLF;
} else {
statusLine = "404 NOT FOUND" + CRLF;
contentTypeLine = "Content Not Found!" + CRLF;
entityBody = "<HTML>" +
"<HEAD><TITLE>Not Found</TITLE></HEAD>" +
"<BODY>Not Found</BODY></HTML>";
}
// Send the status line.
os.writeBytes(statusLine);
// Send the content type line.
os.writeBytes(contentTypeLine);
// Send a blank line to indicate the end of the header lines.
os.writeBytes(CRLF);
// Send the entity body.
if (fileExists) {
sendBytes(fis, os);
fis.close();
} else {
os.writeBytes("File DNE: Content Not Found!");
}
// Close streams and socket.
os.close();
br.close();
socket.close();
}
public static void main(String[] args) throws Exception {
final ServerSocket ss = new ServerSocket(8080);
while (true)
new HttpRequest(ss.accept()).run();
}
}
Solution:
SOLVED. It turns out, to test it, all you need to do is:
1) run the program from the terminal as per usual,
2) place the file you want to try to retrieve (lets say "example.html") into the same folder as your .java file(s),
3) in a separate terminal, run the command $ wget localhost:PORT/FILE.EXTENSION
(I used port 8080 here, so $ wget localhost:8080/example.html)
You should now see, in the folder you are currently sending the wget command from, an html response file "200 OK" or "404 File Not Server", along with the contents of the file if the former is true.
I was over-complicating this, as were the comments/replies... But it's done.
Guessing and checking ftw.

SOLVED. It turns out, to test it, all you need to do is:
1) run the program from the terminal as per usual,
2) place the file you want to try to retrieve (lets say "example.html") into the same folder as your .java file(s),
3) in a separate terminal, run the command $ wget localhost:PORT/FILE.EXTENSION
(I used port 8080 here, so $ wget localhost:8080/example.html)
You should now see, in the folder you are currently sending the wget command from, a response file "200 OK" or "404 File Not Server", along with the contents of the file if the former is true.
I was over-complicating this, as were the comments/replies... But it's done.
Guessing and checking ftw.

Related

BufferReader stuck in readline()

I am making an HTTP server and HTTP web client for simple Http request and response.
This is the code for Server
import java.io.*;
import java.net.*;
import java.util.*;
public final class WebServer{
public static void main(String[] args) throws Exception{
//storing port number
int port = 2048;
//open socket and wait for TCP connection
ServerSocket serverConnect = new ServerSocket(port);
System.out.println("Server started.\nListening for connections on port : " + port + " ...\n");
// we listen until user halts server execution
while (true) {
//Construct an object to process the HTTP request message.
//This will call another class where we do everything else
HttpRequest request = new HttpRequest(serverConnect.accept());
//create a new thread to process the request
Thread thread = new Thread(request);
thread.start();
} //end of while
}//end of main
}//end of the class webServer
The code for HttpRequest class is as follow:
import java.io.*;
import java.net.*;
import java.util.*;
final class HttpRequest implements Runnable{
final static String CRLF = "\r\n";
Socket socket;
//start of constructor
public HttpRequest(Socket socket) throws Exception{
this.socket=socket;
}//end of constructor
//Implement the run() method of the Runnable interface.
public void run(){
try{
processRequest();
}
catch(Exception e){
System.out.println(e);
}
}//end of run
private void processRequest() throws Exception{
//Get a reference to the scoket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
//set up the stream filters
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//Get the request line of the HTTP request message.
String requestLine = br.readLine();
//Display the request line
System.out.println();
System.out.println(requestLine);
//Get and display the header lines.
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println(headerLine);
}
//System.out.println(requestLine);
//Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
tokens.nextToken(); //skip over the method, which should be. "GET"
String fileName = tokens.nextToken();
//Prepend a "." so that file request is within the current directory
fileName = "." + fileName;
//printing for test
//System.out.println(fileName);
//Open the requested file
FileInputStream fis = null;
boolean fileExists = true;
try{
fis = new FileInputStream(fileName);
}
catch(FileNotFoundException e){
fileExists = false;
}
//Construct the response message
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if(fileExists){
statusLine = tokens.nextToken();
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
}
else{
statusLine = "HTTP/1.1 404 File Not Found";
contentTypeLine = "Content-type: " + "text/html" + CRLF;
entityBody = "<html><head><title>Not Found </title></head>" +
"<BODY>Not Found</body></html>";
}
//send the status line
os.writeBytes(statusLine);
//send the content Type
os.writeBytes(contentTypeLine);
//send a blank line to indicate the end of the header lines
os.writeBytes(CRLF);
//send the entity Body
if(fileExists){
sendBytes(fis, os);
fis.close();
}
else{
os.writeBytes(entityBody);
os.writeBytes(CRLF);
}
//Close scokets and streams.
fis.close();
os.close();
br.close();
socket.close();
}//end of processRequest
private static String contentType(String fileName){
if(fileName.endsWith(".htm") || fileName.endsWith(".html")){
return "text/html";
}
if(fileName.endsWith(".gif")){
return "image/gif";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")){
return "image/jpeg";
}
return "application/octet-stream";
}// end of contentType
private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception{
//Construct a 1k buffer to hold bytes on their way to the Socket
byte[] buffer = new byte[1024];
int bytes = 0;
//Copy requested file into the scoket's output stream.
while((bytes = fis.read(buffer)) != -1){
os.write(buffer, 0, bytes);
}//end of while
}//end of sendBytes
} // end of the class
The Code works fine when I make a request from Chrome webbrowser. However, I made WebClient as well. When I make request from WebClient, I am stuck as the program runs forever.
As far I have tracked, the pointer does not move from the br.readline on the while loops on the Server Side.
The code for my client is as follow.
import java.io.*;
import java.net.*;
import java.util.*;
public class WebClient{
final static String CRLF = "\r\n";
public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
// System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("GET /" +args[2] +" HTTP/1.1");
out.writeUTF(CRLF);
out.writeUTF("Host: "+client.getLocalSocketAddress());
out.writeUTF(CRLF);
out.writeUTF("Connection: close" + CRLF);
out.writeUTF("User-agent: close" + CRLF);
out.writeUTF(CRLF);
//Cache-Control: max-age=0
System.out.println("Just connected to 1 ");
InputStream inFromServer = client.getInputStream();
System.out.println("Just connected to 2 ");
BufferedReader br = new BufferedReader(new InputStreamReader(inFromServer));
System.out.println("Just connected to 3 ");
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}
System.out.println("Just connected to 4 ");
client.close();
System.out.println("Just connected to 5 ");
} catch (IOException e) {
e.printStackTrace();
}
}
}//end of the class WebClient
Can anyone help me figure out the problem.
Thanks.
First of all, you have to remove line fis.close(); (right before os.close();) in your HttpRequest class: if no file exists, this line raises NullPointerException because fis is null, so after sending Not Found response to the browser, your server does not close the socket accepted from that browser, that's why even though you see Not Found in your browser, your request never ends.
Secondly, the reason of why your client gets stuck is writeUTF() method that you used for sending request header. Seems that this line out.writeUTF(CRLF); does not really send an empty string but adds some other UTF-related character(s) (you may notice that in your server's console output), so your server gets stuck at while((headerLine = br.readLine()).length()!=0) waiting for the client to send an empty string, but never receives it. You need to replace out.writeUTF(CRLF); with out.writeBytes(CRLF);.
Also, it makes little sense to use BufferedReader for receiving binary files from socket. Reader in general is used with character-input stream, so it is not applicable for your case. You may use InputStream instead, by replacing this fragment:
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}
with this (I chose buffer size of 4096, you may replace it with your preferred value):
int readBytes;
byte[] cbuf = new byte[4096];
while((readBytes=inFromServer.read(cbuf, 0, 4096))>-1){
System.out.println("read: " + readBytes);
}
Note: You may easily notice here that InputStream.read() will fetch not only the file itself but also statusLine, contentTypeLine and two CRLFs, so in case if you would like to separate them from the file, you may read them first, by issuing two "readLines" and then fetch the file only by read()
In your server, you use writeBytes()
Writes out the string to the underlying output stream as a sequence of bytes. Each character in the string is written out, in sequence, by discarding its high eight bits. If no exception is thrown, the counter written is incremented by the length of s.
While you may worry about non-ASCII text, generally this is what you need.
In your client you attempt to use writeUTF()
First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for the character. If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.
While that 2-byte length in the beginning can be useful in other cases, it is not what web servers expect, including yours (and that is correct). So use writeBytes() everywhere in your client, and it will suddenly work:
out.writeBytes("GET /" +args[2] +" HTTP/1.1");
out.writeBytes(CRLF);
out.writeBytes("Host: "+client.getLocalSocketAddress());
out.writeBytes(CRLF);
out.writeBytes("Connection: close" + CRLF);
out.writeBytes("User-agent: close" + CRLF);
out.writeBytes(CRLF);
In fact those extra bytes may be visible in your server output, at least when I ran it in Eclipse, I saw garbage characters, as a combination of mysterious empty space and a tiny question mark in a rectangle (note how they also appear at the end of the lines when CRLF is sent separately):
(The first request is the one issued with writeUTF, and the second one comes from Chrome)

retrieve file from remote ftp to a webserver

Sorry if this seems like a dumb question, but I just start the ftp and webserver thing so I get a little bit confused about it, particularly about the InputStream, fileInputStream and outputStream etc this kind of concepts. So I try to extend the program I write called web server and make it act as a FTP client that request txt file only. So when request a text file (.txt) from within my web browser, the web server will not have a copy of this file. It will instantiate an FtpClient, retrieve the text file from your local FTP server and then send it back to your web browser as an HTTP response.
My code works fine for web server part, following is part of my code:
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input stream filters.
BufferedReader br = new BufferedReader(new InputStreamReader(is));
...
// Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
// skip over the method, which should be "GET"
tokens.nextToken();
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
// Open the requested file.
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
// Construct the response message.
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "HTTP/1.1 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
}
// file doesn't exist
else {
// if the file requested is any type other than a text (.txt) file,
// report // error to the web client
if (!contentType(fileName).equalsIgnoreCase("text/plain")) {
statusLine = "404 Not Found" + CRLF;
contentTypeLine = "no content" + CRLF;
entityBody = "<HTML>" + "<HEAD><TITLE>Not Found</TITLE></HEAD>" + "<BODY>Not Found</BODY></HTML>";
} else {
String server = "127.0.0.1";
// else retrieve the text (.txt) file from your local FTP server
statusLine = "200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
// create an instance of ftp client
FTPClient ftp = new FTPClient();
// connect to the ftp server
ftp.connect(server);
ftp.login(userName, password);
// retrieve the file from the ftp server, remember you need to
// // first upload this file to the ftp server under your user
// ftp directory
ftp.retrieveFile("/folder1/"+ fileName.substring(1), os);
// disconnect from ftp server
ftp.disconnect();
// assign input stream to read the recently ftp-downloaded file
fis = new FileInputStream(fileName);
}
}
// Send the status line.
os.writeBytes(statusLine);
// Send the content type line.
os.writeBytes(contentTypeLine);
// Send a blank line to indicate the end of the header lines.
os.writeBytes(CRLF);
// Send the entity body.
if (fileExists) {
sendBytes(fis, os);
fis.close();
} else {
os.writeBytes(entityBody);
}
os.close();
br.close();
socket.close();
where things get confusing is that in the ftp retrieve part, I don't know if I use the correct method and if I should using "os" the DataOutputStream as argument or something else. Not fully understand the input and output stream thing. what I'm sure is that I want to use
fis = new FileInputStream(fileName);
after I retrieve the file from ftp server.
So can anyone tell me what should I use in the retrieve part?
Thanks!

Generating Http 301 Response Message

I'm trying to create a little web server and have be able to generate Http response messages 200, 301, and 404.
I am able to get 200 and 404 to work, but I am having problems with 301.
When I try to access a page that has "permanently moved" my browser doesn't get redirected and I get a java.lang.NullPointerException from java.
The way I have it determine if the code should be a 301 is it checks a list of strings for the file the client is trying to access, and if the original file they're trying to access has been moved, it will be in the list, along with it's new name/location. So if the original file is "index5.html" and it's been moved to "index.html" then they will be in an array and "index5.html" will be in an index 1 before "index.html"
I'm also just testing this on my own machine so I'm using localhost for the URL and using port 9012.
Here is my code:
import java.io.*;
import java.net.*;
import java.util.*;
public final class HttpRequest implements Runnable {
final static String CarrLine = "\r\n";
Socket clientSocket;
// A list of files that have been moved.
// Even indexes (0, 2, 4, ...) are the original file names.
// Odd indexes (1, 3, 5, ...) are where the files of previous indexes moved to.
static String movedFiles[] = {"index5.html", "index.html", "page.html", "homepage.html"};
// This sets the Httprequest object socket equal to
// the socket the client comes in through
public HttpRequest(Socket socket) throws Exception {
this.clientSocket = socket;
}
// Here we define a new method that overwrites the
// previous method in the Runnables class. This is done
// so that when an Http request is attempted, and
// something goes wrong, our whole web server will
// not fail and crash.
#Override
public void run(){
try {
// This is where the method to actually start the Http request starts.
requestProcessing();
} catch (Exception ex) { System.out.print(ex); }
}
// This is our main processing method to take in out Http request
// and spit out a reponse header along with the requested data,
// if there is any.
void requestProcessing() throws Exception {
Boolean fileExists = false;
String CarrLine = "\r\n";
String statusCode = null;
String responseHeader = "HTTP/1.1 ";
String fileName, line = null;
String clientSentence = null;
ArrayList<String> records = new ArrayList<String>();
FileInputStream requestedFileStream = null;
File requestedFile;
// Starts input from client and establishes filters
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Starts output stream for output to client through socket
DataOutputStream outToClient = new DataOutputStream(clientSocket.getOutputStream());
/*
// Reads in GET from client BufferedReader
while ( (line = inFromClient.readLine()) != null){
records.add(line);
break;
}*/
clientSentence = inFromClient.readLine();
// Parses and stores file name the client wants in a string
fileName = parseGET(clientSentence);
if (!existingFile(fileName)){
// Here is where the 301 response message is generated and
// retrieve the correct filename.
if (hasMoved(fileName) != -1){
statusCode = "301";
responseHeader = responseHeader + statusCode + " Moved Permanently\n";
responseHeader = responseHeader + "Location: localhost:9012/"
+ movedFiles[hasMoved(fileName)] + CarrLine;
}
// This generates the response header for the client
// if the file the client is looking for is not there (404).
else {
statusCode = "404";
responseHeader = responseHeader + statusCode + " Not Found: \n";
responseHeader = responseHeader + "Content-Type: text/html" + CarrLine;
}
}
// This generates the 200 status code response header
// to send to the client saying the file was found.
if (existingFile(fileName)) {
statusCode = "200";
responseHeader = responseHeader + statusCode + " OK: \n";
responseHeader = responseHeader + "Content-Type: " + fileType(fileName) + CarrLine;
requestedFileStream = openFileStream(fileName);
}
// Outputs the response message to the client through a data stream
outToClient.writeBytes(responseHeader);
outToClient.writeBytes(CarrLine);
// If the file the client is requesting exists,
// begin writing file out to client.
if (existingFile(fileName)){
fileWriteOut(requestedFileStream, outToClient);
requestedFileStream.close();
}
else if(hasMoved(fileName) != -1){
outToClient.writeBytes("File Moved");
}
// If the file the client is requesting does not exist,
// return a 404 message.
else {
outToClient.writeBytes("404: File not found!");
}
// Closes all open streams and sockets to the client.
inFromClient.close();
outToClient.close();
clientSocket.close();
}
// This parses the GET line from the client to get the filename the client is requesting
String parseGET(String clientString){
String temp[] = clientString.split(" /");
temp = temp[1].split(" ");
return temp[0];
}
// This is used to find the file the client is requesting.
// It will return null if no file was found/opened.
FileInputStream openFileStream(String file){
FileInputStream fileStream = null;
// Opening the file stream is in a try catch statment so that
// incase there was no file, the program doesn't crash
// and it'll alert the user on the console.
try {
fileStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
System.out.println(e);
return null;
}
return fileStream;
}
// Determines the file type that is being sent to the client
// and returns the appropriate string
String fileType(String clientRequestFile){
// If the file ends in .html or .htm, it will return "text/html"
// so that it can be added to the response message.
if (clientRequestFile.endsWith(".html") || clientRequestFile.endsWith(".htm")){
return "text/html";
}
// If the file ends in .jpg, it will return "text/jpeg"
// so that it can be added to the response message.
if (clientRequestFile.endsWith(".jpg")){
return "text/jpg";
}
// If the file ends in .css, it will return "text/css"
// so that it can be added to the response message.
if (clientRequestFile.endsWith(".css")){
return "text/css";
}
// Returns this by default, if none of the above.
return "application/octet-stream";
}
// This creates a 2k buffer and writes out
// requested filed to the client.
static void fileWriteOut(FileInputStream clientStream, OutputStream toClient) throws Exception{
byte[] buffer = new byte[2048];
int bytes = 0;
while ((bytes = clientStream.read(buffer)) != -1){
toClient.write(buffer, 0, bytes);
}
}
// This determines whether or not a file that
// the client has requested exists or not.
// Returns a Boolean value.
static Boolean existingFile(String fileName){
File file = new File(fileName);
if (file.exists() && !file.isDirectory()){
return true;
}
return false;
}
// Determines if a file has been moved and if so,
// returns the index of the NEW file. Else it
// returns -1.
static int hasMoved(String fileName){
int i = 0;
for (i = 0; i < movedFiles.length; i=i+2){
if (movedFiles[i].equals(fileName)){
return i+1;
}
}
return -1;
}
}
Could someone point me in the right direction to doing this correctly?
Thank you!
Okay, I figured it out.
It was because I was trying to define the entire "URL" in the 301 response messages.
So it should have been:
responseHeader = responseHeader + "Location: /" + movedFiles[hasMoved(fileName)] + CarrLine;
Instead of:
responseHeader = responseHeader + "Location: localhost:9012/" + movedFiles[hasMoved(fileName)] + CarrLine;

Sending HTTP request's

I am writing a web client. I have the following code.
public class Connection extends Thread{
public final static int PORT = 1337;
private ServerSocket svrSocket = null;
private Socket con = null;
public Connection(){
try{
svrSocket = new ServerSocket(PORT);
System.out.println("Conected to: " + PORT);
}catch(IOException ex)
{
System.err.println(ex);
System.out.println("Unable to attach to port");
}
}
public void run(){
while(true)
{
try{
con = svrSocket.accept();//on this part the program stops
System.out.println("Client request accepted");
PrintWriter out = new PrintWriter(con.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
out.println("GET /<index.html> HTTP/1.1");
out.println("***CLOSE***");
System.out.println(in.readLine());
/*
String s;
while((s = in.readLine()) != null)
{
System.out.println(s);
}*/
out.flush();
out.close();
in.close();
con.close();
System.out.println("all closed");
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
}
The run method will be used latter on. That I have is a file called index.html. This file is in the same file as the java code. What I am trying to do with the request is send the HTML file. But if I run this program on a web browser localhost:1337 the following gets displayed.
GET /<index.html> HTTP/1.1
***CLOSE***
This should not get displayed. The page that results of the HTML code in the index.html should get displayed.
Index.html code:
<html>
<head>
<title> </title>
</head>
<body bgcolor = "#ffffcc" text = "#000000">
<h1>Hello</h1>
<p>This is a simple web page</p>
</body>
</html>
How do I get this html page to display in the browser?
Thank you
t seems that all is good on your code, it seems you need to read the HTTP header from the input stream so you can get the requested file name and then use the Socket output stream to write the response from the file.
OutputStream output = con.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String fileName = readHeader(in);
String baseDir = System.getProperty("my.base.dir", "/home/myname/httpserver");
boolean exist = true;
InputStream fileIn = null;
try {
File requestedFile = new File(baseDir, fileName);
fileIn = new FileInputStream(requestedFile);
} catch(Exception e){
exist = false;
}
String server = "Java Http Server";
String statusLine = null;
String typeLine = null;
String body = null;
String lengthLine = "error";
if (exist) {
statusLine = "HTTP/1.0 200 OK" + "\r\n";
//get content type by extension
typeLine = "Content-type: html/text \r\n";
lengthLine = "Content-Length: " + (new Integer(fileIn.available())).toString() + "\r\n";
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
typeLine = "text/html";
body = "<HTML>" + "<HEAD><TITLE>404</TITLE></HEAD>" + "<BODY>404 Not Found"+"</BODY></HTML>";
}
output.write(statusLine.getBytes());
output.write(server.getBytes());
output.write(typeLine.getBytes());
output.write(lengthLine.getBytes());
output.write("\r\n".getBytes());
if (exist) {
byte[] buffer = new byte[1024];
int bytes = 0;
while ((bytes = fileIn.read(buffer)) != -1) {
output.write(buffer, 0, bytes);
}
} else {
output.write(body.getBytes());
}
//close sreams
You are confusing a couple of things. First of all: what you are writing is a server, not a client.
Second: You are not following the HTT Protocol.
The line GET /<index.html> HTTP/1.1 (which is wrong, it should be GET /index.html HTTP/1.1) is a request that is sent by the client (like a web browser). Instead, it is your server sending this.
A quick solution:
Instead of sending this static text (the line with the GET and the one with the ***CLOSE***), read the content of your index.html file and print it to your out stream.
EDIT: Here's a quick overview of the http data flow:
The client (e.g. a browser) connects to the server
The client sends it's request, something like
GET /theFileIWant.html HTTP/1.1\r\n
Host: localhost\r\n
\r\n
at this point, the client usually stops sending anything and waits for the server to respond. That is called the "request/response" model.
The server reads the request data and finds out what it has to do.
The output (in this case: a file's content) is sent to the client, preceded by HTTP response headers.
The connection can be kept open or closed, depending on the HTTP headers of both client's request and server's response.

HTTP GET request not working in java when HTTP is 1.1?

so i made a little code that can download 4chan pages. i get the raw HTML page and parse it for my need. the code below was working fine but it suddenly stopped working. when i run it the server does not accept my request it seems its waiting for something more. however i know that HTTP request is as below
GET /ck HTTP/1.1
Host: boards.4chan.org
(extra new line)
if i change this format in anyway i revive "400 bad request" status code. but if i change HTTP/1.1 to 1.0 the server responses in "200 ok" status and i get the whole page. so this makes me thing the error is in the host line since that became mandatory in HTTP/1.1. but still i cannot figure out what exactly need to be changed.
the calling function simply this, to get one whole board
downloadHTMLThread( "ck", -1);
or for a specific thread u just change -1 to that number. for example like for the link below will have like below.
//http://boards.4chan.org/ck/res/3507158
//url.getDefaultPort() is 80
//url.getHost() is boards.4chan.org
//url.getFile() is /ck/res/3507158
downloadHTMLThread( "ck", 3507158);
any advise would be appreciated, thanks
public static final String BOARDS = "boards.4chan.org";
public static final String IMAGES = "images.4chan.org";
public static final String THUMBS = "thumbs.4chan.org";
public static final String RES = "/res/";
public static final String HTTP = "http://";
public static final String SLASH = "/";
public String downloadHTMLThread( String board, int thread) {
BufferedReader reader = null;
PrintWriter out = null;
Socket socket = null;
String str = null;
StringBuilder input = new StringBuilder();
try {
URL url = new URL(HTTP+BOARDS+SLASH+board+(thread==-1?SLASH:RES+thread));
socket = new Socket( url.getHost(), url.getDefaultPort());
reader = new BufferedReader( new InputStreamReader( socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println( "GET " +url.getFile()+ " HTTP/1.1");
out.println( "HOST: " + url.getHost());
out.println();
long start = System.currentTimeMillis();
while ((str = reader.readLine()) != null) {
input.append( str).append("\r\n");
}
long end = System.currentTimeMillis();
System.out.println( input);
System.out.println( "\nTime: " +(end-start)+ " milliseconds");
} catch (Exception ex) {
ex.printStackTrace();
input = null;
} finally {
if( reader!=null){
try {
reader.close();
} catch (IOException ioe) {
// nothing to see here
}
}
if( socket!=null){
try {
socket.close();
} catch (IOException ioe) {
// nothing to see here
}
}
if( out!=null){
out.close();
}
}
return input==null? null: input.toString();
}
Try using Apache HttpClient instead of rolling your own:
static String getUriContentsAsString(String uri) throws IOException {
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(new HttpGet(uri));
return EntityUtils.toString(response.getEntity());
}
If you are doing this to really learn the internals of HTTP client requests, then you might start by playing with curl from the command line. This will let you get all your headers and request body squared away. Then it will be a simple matter of adjusting your request to match what works in curl.
By the code I think that you are sending 'HOST' instead of 'Host'. Since this is a compulsory header in http/1.1, but ignored in http/1.0, that might be the problem.
Anyway, you could use a program to capture the packet sent (i. e. wireshark), just to make sure.
Using println is quite useful, but the line separator appended to the command depends on the system property line.separator. I think (although I'm not sure) that the line separator used in http protocol has to be '\r\n'. If you're capturing the packet, I think it'd be a good idea to check that each line sent ends with '\r\n' (bytes x0D0A) (just in case your os line separator is different)
Use www.4chan.org as the host instead. Since boards.4chan.org is a 302 redirect to www.4chan.org, you won't be able to scrape anything from boards.4chan.org.

Categories