Created
December 8, 2017 19:53
-
-
Save skanga/d5737a4339fea498b8e67b6fd3842820 to your computer and use it in GitHub Desktop.
Multi threaded HTTP server in Java that will only serve 1 single file for ANY http request
This file contains hidden or 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
import java.io.BufferedInputStream; | |
import java.io.BufferedOutputStream; | |
import java.io.File; | |
import java.io.InputStream; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.net.ServerSocket; | |
import java.net.Socket; | |
import java.net.URLConnection; | |
import java.nio.charset.Charset; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
import java.nio.file.Paths; | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
// Serve only a single specific file for ANY http request | |
public class SingleFileHTTPServer | |
{ | |
private static final String serverName = "SingleFileHTTPServer"; | |
private static final String serverVer = "1.0"; | |
private static final Logger logger = Logger.getLogger (serverName); | |
private static final int numThreads = 2; | |
private final byte[] httpHeader; | |
private final int httpPort; | |
private final Path filePath; | |
public SingleFileHTTPServer (String fileName, int httpPort) | |
{ | |
String mimeType = URLConnection.getFileNameMap ().getContentTypeFor (fileName); | |
filePath = Paths.get (fileName); | |
this.httpPort = httpPort; | |
String header = "HTTP/1.0 200 OK\r\n" | |
+ "Server: " + serverName + " " + serverVer + "\r\n" | |
+ "Content-length: " + new File (fileName).length () + "\r\n" | |
+ "Content-type: " + mimeType + "\r\n\r\n"; | |
this.httpHeader = header.getBytes (Charset.forName ("US-ASCII")); | |
} | |
public void start () | |
{ | |
ExecutorService threadPool = Executors.newFixedThreadPool (numThreads); | |
try (ServerSocket serverSocket = new ServerSocket (this.httpPort)) | |
{ | |
logger.info ("Accepting connections on port " + serverSocket.getLocalPort ()); | |
while (true) | |
{ | |
try | |
{ | |
Socket clientSocket = serverSocket.accept (); | |
threadPool.submit (new HTTPHandler (clientSocket)); | |
} | |
catch (IOException ex) | |
{ | |
logger.log (Level.WARNING, "Exception accepting connection", ex); | |
} | |
catch (RuntimeException ex) | |
{ | |
logger.log (Level.SEVERE, "Unexpected error", ex); | |
} | |
} | |
} | |
catch (IOException ex) | |
{ | |
logger.log (Level.SEVERE, "Could not start server", ex); | |
} | |
} | |
private class HTTPHandler implements Callable <Void> | |
{ | |
private final Socket clientSocket; | |
HTTPHandler (Socket clientSocket) | |
{ | |
this.clientSocket = clientSocket; | |
} | |
@Override | |
public Void call () throws IOException | |
{ | |
try | |
{ | |
OutputStream outStream = new BufferedOutputStream (clientSocket.getOutputStream ()); | |
InputStream inStream = new BufferedInputStream (clientSocket.getInputStream ()); | |
// read the first line only; that's all we need | |
StringBuilder httpRequest = new StringBuilder (80); | |
while (true) | |
{ | |
int currChar = inStream.read (); | |
if (currChar == '\r' || currChar == '\n' || currChar == -1) break; | |
httpRequest.append ((char) currChar); | |
} | |
// If this is HTTP/1.0 or later send a MIME header | |
if (httpRequest.toString ().indexOf ("HTTP/") != -1) | |
{ | |
outStream.write (httpHeader); | |
} | |
Files.copy (filePath, outStream); | |
outStream.flush (); | |
} | |
catch (IOException ex) | |
{ | |
logger.log (Level.WARNING, "Error writing to client", ex); | |
} | |
finally | |
{ | |
clientSocket.close (); | |
} | |
return null; | |
} | |
} | |
public static void main (String[] args) | |
{ | |
// set the port to listen on | |
int port; | |
try | |
{ | |
port = Integer.parseInt (args[1]); | |
if (port < 1 || port > 65535) port = 80; | |
} | |
catch (RuntimeException ex) | |
{ | |
port = 80; | |
} | |
try | |
{ | |
SingleFileHTTPServer server = new SingleFileHTTPServer (args[0], port); | |
server.start (); | |
} | |
catch (ArrayIndexOutOfBoundsException ex) | |
{ | |
System.out.println ("Usage: java SingleFileHTTPServer filename port"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment