I worked with HTTP Servers for a long time but I never tried to explore how an HTTP server works, so let do it together.
What is an HTTP server actually?
A server which runs in a computer to serve HTTP request from remote browsers.How it works?
As a user when we type an URL (Unified Resource Locator) in our browser it sends an HTTP request to the internet then it forwarded to the concerned server, the server process the request and send back HTTP response to the client browser.Okay, it sounds simple to make HTTP server work.
Let's get into it.
A Server class which creates a server program, do initial setup for web server operation like port number, file directory etc then it run in an infinite loop and wait for requests.
A Server class which creates a server program, do initial setup for web server operation like port number, file directory etc then it run in an infinite loop and wait for requests.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @Author Anindya Bandopadhyay | |
* | |
* SimpleHttpWebServer\andy.blog.web.server.Server.java | |
* | |
* @Created on Sep 14, 2014 6:55:31 PM | |
*/ | |
package andy.blog.web.server; | |
import java.io.File; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
import java.net.InetAddress; | |
import java.net.ServerSocket; | |
import java.net.Socket; | |
import andy.blog.constant.ServerConstant; | |
public class Server { | |
private boolean serverStart = true; | |
private int port = ServerConstant.PORT; | |
private String webRootPath = ServerConstant.DEFAULT_WEB_ROOT; | |
private File webRootDir = new File(ServerConstant.WORKING_DIR, webRootPath); | |
public static void main(String[] args) { | |
Server server = new Server(); | |
server.initialSetUp(args); | |
server.waitForClient(); | |
} | |
private void initialSetUp(String[] args) { | |
for (int index = 0; index < args.length; index++) { | |
switch (index) { | |
case 0: | |
break; | |
case 1: | |
try { | |
port = Integer.valueOf(args[1]); | |
} catch (NumberFormatException e) { | |
throw new IllegalArgumentException("Port number must be numeric."); | |
} | |
break; | |
case 2: | |
webRootPath = args[2]; | |
webRootDir = new File(ServerConstant.WORKING_DIR, webRootPath); | |
if (!(webRootDir.exists() && webRootDir.isDirectory())) { | |
throw new IllegalArgumentException("Web root '" + webRootPath + "' folder doesn't exist"); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
private void waitForClient() { | |
ServerSocket serverSocket = null; | |
try { | |
serverSocket = new ServerSocket(port, 1, InetAddress.getByName(ServerConstant.HOSTNAME)); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
System.exit(1); | |
} | |
while (serverStart) { | |
Socket socket = null; | |
InputStream inputStream = null; | |
OutputStream outputStream = null; | |
try { | |
socket = serverSocket.accept(); | |
inputStream = socket.getInputStream(); | |
outputStream = socket.getOutputStream(); | |
Request httpRequest = new Request(); | |
String resource = httpRequest.getUri(inputStream); | |
System.out.println("\nRequested resource = " + resource); | |
Response httpResponse = new Response(); | |
httpResponse.processResponse(outputStream, webRootDir, resource); | |
inputStream.close(); | |
outputStream.close(); | |
socket.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
continue; // We want server to keep running... | |
} | |
} | |
} | |
} |
In request object we are going to process the HTTP request coming from client browsers. In Request.java class we are going to process the request and see the URLs browsers are requesting are valid or not.
In request class we are read the request from socket request stream and striping up the requested page name.
In request class we are read the request from socket request stream and striping up the requested page name.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @Author Anindya Bandopadhyay | |
* | |
* SimpleHttpWebServer\andy.blog.web.server.Request.java | |
* | |
* @Created on Sep 14, 2014 6:55:52 PM | |
*/ | |
package andy.blog.web.server; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import andy.blog.constant.ServerConstant; | |
public class Request { | |
public String getUri(InputStream inputStream) { | |
byte buffer[] = new byte[ServerConstant.BUFFER_SIZE]; | |
StringBuffer inputBuffer = new StringBuffer(ServerConstant.BUFFER_SIZE); | |
int byteRequest; | |
try { | |
byteRequest = inputStream.read(buffer); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
byteRequest = -1; | |
} | |
for (int index = 0; index < byteRequest; index++) { | |
inputBuffer.append((char) buffer[index]); | |
} | |
String request = inputBuffer.toString(); | |
System.out.println(request); | |
return parseUri(request); | |
} | |
private String parseUri(String requestString) { | |
// GET /index.html HTTP/1.1 | |
// strip out '/index.html' from request string | |
String[] resource = requestString.split(" "); | |
return resource[1]; | |
} | |
} |
Now let work on HTTP response. In this class we create a response and send it back to requesting browser.
So what we are doing here is we are looking at a specific location where all the web files should be present and if the requested page found then simply write it to socket output stream.
Source Code of SimpleHttpWebServer
So what we are doing here is we are looking at a specific location where all the web files should be present and if the requested page found then simply write it to socket output stream.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @Author Anindya Bandopadhyay | |
* | |
* SimpleHttpWebServer\andy.blog.web.server.Response.java | |
* | |
* @Created on Sep 14, 2014 6:56:11 PM | |
*/ | |
package andy.blog.web.server; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
public class Response { | |
private static final int BUFFER_SIZE = 1024; | |
String success = "HTTP/1.1 200 OK\r\nConnection: close\r\n"+ | |
"Server: Anindya's Server v1\r\nContent-Type: text/html\r\n\r\n"; | |
public void processResponse(OutputStream outputStream, File rootDir, String resource) throws IOException { | |
byte buffer[] = new byte[BUFFER_SIZE]; | |
FileInputStream fileInputStream = null; | |
try { | |
File file = new File(rootDir, resource); | |
System.out.println(file.getAbsolutePath()); | |
if (file.exists()) { | |
outputStream.write(success.getBytes()); | |
fileInputStream = new FileInputStream(file); | |
int character = fileInputStream.read(buffer, 0, BUFFER_SIZE); | |
while (character != -1) { | |
outputStream.write(buffer, 0, character); | |
character = fileInputStream.read(buffer, 0, BUFFER_SIZE); | |
} | |
} else { | |
String notFound = "HTTP/1.1 404 File Not Found\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 23\r\n" | |
+ "\r\n" + "<h1>Page Not Found</h1>"; | |
outputStream.write(notFound.getBytes()); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} finally { | |
if (fileInputStream != null) { | |
fileInputStream.close(); | |
} | |
} | |
} | |
} |
Source Code of SimpleHttpWebServer
![]() |
Welcome to Anindya's Simple Web Server |