view src/luan/webserver/Connection.java @ 1162:e2d2354807f3

minor
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 06 Feb 2018 21:25:55 -0700
parents 4beabb087be6
children bd0420fb3dd0
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();
			{
				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( request.body == null ) {
						logger.error("body is null");
					} else {
						if( "application/x-www-form-urlencoded".equals(contentType) ) {
							parser.parseUrlencoded();
						} else if( contentType.startsWith("multipart/form-data;") ) {
							parser.parseMultipart();
						} else {
							logger.error("unknown content type: "+contentType);
						}
					}
				}
			}

			Response response = server.handler.handle(request);
			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);
		} catch(ParseException e) {
			logger.warn("",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);
		}
	}

}