This is the window that comes up when you run the program,
just a little motivator so you can see what's in the end of the
tunnel.

Note to get the maximum
out of this tutorial it is recommended that you have a basic
grasp on how HTTP works. If the little man inside your head says
what tha H is HTTP, you should go to the bottom and check some
of the pointers. There you will find some nice text to explain
the basic concept.

Let's get started!
When making a program nowadays the first thing you should think
about is the GUI (graphical user interface). If the program dosen't
look fancy, you can just press all the cancel buttons on the
project. Ok that was meant as a joke, but there is some truth
in it. People tend to judge a program a lot on its look, even
though the real coding job is in making the stuff that goes on
behind the scenes.

The good news is that we are making this in Java, and since
Java is such a friendly programming language it's real easy to
get some interface going. Comments are in green.

In a nutshell this code sets up the window and makes everything
look good. If you look at the picture of the program on top of
this page. This code makes that!

Ok, enough time wasted on the look. Lets get down with the
fun stuff, making the actual httpserver.

//file: server.java//the real (http) serverclass//it extends thread so the server is run in a different//thread than the gui, that is to make it responsive.//it's really just a macho coding thing.public class serverextends Thread {//the constructor method//the parameters it takes is what port to bind to, the default tcp port//for a httpserver is port 80. the other parameter is a reference to//the gui, this is to pass messages to our nice interfacepublic server(int listen_port, webserver_starter to_send_message_to) {message_to = to_send_message_to;port = listen_port;//this makes a new thread, as mentioned before,it's to keep gui in//one thread, server in another. You may argue that this is totally//unnecessary, but we are gonna have this on the web so it needs to//be a bit macho! Another thing is that real pro webservers handles//each request in a new thread. This server dosen't, it handles each//request one after another in the same thread. This can be a good//assignment!! To redo this code so that each request to the server//is handled in its own thread. The way it is now it blocks while//one client access the server, ex if it transferres a big file the//client have to wait real long before it gets any response.this.start();}private void s(String s2) { //an alias to avoid typing so much!message_to.send_message_to_window(s2);}private webserver_starter message_to; //the starter class, needed for guiprivate int port; //port we are going to listen to//this is a overridden method from the Thread class we extended frompublic void run() {//we are now inside our own thread separated from the gui.ServerSocket serversocket = null;//To easily pick up lots of girls, change this to your name!!!s("The simple httpserver v. 0000000000\nCoded by Jon Berg" +"<jon.berg[on server]turtlemeat.com>\n\n");//Pay attention, this is where things starts to cook!try {//print/send message to the guiwindows("Trying to bind to localhost on port " + Integer.toString(port) + "...");//make a ServerSocket and bind it to given port,serversocket = new ServerSocket(port);}catch (Exception e) { //catch any errors and print errors to guis("\nFatal Error:" + e.getMessage());return;}s("OK!\n");//go in a infinite loop, wait for connections, process request, send responsewhile (true) {s("\nReady, Waiting for requests...\n");try {//this call waits/blocks until someone connects to the port we//are listening toSocket connectionsocket = serversocket.accept();//figure out what ipaddress the client commes from, just for show!InetAddress client = connectionsocket.getInetAddress();//and print it to guis(client.getHostName() + " connected to server.\n");//Read the http request from the client from the socket interface//into a buffer.BufferedReader input =new BufferedReader(new InputStreamReader(connectionsocket.getInputStream()));//Prepare a outputstream from us to the client,//this will be used sending back our response//(header + requested file) to the client.DataOutputStream output =new DataOutputStream(connectionsocket.getOutputStream());//as the name suggest this method handles the http request, see further down.//abstraction ruleshttp_handler(input, output);}catch (Exception e) { //catch any errors, and print thems("\nError:" + e.getMessage());}} //go back in loop, wait for next request}//our implementation of the hypertext transfer protocol//its very basic and stripped downprivate void http_handler(BufferedReader input, DataOutputStream output) {int method = 0; //1 get, 2 head, 0 not supportedString http = new String(); //a bunch of strings to holdString path = new String(); //the various things, what http v, what path,String file = new String(); //what fileString user_agent = new String(); //what user_agenttry {//This is the two types of request we can handle//GET /index.html HTTP/1.0//HEAD /index.html HTTP/1.0String tmp = input.readLine(); //read from the streamString tmp2 = new String(tmp);tmp.toUpperCase(); //convert it to uppercaseif (tmp.startsWith("GET")) { //compare it is it GETmethod = 1;} //if we set it to method 1if (tmp.startsWith("HEAD")) { //same here is it HEADmethod = 2;} //set method to 2if (method == 0) { // not supportedtry {output.writeBytes(construct_http_header(501, 0));output.close();return;}catch (Exception e3) { //if some error happened catch its("error:" + e3.getMessage());} //and display error}//}//tmp contains "GET /index.html HTTP/1.0 ......."//find first space//find next space//copy whats between minus slash, then you get "index.html"//it's a bit of dirty code, but bear with me...int start = 0;int end = 0;for (int a = 0; a < tmp2.length(); a++) {if (tmp2.charAt(a) == ' ' && start != 0) {end = a;break;}if (tmp2.charAt(a) == ' ' && start == 0) {start = a;}}path = tmp2.substring(start + 2, end); //fill in the path}catch (Exception e) {s("errorr" + e.getMessage());} //catch any exception//path do now have the filename to what to the file it wants to opens("\nClient requested:" + new File(path).getAbsolutePath() + "\n");FileInputStream requestedfile = null;try {//NOTE that there are several security consideration when passing//the untrusted string "path" to FileInputStream.//You can access all files the current user has read access to!!!//current user is the user running the javaprogram.//you can do this by passing "../" in the url or specify absoulute path//or change drive (win)//try to open the file,requestedfile = new FileInputStream(path);}catch (Exception e) {try {//if you could not open the file send a 404output.writeBytes(construct_http_header(404, 0));//close the streamoutput.close();}catch (Exception e2) {};s("error" + e.getMessage());} //print error to gui//happy day scenariotry {int type_is = 0;//find out what the filename ends with,//so you can construct a the right content typeif (path.endsWith(".zip" ) {type_is = 3;}if (path.endsWith(".jpg") || path.endsWith(".jpeg")) {type_is = 1;}if (path.endsWith(".gif")) {type_is = 2;//write out the header, 200 ->everything is ok we are all happy.}output.writeBytes(construct_http_header(200, 5));//if it was a HEAD request, we don't print any BODYif (method == 1) { //1 is GET 2 is head and skips the bodywhile (true) {//read the file from filestream, and print out through the//client-outputstream on a byte per byte base.int b = requestedfile.read();if (b == -1) {break; //end of file}output.write(b);}}//clean up the files, close open handlesoutput.close();requestedfile.close();}catch (Exception e) {}}//this method makes the HTTP header for the response//the headers job is to tell the browser the result of the request//among if it was successful or not.private String construct_http_header(int return_code, int file_type) {String s = "HTTP/1.0 ";//you probably have seen these if you have been surfing the web a whileswitch (return_code) {case 200:s = s + "200 OK";break;case 400:s = s + "400 Bad Request";break;case 403:s = s + "403 Forbidden";break;case 404:s = s + "404 Not Found";break;case 500:s = s + "500 Internal Server Error";break;case 501:s = s + "501 Not Implemented";break;}s = s + "\r\n"; //other header fields,s = s + "Connection: close\r\n"; //we can't handle persistent connectionss = s + "Server: SimpleHTTPtutorial v0\r\n"; //server name//Construct the right Content-Type for the header.//This is so the browser knows what to do with the//file, you may know the browser dosen't look on the file//extension, it is the servers job to let the browser know//what kind of file is being transmitted. You may have experienced//if the server is miss configured it may result in//pictures displayed as text!switch (file_type) {//plenty of types for you to fill incase 0:break;case 1:s = s + "Content-Type: image/jpeg\r\n";break;case 2:s = s + "Content-Type: image/gif\r\n";case 3:s = s + "Content-Type: application/x-zip-compressed\r\n";default:s = s + "Content-Type: text/html\r\n";break;}////so on and so on......s = s + "\r\n"; //this marks the end of the httpheader//and the start of the body//ok return our newly created header!return s;}} //class phhew caffeine yes please!

BEWARE! When you run the web server you
are potentially opening for all your files to be red by the entire
Internet! The httpserver is only ment to be used for testing.
If you absoulutely want to run this httpserver for longer periods
of time; consider creating a new user with only read access to
the files you want to share and running it only with this user!

Download
the tutorial files!this
zipfile contains both sourcecode and compiled javabytecode files.
So you can test the program without having the javacompiler.
It also contains a sample index.html and a jpg file.

How to run the program? Get into commandline, cd to the dir
where you extracted the files (webserver_starter.class and the
other files). Then type: java webserver_starter

Then the window you see on top of this page should pop up.
To test if this httpserver is really functioning, you open your
browser, and in the location line you type: http://localhost/index.html
,this will bring up a sample html file that is in the zipfile.

If you want to test the httpserver from another machine on
the Internet, then you need to know the ip-address or hostname
the httpserver is running on, then you type that in the location
line in the browser, like http://123.123.123.123/index.html .Note,
it may not work if you are behind a firewall or a NAT router,
but that's not the programs' fault!

Update: Oct 2011. This code is not actively updated, but I changed a few
things mainly due to many people are referencing this. The switch (file_type) was
missing breaks. requestedfile.read() and output.write() now reads and writes a byte array which speeds things up.
And added favicon support since somebody asked about it.

How to compile: Open command line. cd to directory where you unpacked it. javac *.java
How to run: Open command line. cd to directory where you unpacked it. java -cp . webserver_starter

Pointers to related stuff on the hypertext
transfer protocol (http) and web servers:

HowStuffWorks
This is a very basic introduction for the novice on how web servers
works. Has also other text about Internet and Routers, in easy
to understandable language. Nice if you are starting out learning.

HTTP Made Really
Easy Here is some nice text that goes through the main points
in HTTP. A little more technical. It's recommended that you know
these things to understand the above tutorial.

Apache the best and most
widely used web server on the Internet today, check it out. If
you want to run your own web server this is the one to get, you
can get binaries for both Windows and Unix. You can download
the entire sourcecode if you want to check how it was made.

Mozilla / Netscape is
a nice web browser. Get rid of the Explorer, there are some rumors
that Internet Explorer secretly collects all the pages you are
visiting and sends it to microsoft.com.