view src/luan/webserver/Connection.java @ 1207:59289af20d9a

better webserver logging
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 07 Mar 2018 16:48:32 -0700
parents 9d3835e88204
children 85aa7961239a
line wrap: on
line source

package luan.webserver;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.Socket;
import org.slf4j.Logger;
import org.slf4j.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 ) {
						if( "application/x-www-form-urlencoded".equals(contentType) ) {
							parser.parseUrlencoded();
						} else if( contentType.startsWith("multipart/form-data;") ) {
							parser.parseMultipart();
						} else {
							logger.warn("unknown request content-type: "+contentType);
						}
					}
				}
				response = server.handler.handle(request);
			} catch(ParseException e) {
				logger.error("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);
		}
	}

}