From b0e5ac41a3c9e296c54edaf0d5aa69c52ee94023 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Feb 2023 15:02:02 +0100 Subject: Add thrift json/http listener --- src/main/java/org/openslx/imagemaster/App.java | 10 +++ .../imagemaster/thrift/server/HttpListener.java | 95 ++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/main/java/org/openslx/imagemaster/thrift/server/HttpListener.java diff --git a/src/main/java/org/openslx/imagemaster/App.java b/src/main/java/org/openslx/imagemaster/App.java index 12e583d..92f7326 100644 --- a/src/main/java/org/openslx/imagemaster/App.java +++ b/src/main/java/org/openslx/imagemaster/App.java @@ -13,6 +13,7 @@ import org.apache.logging.log4j.core.config.DefaultConfiguration; import org.apache.thrift.transport.TTransportException; import org.openslx.imagemaster.localrpc.NetworkHandler; import org.openslx.imagemaster.thrift.server.BinaryListener; +import org.openslx.imagemaster.thrift.server.HttpListener; import org.openslx.sat.thrift.version.Version; import org.openslx.util.AppUtil; @@ -62,6 +63,15 @@ public class App } } + // Spawn HTTP thrift listener - always do this on localhost, expected to be proxied with SSL + try { + t = new Thread( new HttpListener( "127.0.0.1", 8090 ), "JSON-HTTP" ); + servers.add( t ); + t.start(); + } catch ( Exception e ) { + log.warn( "No JSON-HTTP available", e ); + } + // Run more servers // ... // Wait for all servers to die diff --git a/src/main/java/org/openslx/imagemaster/thrift/server/HttpListener.java b/src/main/java/org/openslx/imagemaster/thrift/server/HttpListener.java new file mode 100644 index 0000000..f130989 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/thrift/server/HttpListener.java @@ -0,0 +1,95 @@ +package org.openslx.imagemaster.thrift.server; + +import java.io.IOException; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.thrift.protocol.TJSONProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TMemoryBuffer; +import org.openslx.bwlp.thrift.iface.MasterServer; +import org.openslx.util.Util; + +import fi.iki.elonen.NanoHTTPD; + +public class HttpListener extends NanoHTTPD +{ + + private static final Logger LOGGER = LogManager.getLogger( HttpListener.class ); + + private final MasterServer.Processor processor = new MasterServer.Processor( + new MasterServerHandler() ); + + public HttpListener( String hostname, int port ) throws IOException + { + super( hostname, port, 64, 16 ); + this.maxRequestSize = 1_000_000; + } + + @Override + public Response serve( IHTTPSession session ) + { + Method method = session.getMethod(); + if ( Method.OPTIONS.equals( method ) ) { + Response response = new Response( Response.Status.NO_CONTENT, "application/json", "" ); + addCorsHeaders( response ); + return response; + } + if ( !Method.PUT.equals( method ) && !Method.POST.equals( method ) ) + return new Response( Response.Status.BAD_REQUEST, "text/plain; charset=UTF-8", "Method not supported" ); + + try { + //Input + String str = session.getHeaders().get( "content-length" ); + int len = 0; + if ( str != null ) { + len = Util.parseInt( str, 0 ); + } + if ( len <= 0 ) { + len = session.getInputStream().available(); + } + if ( len <= 0 ) + return new Response( Response.Status.BAD_REQUEST, "text/plain; charset=UTF-8", "No Content-Length provided" ); + + byte[] buffer = session.getInputStream().readNBytes( len ); + TMemoryBuffer inbuffer = new TMemoryBuffer( buffer.length ); + inbuffer.write( buffer ); + TProtocol inprotocol = new TJSONProtocol( inbuffer ); + + //Output + TMemoryBuffer outbuffer = new TMemoryBuffer( 900 ); + TProtocol outprotocol = new TJSONProtocol( outbuffer ); + + processor.process( inprotocol, outprotocol ); + + buffer = new byte[ outbuffer.length() ]; + outbuffer.readAll( buffer, 0, buffer.length ); + + Response response = new Response( Response.Status.OK, "application/json", buffer ); + addCorsHeaders( response ); + return response; + } catch ( Throwable t ) { + if ( !t.getMessage().contains( "Remote side has closed" ) ) { + LOGGER.warn( "Error handling HTTP thrift", t ); + } + return new Response( Response.Status.INTERNAL_ERROR, "text/plain; charset=UTF-8", t.getMessage() ); + } + + } + + @Override + public void serverStopped() + { + System.exit( 1 ); + } + + private static void addCorsHeaders( Response response ) + { + response.addHeader( "Allow", "OPTIONS, GET, HEAD, POST, PUT" ); + response.addHeader( "Access-Control-Allow-Methods", "*" ); + response.addHeader( "Access-Control-Allow-Origin", "*" ); + response.addHeader( "Access-Control-Allow-Headers", "*, Content-Type" ); + response.addHeader( "Access-Control-Max-Age", "86400" ); + } + +} -- cgit v1.2.3-55-g7522