Mercurial Hosting > luan
annotate src/goodjava/webserver/Connection.java @ 1804:b4328322d2be
minor
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 07 May 2024 22:08:37 -0600 |
parents | 32e77b071e09 |
children |
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 ) { | |
1801 | 72 int len; |
73 try { | |
74 len = Integer.parseInt(lenStr); | |
75 } catch(NumberFormatException e) { | |
76 throw new WrappedRuntimeException(e); | |
77 } | |
1738 | 78 byte[] body = new byte[len]; |
79 size -= endOfHeader; | |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
80 try { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
81 System.arraycopy(a,endOfHeader,body,0,size); |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
82 } catch(ArrayIndexOutOfBoundsException e) { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
83 throw new WrappedRuntimeException(e); |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
84 } |
1738 | 85 while( size < len ) { |
86 int n = in.read(body,size,len-size); | |
1144
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
87 if( n == -1 ) { |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
88 throw new IOException("unexpected end of input at "+size); |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
89 } |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
90 size += n; |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1142
diff
changeset
|
91 } |
1738 | 92 request.body = body; |
93 //System.out.println(new String(request.body)); | |
94 } | |
95 | |
96 contentType = (String)request.headers.get("content-type"); | |
97 if( contentType != null ) { | |
98 contentType = contentType.toLowerCase(); | |
99 if( contentType.equals("application/x-www-form-urlencoded") ) { | |
100 parser.parseUrlencoded(null); | |
101 } else if( contentType.equals("application/x-www-form-urlencoded; charset=utf-8") ) { | |
102 parser.parseUrlencoded("utf-8"); | |
103 } else if( contentType.startsWith("multipart/form-data;") ) { | |
104 parser.parseMultipart(); | |
105 } else if( contentType.equals("application/json") ) { | |
106 parser.parseJson(null); | |
107 } else if( contentType.equals("application/json; charset=utf-8") ) { | |
108 parser.parseJson("utf-8"); | |
109 } else { | |
110 logger.info("unknown request content-type: "+contentType); | |
1194
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
111 } |
1738 | 112 } |
113 | |
114 String scheme = (String)request.headers.get("x-forwarded-proto"); | |
115 if( scheme != null ) | |
116 request.scheme = scheme; | |
1237 | 117 |
1738 | 118 if( "text/event-stream".equals(request.headers.get("accept")) ) { |
119 ServerSentEvents.add(socket,request); | |
120 return; | |
1137 | 121 } |
1738 | 122 |
1194
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
123 response = server.handler.handle(request); |
bd0420fb3dd0
handle ParseException in webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
1162
diff
changeset
|
124 } catch(ParseException e) { |
1770 | 125 logger.info("parse error\n"+rawHead.trim()+"\n",e); |
1513 | 126 String msg = e.toString(); |
127 if( contentType != null ) | |
128 msg = "invalid content for content-type " + contentType + "\n" + msg; | |
129 response = Response.errorResponse(Status.BAD_REQUEST,msg); | |
1137 | 130 } |
1607 | 131 response.headers.put("Connection","close"); |
132 response.headers.put("Content-Length",Long.toString(response.body.length)); | |
1137 | 133 byte[] header = response.toHeaderString().getBytes(); |
134 | |
135 OutputStream out = socket.getOutputStream(); | |
136 out.write(header); | |
1493 | 137 IoUtils.copyAll(response.body.content,out); |
1137 | 138 out.close(); |
139 socket.close(); | |
140 } catch(IOException e) { | |
1736
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
141 logger.info(rawHead.trim()+"\n",e); |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
142 } catch(WrappedRuntimeException wrapped) { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
143 RuntimeException e = (RuntimeException)wrapped.getCause(); |
1752 | 144 logger.warn(rawHead.trim()+"\n",e); |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
145 throw e; |
1736
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
146 } catch(RuntimeException e) { |
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
147 logger.error(rawHead.trim()+"\n",e); |
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
148 throw e; |
1137 | 149 } |
150 } | |
151 | |
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
152 private static final class WrappedRuntimeException extends Exception { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
153 WrappedRuntimeException(RuntimeException e) { |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
154 super(e); |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
155 } |
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
156 } |
1137 | 157 } |