package org.openslx.bwlp.sat.thrift; import java.io.IOException; import java.util.Arrays; import java.util.concurrent.ExecutorService; 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.SatelliteServer; import org.openslx.util.Util; import fi.iki.elonen.NanoHTTPD; public class JsonHttpListener extends NanoHTTPD { private static final Logger LOGGER = LogManager.getLogger(JsonHttpListener.class); private final SatelliteServer.Processor processor = new SatelliteServer.Processor( new ServerHandler()); public JsonHttpListener(int port, ExecutorService es) throws IOException { super("127.0.0.1", port, es); this.maxRequestSize = 1_000_000; } @Override public Response serve(IHTTPSession session) { Response res = serveInternal(session); if (res != null) { addCorsHeaders(res); } return res; } private Response serveInternal(IHTTPSession session) { Method method = session.getMethod(); if (Method.OPTIONS.equals(method)) return new Response(Response.Status.NO_CONTENT, "application/json", ""); 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 = new byte[len]; int pos = 0; while (pos < len) { int ret = session.getInputStream().read(buffer, pos, len - pos); if (ret <= 0) return new Response(Response.Status.BAD_REQUEST, "text/plain; charset=UTF-8", "Request content truncated (" + pos + "/" + len + ")"); pos += ret; } 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 = Arrays.copyOf(outbuffer.getArray(), outbuffer.length()); return new Response(Response.Status.OK, "application/json", buffer); } 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"); } }