comparison 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
comparison
equal deleted inserted replaced
1346:efd1c6380f2c 1347:643cf1c37723
1 package luan.lib.webserver;
2
3 import java.io.InputStream;
4 import java.io.OutputStream;
5 import java.io.IOException;
6 import java.net.Socket;
7 import luan.lib.logging.Logger;
8 import luan.lib.logging.LoggerFactory;
9 import luan.lib.parser.ParseException;
10
11
12 final class Connection {
13 private static final Logger logger = LoggerFactory.getLogger(Connection.class);
14
15 static void handle(Server server,Socket socket) {
16 new Connection(server,socket).handle();
17 }
18
19 private final Server server;
20 private final Socket socket;
21
22 private Connection(Server server,Socket socket) {
23 this.server = server;
24 this.socket = socket;
25 }
26
27 private void handle() {
28 try {
29 Request request = new Request();
30 Response response;
31 try {
32 {
33 InputStream in = socket.getInputStream();
34 byte[] a = new byte[8192];
35 int endOfHeader;
36 int size = 0;
37 int left = a.length;
38 outer: while(true) {
39 int n = in.read(a,size,left);
40 if( n == -1 ) {
41 if( size == 0 ) {
42 socket.close();
43 return;
44 }
45 throw new IOException("unexpected end of input at "+size);
46 }
47 size += n;
48 for( int i=0; i<=size-4; i++ ) {
49 if( a[i]=='\r' && a[i+1]=='\n' && a[i+2]=='\r' && a[i+3]=='\n' ) {
50 endOfHeader = i + 4;
51 break outer;
52 }
53 }
54 left -= n;
55 if( left == 0 ) {
56 byte[] a2 = new byte[2*a.length];
57 System.arraycopy(a,0,a2,0,size);
58 a = a2;
59 left = a.length - size;
60 }
61 }
62 String rawHead = new String(a,0,endOfHeader);
63 //System.out.println(rawHead);
64 request.rawHead = rawHead;
65 RequestParser parser = new RequestParser(request);
66 parser.parseHead();
67
68 String lenStr = (String)request.headers.get("content-length");
69 if( lenStr != null ) {
70 int len = Integer.parseInt(lenStr);
71 byte[] body = new byte[len];
72 size -= endOfHeader;
73 System.arraycopy(a,endOfHeader,body,0,size);
74 while( size < len ) {
75 int n = in.read(body,size,len-size);
76 if( n == -1 ) {
77 throw new IOException("unexpected end of input at "+size);
78 }
79 size += n;
80 }
81 request.body = body;
82 //System.out.println(new String(request.body));
83 }
84
85 String contentType = (String)request.headers.get("content-type");
86 if( contentType != null ) {
87 contentType = contentType.toLowerCase();
88 if( "application/x-www-form-urlencoded".equals(contentType) ) {
89 parser.parseUrlencoded(null);
90 } else if( "application/x-www-form-urlencoded; charset=utf-8".equals(contentType) ) {
91 parser.parseUrlencoded("utf-8");
92 } else if( contentType.startsWith("multipart/form-data;") ) {
93 parser.parseMultipart();
94 } else if( contentType.equals("application/json; charset=utf-8") ) {
95 parser.parseJson();
96 } else {
97 logger.info("unknown request content-type: "+contentType);
98 }
99 }
100
101 String scheme = (String)request.headers.get("x-forwarded-proto");
102 if( scheme != null )
103 request.scheme = scheme;
104 }
105 response = server.handler.handle(request);
106 } catch(ParseException e) {
107 logger.warn("parse error\n"+request.rawHead.trim()+"\n",e);
108 response = Response.errorResponse(Status.BAD_REQUEST,e.toString());
109 }
110 response.headers.put("connection","close");
111 response.headers.put("content-length",Long.toString(response.body.length));
112 byte[] header = response.toHeaderString().getBytes();
113
114 OutputStream out = socket.getOutputStream();
115 out.write(header);
116 copyAll(response.body.content,out);
117 out.close();
118 socket.close();
119 } catch(IOException e) {
120 logger.info("",e);
121 }
122 }
123
124 private static void copyAll(InputStream in,OutputStream out)
125 throws IOException
126 {
127 byte[] a = new byte[8192];
128 int n;
129 while( (n=in.read(a)) != -1 ) {
130 out.write(a,0,n);
131 }
132 }
133
134 }