Skip to content

Instantly share code, notes, and snippets.

@mapio
Last active May 11, 2016 21:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mapio/d36bfdbee57f653832f9 to your computer and use it in GitHub Desktop.
Save mapio/d36bfdbee57f653832f9 to your computer and use it in GitHub Desktop.
Putting together ElementalHttpServer and LifecycleWebServer
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import org.apache.http.ConnectionClosedException;
import org.apache.http.HttpConnectionFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpServerConnection;
import org.apache.http.HttpStatus;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultBHttpServerConnection;
import org.apache.http.impl.DefaultBHttpServerConnectionFactory;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.HttpProcessorBuilder;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.http.protocol.UriHttpRequestHandlerMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AnHttpServer {
private static final Logger LOGGER = LoggerFactory.getLogger( WarcHttpServer.class );
public static void main( String[] args ) throws Exception {
if ( args.length < 1 ) {
System.err.println( "Please specify document root directory" );
System.exit( 1 );
}
String docRoot = args[ 0 ];
int port = 8000;
if ( args.length >= 2 ) {
port = Integer.parseInt( args[ 1 ] );
}
HttpProcessor processor =
HttpProcessorBuilder.create()
.add( new ResponseDate() )
.add( new ResponseServer( "Test/1.1" ) )
.add( new ResponseContent() )
.add( new ResponseConnControl() ).build();
UriHttpRequestHandlerMapper handlerMapper = new UriHttpRequestHandlerMapper();
handlerMapper.register( "*", new HttpFileHandler( docRoot ) );
HttpService httpService = new HttpService( processor, handlerMapper );
RequestListener rl = new RequestListener( port, httpService );
LOGGER.info( "serving on port " + port + ", document root " + docRoot );
rl.start();
}
static class RequestListener {
private final ExecutorService exec = Executors.newCachedThreadPool();
private final HttpConnectionFactory<DefaultBHttpServerConnection> connFactory;
private final ServerSocket serversocket;
private final HttpService httpService;
public RequestListener( final int port, final HttpService httpService ) throws IOException {
this.connFactory = DefaultBHttpServerConnectionFactory.INSTANCE;
this.serversocket = new ServerSocket( port );
this.httpService = httpService;
}
public void start() throws IOException {
while ( !exec.isShutdown() ) {
try {
final Socket socket = serversocket.accept();
exec.execute( new Runnable() {
public void run() {
try {
LOGGER.info( "incoming connection from " + socket.getInetAddress() );
HttpServerConnection conn = connFactory.createConnection( socket );
HttpContext context = new BasicHttpContext( null );
try {
while ( !exec.isShutdown() && conn.isOpen() )
httpService.handleRequest( conn, context );
} catch ( ConnectionClosedException e ) {
LOGGER.info( "client closed connection" );
} catch ( IOException e ) {
LOGGER.error( "I/O error", e );
} catch ( HttpException e ) {
LOGGER.error( "unrecoverable HTTP protocol violation", e );
} finally {
try { conn.shutdown(); } catch ( IOException ignore ) {}
}
} catch ( IOException e ) {
LOGGER.error( "exception while handling request", e );
}
}
} );
} catch ( RejectedExecutionException e ) {
if ( !exec.isShutdown() ) LOGGER.error( "task submission rejected", e );
}
}
}
}
static class HttpFileHandler implements HttpRequestHandler {
private final String docRoot;
public HttpFileHandler( final String docRoot ) {
super();
this.docRoot = docRoot;
}
public void handle( final HttpRequest request, final HttpResponse response, final HttpContext context ) throws HttpException, IOException {
String method = request.getRequestLine().getMethod().toUpperCase( Locale.ENGLISH );
if ( !method.equals( "GET" ) && !method.equals( "HEAD" ) && !method.equals( "POST" ) ) {
throw new MethodNotSupportedException( method + " method not supported" );
}
String target = request.getRequestLine().getUri();
if ( request instanceof HttpEntityEnclosingRequest ) {
HttpEntity entity = ( (HttpEntityEnclosingRequest)request ).getEntity();
/*
byte[] entityContent = EntityUtils.toByteArray( entity );
System.out.println( "Incoming entity content (bytes): " + entityContent.length );
*/
List<NameValuePair> kv = URLEncodedUtils.parse( entity );
LOGGER.info( kv.toString() );
}
final File file = new File( this.docRoot, URLDecoder.decode( target, "UTF-8" ) );
if ( !file.exists() ) {
response.setStatusCode( HttpStatus.SC_NOT_FOUND );
StringEntity entity = new StringEntity( "<html><body><h1>File" + file.getPath() + " not found</h1></body></html>", ContentType.create( "text/html", "UTF-8" ) );
response.setEntity( entity );
LOGGER.warn( "file " + file.getPath() + " not found" );
} else if ( !file.canRead() || file.isDirectory() ) {
response.setStatusCode( HttpStatus.SC_FORBIDDEN );
StringEntity entity = new StringEntity( "<html><body><h1>Access denied</h1></body></html>", ContentType.create( "text/html", "UTF-8" ) );
response.setEntity( entity );
LOGGER.warn( "cannot read file " + file.getPath() );
} else {
response.setStatusCode( HttpStatus.SC_OK );
FileEntity body = new FileEntity( file, ContentType.create( "text/html", (Charset)null ) );
response.setEntity( body );
LOGGER.info( "serving file " + file.getPath() );
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment