Mercurial Hosting > luan
annotate src/goodjava/webserver/Connection.java @ 1832:d55c3eaf21d7
add jar
| author | clarkton <ibraclarkton@gmail.com> | 
|---|---|
| date | Wed, 11 Dec 2024 17:17:56 +0000 | 
| parents | 32e77b071e09 | 
| children | bba3e529e346 | 
| rev | line source | 
|---|---|
| 1402 
27efb1fcbcb5
move luan.lib to goodjava
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1347diff
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: 
1347diff
changeset | 7 import goodjava.logging.Logger; | 
| 
27efb1fcbcb5
move luan.lib to goodjava
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1347diff
changeset | 8 import goodjava.logging.LoggerFactory; | 
| 
27efb1fcbcb5
move luan.lib to goodjava
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1347diff
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: 
1138diff
changeset | 16 static void handle(Server server,Socket socket) { | 
| 
0f59eab45f3d
webserver - threading
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1138diff
changeset | 17 new Connection(server,socket).handle(); | 
| 
0f59eab45f3d
webserver - threading
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1138diff
changeset | 18 } | 
| 
0f59eab45f3d
webserver - threading
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1138diff
changeset | 19 | 
| 1137 | 20 private final Server server; | 
| 21 private final Socket socket; | |
| 22 | |
| 1142 
0f59eab45f3d
webserver - threading
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1138diff
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: 
1607diff
changeset | 29 String rawHead = ""; | 
| 1137 | 30 try { | 
| 1144 
ae0a048f3bc7
webserver - handle POST params
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1142diff
changeset | 31 Request request = new Request(); | 
| 1194 
bd0420fb3dd0
handle ParseException in webserver
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1162diff
changeset | 32 Response response; | 
| 1513 | 33 String contentType = null; | 
| 1194 
bd0420fb3dd0
handle ParseException in webserver
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1162diff
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: 
1738diff
changeset | 80 try { | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 81 System.arraycopy(a,endOfHeader,body,0,size); | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 82 } catch(ArrayIndexOutOfBoundsException e) { | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 83 throw new WrappedRuntimeException(e); | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
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: 
1142diff
changeset | 87 if( n == -1 ) { | 
| 
ae0a048f3bc7
webserver - handle POST params
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1142diff
changeset | 88 throw new IOException("unexpected end of input at "+size); | 
| 
ae0a048f3bc7
webserver - handle POST params
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1142diff
changeset | 89 } | 
| 
ae0a048f3bc7
webserver - handle POST params
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1142diff
changeset | 90 size += n; | 
| 
ae0a048f3bc7
webserver - handle POST params
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1142diff
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: 
1162diff
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: 
1162diff
changeset | 123 response = server.handler.handle(request); | 
| 
bd0420fb3dd0
handle ParseException in webserver
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1162diff
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: 
1607diff
changeset | 141 logger.info(rawHead.trim()+"\n",e); | 
| 1750 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 142 } catch(WrappedRuntimeException wrapped) { | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
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: 
1738diff
changeset | 145 throw e; | 
| 1736 
a02a75e3daa8
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1607diff
changeset | 146 } catch(RuntimeException e) { | 
| 
a02a75e3daa8
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1607diff
changeset | 147 logger.error(rawHead.trim()+"\n",e); | 
| 
a02a75e3daa8
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1607diff
changeset | 148 throw e; | 
| 1137 | 149 } | 
| 150 } | |
| 151 | |
| 1750 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 152 private static final class WrappedRuntimeException extends Exception { | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 153 WrappedRuntimeException(RuntimeException e) { | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 154 super(e); | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 155 } | 
| 
c7b3c327248a
webserver error handling
 Franklin Schmidt <fschmidt@gmail.com> parents: 
1738diff
changeset | 156 } | 
| 1137 | 157 } | 
