Mercurial Hosting > luan
annotate src/goodjava/webserver/Connection.java @ 2013:0f14207596b3
swing
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Sun, 14 Sep 2025 18:04:00 -0600 |
| parents | bba3e529e346 |
| 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"); |
| 1137 | 132 byte[] header = response.toHeaderString().getBytes(); |
| 133 | |
| 134 OutputStream out = socket.getOutputStream(); | |
| 135 out.write(header); | |
| 2008 | 136 IoUtils.copyAll(response.body,out); |
| 1137 | 137 out.close(); |
| 138 socket.close(); | |
| 139 } catch(IOException e) { | |
|
1736
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
140 logger.info(rawHead.trim()+"\n",e); |
|
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
141 } catch(WrappedRuntimeException wrapped) { |
|
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
142 RuntimeException e = (RuntimeException)wrapped.getCause(); |
| 1752 | 143 logger.warn(rawHead.trim()+"\n",e); |
|
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
144 throw e; |
|
1736
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
145 } catch(RuntimeException e) { |
|
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
146 logger.error(rawHead.trim()+"\n",e); |
|
a02a75e3daa8
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
147 throw e; |
| 1137 | 148 } |
| 149 } | |
| 150 | |
|
1750
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
151 private static final class WrappedRuntimeException extends Exception { |
|
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
152 WrappedRuntimeException(RuntimeException e) { |
|
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
153 super(e); |
|
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
154 } |
|
c7b3c327248a
webserver error handling
Franklin Schmidt <fschmidt@gmail.com>
parents:
1738
diff
changeset
|
155 } |
| 1137 | 156 } |
