/
akolonin
/
aigents-java
Обзор
Документация
Войти
/
akolonin
/
aigents-java
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/main/java/net/webstructor/cat/HttpServer.java
272 строки
9 KB
Anton Kolonin
Archiver dated-based clearing plus optimized String building for Android
05 янв 2019, 18:01
05 янв 2019, 18:01
6abe581
Код
Авторство
О чём код?
/* * MIT License * * Copyright (c) 2005-2018 by Anton Kolonin, Aigents * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package net.webstructor.cat; import java.net.*; import java.io.*; import net.webstructor.agent.Farm; import net.webstructor.main.Logger; /** * This is simple and rough implementatoion of single threaded, single-user HTTP server for IDD application<p> * This is based on: <p> * http://www.oreilly.com/catalog/javanp2/chapter/ch11.html <p> * http://www.oreilly.com/catalog/javanp2/chapter/ch11.html#53648 <p> * The alternate and better solution may be based on: <p> * http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/package-summary.html <p> * http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/index.html <p> * http://developers.sun.com/web/swdp/r1/rest-impl/samples/SimpleAtomServer/README.html <p> * @author Anton * @since 20070515 */ public class HttpServer extends Thread { static String m_lineBr = "<br>"; private int port = 80; private boolean bDone = false; //private CommandHandler handler; //public HttpServer(int port,CommandHandler handler) throws UnsupportedEncodingException { // this.port = port; // this.handler = handler; //} public HttpServer(int port) throws UnsupportedEncodingException { this.port = port; } byte[] getHeader(int contentLength) throws Exception { String header = "HTTP/1.0 200 OK\r\n" + "Server: WebCat 1.0\r\n" + "Content-length: " + contentLength + "\r\n" + "Content-type: " + "text/html; charset=utf-8" + "\r\n\r\n"; //+ "Content-type: " + "text/plain" + "\r\n\r\n"; return header.getBytes("ASCII"); } public static String decode(String request) throws Exception { // this should convert "+" to " " (which may not be good) but it throws exceptions // return URLDecoder.decode(request,""); /* // this converts "%20" to " " (which is good) but lacks converting the rest StringBuilder sb = new StringBuilder(); int start=0; for (;;) { int next = request.indexOf("%20",start); if (next==-1) { sb.append(request.substring(start)); break; } else { if (next>0) sb.append(request.substring(start,next)); sb.append(' '); start = next+3; } } return sb.toString(); */ StringBuilder sb = new StringBuilder(); int start=0; for (;;) { int next = request.indexOf("%",start); if (next==-1) { sb.append(request.substring(start)); break; } else { if (next>0) sb.append(request.substring(start,next)); try { String code = request.substring(next+1,next+3); sb.append((char)Integer.parseInt(code,16)); start = next+3; } catch (Exception e) { sb.append(request.substring(next,next+1)); start = next+1; } } } return sb.toString(); } protected String handle(String request) throws Exception { int q = request.indexOf('?'); int e = request.indexOf(' ',q+1); if (q==-1 || e==-1) return "HTTP request is wrong: "+request; String cmd = request.substring(q+1,e).trim(); StringBuilder result = new StringBuilder(); if (cmd.equalsIgnoreCase("stop")) { bDone = true; return "Shutdown requested"; } else //synchronized (handler) { //http://localhost:88/?textcat%20299%20cannula //cmd = decode(cmd); //result = handler.handle( cmd ); //cmd = decode(cmd); cmd = URLDecoder.decode(cmd,"UTF-8"); CommandHandler ch = new CommandHandler(cmd,m_lineBr,";",","); ch.run(); //result.append("<HTML><SCRIPT>function doLoad() {alert('top='+top+' accept='+top.accept); if (top && top.accept) {alert('top.accept='+top.accept); top.accept(document.body.innerHTML);}}"); result.append("<HTML><SCRIPT>function doLoad() {if (top) {top.postMessage(document.body.innerHTML,'*');}}"); //result.append("<HTML><SCRIPT>function doLoad() {if (top && top.accept) {top.accept(document.body.innerHTML);}}"); result.append("</SCRIPT><BODY onload=\"doLoad()\">"); result.append(ch.getOutput()); result.append("</BODY></HTML>"); //result = ch.getOutput(); } return result.toString(); } //Should be large enough to consume any input in URL-encoded form private static final int MAX_INPUT = 1024; public void run( ) { ServerSocket server = null; try { Logger logger = Logger.getLogger(); server = new ServerSocket(this.port); System.out.println("Started at " + server.getLocalPort()); logger.log("Started at " + server.getLocalPort(),"startup");//TODO rework while (!bDone) { Socket connection = null; try { connection = server.accept(); connection.setSoTimeout(2000);//prevent silent read access from port scanners logger.log(connection.getRemoteSocketAddress().toString(),"connection");//TODO rework OutputStream out = new BufferedOutputStream( connection.getOutputStream( ) ); InputStream in = new BufferedInputStream( connection.getInputStream( ) ); // read the first line only; that's all we need StringBuilder request = new StringBuilder(MAX_INPUT); int count = 0; while (true) { int c = in.read( ); if (c == '\r' || c == '\n' || c == -1) break; request.append((char) c); //TODO: If this is HTTP 1.0 or later send a MIME header if (++count > MAX_INPUT) { logger.log(StringUtil.first(request.toString(),MAX_INPUT),"suspect"); //bDone = true;//TODO:indicate error and ignore? break; } } String requestString = request.toString(); logger.log(StringUtil.first(requestString,MAX_INPUT),"request");//TODO rework String result = handle(requestString); logger.log(StringUtil.first(result,MAX_INPUT),"response");//TODO rework byte[] bytes = result.getBytes("UTF-8"); if (request.toString( ).indexOf("HTTP/") != -1) { out.write(this.getHeader(bytes.length)); } out.write(bytes); out.flush(); } // end try catch (Exception e) { logger.log("Failed: " + e.toString(),"failure");//TODO rework //bDone = true; } finally { if (connection != null) connection.close( ); } } // end while } // end try catch (IOException e) { System.err.println("Could not start server. Port Occupied"); } if (server!=null) System.out.println("Releasing port "+ server.getLocalPort( )); } // end run public static void main(String[] args) { if (args[0] != null) CmdLine.setCurrentDirectory(args[0]); // initialize the server explicitly CommandHandler.getServer(System.getProperty("user.dir")); try { // set the port to listen on int port; try { port = Integer.parseInt(args[1]); if (port < 1 || port > 65535) port = 80; } catch (Exception e) { port = 80; } System.out.println("Starting at port "+port+", loading asset from "+args[0]); Thread t = new HttpServer(port); t.start( ); //TODO:remove hacky load of Aigents into this JVM if (args.length > 2 && args[2].equalsIgnoreCase("aigents")) new Farm(args,true,false,true,true,true,true,10).start();//all services, but console } catch (ArrayIndexOutOfBoundsException e) { System.out.println( "Usage: java SingleFileHttpServer filename port encoding"); } catch (Exception e) { System.err.println(e); } } }