Mercurial Hosting > luan
annotate src/goodjava/webserver/Connection.java @ 1794:04ac5f2771c8
minor
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sat, 30 Dec 2023 18:41:35 -0700 |
parents | 6c01d54edcac |
children | 32e77b071e09 |
rev | line source |
---|---|
1402
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1347
diff
changeset
|
1 package goodjava.webserver; |
1137 | 2 |
3 import java.io.InputStream; | |
4 import java.io.OutputStream; | |
5 import java.io.IOException; | |
6 import java.net.Socket; | |
1402
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1347
diff
changeset
|
7 import goodjava.logging.Logger; |
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1347
diff
changeset
|
8 import goodjava.logging.LoggerFactory; |
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1347
diff
changeset
|
9 import goodjava.parser.ParseException; |
1493 | 10 import goodjava.io.IoUtils; |
1137 | 11 |
12 | |
13 final class Connection { | |
14 private static final Logger logger = LoggerFactory.getLogger(Connection.class); | |
15 | |
1142
0f59eab45f3d
webserver - threading
Franklin Schmidt <fschmidt@gmail.com>
parents:
1138
diff
changeset
|
16 static void handle(Server server,Socket socket) { |
0f59eab45f3d
webserver - threading
Franklin Schmidt <fschmidt@gmail.com>
parents:
1138
diff
changeset
|
17 new Connection(server,socket).handle(); |
0f59eab45f3d
webserver - threading
Franklin Schmidt <fschmidt@gmail.com>
parents:
1138
diff
changeset
|
18 } |
0f59eab45f3d
webserver - threading
Franklin Schmidt <fschmidt@gmail.com>
parents:
1138
diff
changeset
|
19 |
1137 | 20 private final Server server; |
21 private final Socket socket; | |
22 | |
1142
0f59eab45f3d
webserver - threading
Franklin Schmidt <fschmidt@gmail.com>
parents:
1138
diff
changeset
|
23 private Connection(Server server,Socket socket) { |
1137 | 24 this.server = server; |
25 this.socket = socket; | |
26 } | |
27 | |
28 private void handle() { | |
1736
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
29 String rawHead = ""; |
1137 | 30 try { |
1144
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
31 Request request = new Request(); |
1194
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
32 Response response; |
1513 | 33 String contentType = null; |
1194
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
34 try { |
1738 | 35 InputStream in = socket.getInputStream(); |
36 byte[] a = new byte[8192]; | |
37 int endOfHeader; | |
38 int size = 0; | |
39 int left = a.length; | |
40 outer: while(true) { | |
41 int n = in.read(a,size,left); | |
42 if( n == -1 ) { | |
43 if( size == 0 ) { | |
44 socket.close(); | |
45 return; | |
46 } | |
47 throw new IOException("unexpected end of input at "+size); | |
48 } | |
49 size += n; | |
50 for( int i=0; i<=size-4; i++ ) { | |
51 if( a[i]=='\r' && a[i+1]=='\n' && a[i+2]=='\r' && a[i+3]=='\n' ) { | |
52 endOfHeader = i + 4; | |
53 break outer; | |
54 } | |
55 } | |
56 left -= n; | |
57 if( left == 0 ) { | |
58 byte[] a2 = new byte[2*a.length]; | |
59 System.arraycopy(a,0,a2,0,size); | |
60 a = a2; | |
61 left = a.length - size; | |
62 } | |
63 } | |
64 rawHead = new String(a,0,endOfHeader); | |
65 //System.out.println(rawHead); | |
66 request.rawHead = rawHead; | |
67 RequestParser parser = new RequestParser(request); | |
68 parser.parseHead(); | |
69 | |
70 String lenStr = (String)request.headers.get("content-length"); | |
71 if( lenStr != null ) { | |
72 int len = Integer.parseInt(lenStr); | |
73 byte[] body = new byte[len]; | |
74 size -= endOfHeader; | |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
75 try { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
76 System.arraycopy(a,endOfHeader,body,0,size); |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
77 } catch(ArrayIndexOutOfBoundsException e) { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
78 throw new WrappedRuntimeException(e); |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
79 } |
1738 | 80 while( size < len ) { |
81 int n = in.read(body,size,len-size); | |
1144
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
82 if( n == -1 ) { |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
83 throw new IOException("unexpected end of input at "+size); |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
84 } |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
85 size += n; |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
86 } |
1738 | 87 request.body = body; |
88 //System.out.println(new String(request.body)); | |
89 } | |
90 | |
91 contentType = (String)request.headers.get("content-type"); | |
92 if( contentType != null ) { | |
93 contentType = contentType.toLowerCase(); | |
94 if( contentType.equals("application/x-www-form-urlencoded") ) { | |
95 parser.parseUrlencoded(null); | |
96 } else if( contentType.equals("application/x-www-form-urlencoded; charset=utf-8") ) { | |
97 parser.parseUrlencoded("utf-8"); | |
98 } else if( contentType.startsWith("multipart/form-data;") ) { | |
99 parser.parseMultipart(); | |
100 } else if( contentType.equals("application/json") ) { | |
101 parser.parseJson(null); | |
102 } else if( contentType.equals("application/json; charset=utf-8") ) { | |
103 parser.parseJson("utf-8"); | |
104 } else { | |
105 logger.info("unknown request content-type: "+contentType); | |
1194
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
106 } |
1738 | 107 } |
108 | |
109 String scheme = (String)request.headers.get("x-forwarded-proto"); | |
110 if( scheme != null ) | |
111 request.scheme = scheme; | |
1237 | 112 |
1738 | 113 if( "text/event-stream".equals(request.headers.get("accept")) ) { |
114 ServerSentEvents.add(socket,request); | |
115 return; | |
1137 | 116 } |
1738 | 117 |
1194
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
118 response = server.handler.handle(request); |
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
119 } catch(ParseException e) { |
1770 | 120 logger.info("parse error\n"+rawHead.trim()+"\n",e); |
1513 | 121 String msg = e.toString(); |
122 if( contentType != null ) | |
123 msg = "invalid content for content-type " + contentType + "\n" + msg; | |
124 response = Response.errorResponse(Status.BAD_REQUEST,msg); | |
1137 | 125 } |
1607 | 126 response.headers.put("Connection","close"); |
127 response.headers.put("Content-Length",Long.toString(response.body.length)); | |
1137 | 128 byte[] header = response.toHeaderString().getBytes(); |
129 | |
130 OutputStream out = socket.getOutputStream(); | |
131 out.write(header); | |
1493 | 132 IoUtils.copyAll(response.body.content,out); |
1137 | 133 out.close(); |
134 socket.close(); | |
135 } catch(IOException e) { | |
1736
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
136 logger.info(rawHead.trim()+"\n",e); |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
137 } catch(WrappedRuntimeException wrapped) { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
138 RuntimeException e = (RuntimeException)wrapped.getCause(); |
1752 | 139 logger.warn(rawHead.trim()+"\n",e); |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
140 throw e; |
1736
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
141 } catch(RuntimeException e) { |
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
142 logger.error(rawHead.trim()+"\n",e); |
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
143 throw e; |
1137 | 144 } |
145 } | |
146 | |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
147 private static final class WrappedRuntimeException extends Exception { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
148 WrappedRuntimeException(RuntimeException e) { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
149 super(e); |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
150 } |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
151 } |
1137 | 152 } |