diff src/luan/lib/webserver/Connection.java @ 1347:643cf1c37723

move webserver to lib and bug fixes
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 25 Feb 2019 13:02:33 -0700
parents src/luan/webserver/Connection.java@8b61c8c4e07a
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/lib/webserver/Connection.java	Mon Feb 25 13:02:33 2019 -0700
@@ -0,0 +1,134 @@
+package luan.lib.webserver;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.net.Socket;
+import luan.lib.logging.Logger;
+import luan.lib.logging.LoggerFactory;
+import luan.lib.parser.ParseException;
+
+
+final class Connection {
+	private static final Logger logger = LoggerFactory.getLogger(Connection.class);
+
+	static void handle(Server server,Socket socket) {
+		new Connection(server,socket).handle();
+	}
+
+	private final Server server;
+	private final Socket socket;
+
+	private Connection(Server server,Socket socket) {
+		this.server = server;
+		this.socket = socket;
+	}
+
+	private void handle() {
+		try {
+			Request request = new Request();
+			Response response;
+			try {
+				{
+					InputStream in = socket.getInputStream();
+					byte[] a = new byte[8192];
+					int endOfHeader;
+					int size = 0;
+					int left = a.length;
+					outer: while(true) {
+						int n = in.read(a,size,left);
+						if( n == -1 ) {
+							if( size == 0 ) {
+								socket.close();
+								return;
+							}
+							throw new IOException("unexpected end of input at "+size);
+						}
+						size += n;
+						for( int i=0; i<=size-4; i++ ) {
+							if( a[i]=='\r' && a[i+1]=='\n' && a[i+2]=='\r' && a[i+3]=='\n' ) {
+								endOfHeader = i + 4;
+								break outer;
+							}
+						}
+						left -= n;
+						if( left == 0 ) {
+							byte[] a2 = new byte[2*a.length];
+							System.arraycopy(a,0,a2,0,size);
+							a = a2;
+							left = a.length - size;
+						}
+					}
+					String rawHead = new String(a,0,endOfHeader);
+					//System.out.println(rawHead);
+					request.rawHead = rawHead;
+					RequestParser parser = new RequestParser(request);
+					parser.parseHead();
+		
+					String lenStr = (String)request.headers.get("content-length");
+					if( lenStr != null ) {
+						int len = Integer.parseInt(lenStr);
+						byte[] body = new byte[len];
+						size -= endOfHeader;
+						System.arraycopy(a,endOfHeader,body,0,size);
+						while( size < len ) {
+							int n = in.read(body,size,len-size);
+							if( n == -1 ) {
+								throw new IOException("unexpected end of input at "+size);
+							}
+							size += n;
+						}
+						request.body = body;
+						//System.out.println(new String(request.body));
+					}
+	
+					String contentType = (String)request.headers.get("content-type");
+					if( contentType != null ) {
+						contentType = contentType.toLowerCase();
+						if( "application/x-www-form-urlencoded".equals(contentType) ) {
+							parser.parseUrlencoded(null);
+						} else if( "application/x-www-form-urlencoded; charset=utf-8".equals(contentType) ) {
+							parser.parseUrlencoded("utf-8");
+						} else if( contentType.startsWith("multipart/form-data;") ) {
+							parser.parseMultipart();
+						} else if( contentType.equals("application/json; charset=utf-8") ) {
+							parser.parseJson();
+						} else {
+							logger.info("unknown request content-type: "+contentType);
+						}
+					}
+
+					String scheme = (String)request.headers.get("x-forwarded-proto");
+					if( scheme != null )
+						request.scheme = scheme;
+				}
+				response = server.handler.handle(request);
+			} catch(ParseException e) {
+				logger.warn("parse error\n"+request.rawHead.trim()+"\n",e);
+				response = Response.errorResponse(Status.BAD_REQUEST,e.toString());
+			}
+			response.headers.put("connection","close");
+			response.headers.put("content-length",Long.toString(response.body.length));
+			byte[] header = response.toHeaderString().getBytes();
+	
+			OutputStream out = socket.getOutputStream();
+			out.write(header);
+			copyAll(response.body.content,out);
+			out.close();
+			socket.close();
+		} catch(IOException e) {
+			logger.info("",e);
+		}
+	}
+
+	private static void copyAll(InputStream in,OutputStream out)
+		throws IOException
+	{
+		byte[] a = new byte[8192];
+		int n;
+		while( (n=in.read(a)) != -1 ) {
+			out.write(a,0,n);
+		}
+	}
+
+}