1 17 18 package org.apache.coyote.http11; 19 20 import java.io.IOException ; 21 import java.io.InterruptedIOException ; 22 import java.net.InetAddress ; 23 import java.net.Socket ; 24 import java.security.AccessController ; 25 import java.security.PrivilegedAction ; 26 import java.util.StringTokenizer ; 27 import java.util.regex.Pattern ; 28 import java.util.regex.PatternSyntaxException ; 29 30 import org.apache.coyote.ActionCode; 31 import org.apache.coyote.ActionHook; 32 import org.apache.coyote.Adapter; 33 import org.apache.coyote.Request; 34 import org.apache.coyote.RequestInfo; 35 import org.apache.coyote.Response; 36 import org.apache.coyote.http11.filters.BufferedInputFilter; 37 import org.apache.coyote.http11.filters.ChunkedInputFilter; 38 import org.apache.coyote.http11.filters.ChunkedOutputFilter; 39 import org.apache.coyote.http11.filters.GzipOutputFilter; 40 import org.apache.coyote.http11.filters.IdentityInputFilter; 41 import org.apache.coyote.http11.filters.IdentityOutputFilter; 42 import org.apache.coyote.http11.filters.SavedRequestInputFilter; 43 import org.apache.coyote.http11.filters.VoidInputFilter; 44 import org.apache.coyote.http11.filters.VoidOutputFilter; 45 import org.apache.tomcat.util.buf.Ascii; 46 import org.apache.tomcat.util.buf.ByteChunk; 47 import org.apache.tomcat.util.buf.HexUtils; 48 import org.apache.tomcat.util.buf.MessageBytes; 49 import org.apache.tomcat.util.http.FastHttpDateFormat; 50 import org.apache.tomcat.util.http.MimeHeaders; 51 import org.apache.tomcat.util.net.JIoEndpoint; 52 import org.apache.tomcat.util.net.SSLSupport; 53 import org.apache.tomcat.util.res.StringManager; 54 55 56 61 public class Http11Processor implements ActionHook { 62 63 64 67 protected static org.apache.commons.logging.Log log 68 = org.apache.commons.logging.LogFactory.getLog(Http11Processor.class); 69 70 73 protected static StringManager sm = 74 StringManager.getManager(Constants.Package); 75 76 77 79 80 public Http11Processor(int headerBufferSize, JIoEndpoint endpoint) { 81 82 this.endpoint = endpoint; 83 84 request = new Request(); 85 inputBuffer = new InternalInputBuffer(request, headerBufferSize); 86 request.setInputBuffer(inputBuffer); 87 88 response = new Response(); 89 response.setHook(this); 90 outputBuffer = new InternalOutputBuffer(response, headerBufferSize); 91 response.setOutputBuffer(outputBuffer); 92 request.setResponse(response); 93 94 initializeFilters(); 95 96 int foo = HexUtils.DEC[0]; 98 99 } 100 101 102 104 105 108 protected Adapter adapter = null; 109 110 111 114 protected Request request = null; 115 116 117 120 protected Response response = null; 121 122 123 126 protected InternalInputBuffer inputBuffer = null; 127 128 129 132 protected InternalOutputBuffer outputBuffer = null; 133 134 135 138 protected boolean started = false; 139 140 141 144 protected boolean error = false; 145 146 147 150 protected boolean keepAlive = true; 151 152 153 156 protected boolean http11 = true; 157 158 159 162 protected boolean http09 = false; 163 164 165 169 protected boolean contentDelimitation = true; 170 171 172 175 protected boolean expectation = false; 176 177 178 181 protected Pattern [] restrictedUserAgents = null; 182 183 184 187 protected int maxKeepAliveRequests = -1; 188 189 190 193 protected SSLSupport sslSupport; 194 195 196 199 protected Socket socket; 200 201 202 205 protected String remoteAddr = null; 206 207 208 211 protected String remoteHost = null; 212 213 214 217 protected String localName = null; 218 219 220 221 224 protected int localPort = -1; 225 226 227 230 protected int remotePort = -1; 231 232 233 236 protected String localAddr = null; 237 238 239 242 protected int timeout = 300000; 243 244 245 248 protected boolean disableUploadTimeout = false; 249 250 251 254 protected int compressionLevel = 0; 255 256 257 260 protected int compressionMinSize = 2048; 261 262 263 266 protected int socketBuffer = -1; 267 268 269 272 protected int maxSavePostSize = 4 * 1024; 273 274 275 278 protected Pattern noCompressionUserAgents[] = null; 279 280 283 protected String [] compressableMimeTypes = 284 { "text/html", "text/xml", "text/plain" }; 285 286 287 290 protected char[] hostNameC = new char[0]; 291 292 293 296 protected JIoEndpoint endpoint; 297 298 299 302 protected String server = null; 303 304 305 307 308 311 public String getCompression() { 312 switch (compressionLevel) { 313 case 0: 314 return "off"; 315 case 1: 316 return "on"; 317 case 2: 318 return "force"; 319 } 320 return "off"; 321 } 322 323 324 327 public void setCompression(String compression) { 328 if (compression.equals("on")) { 329 this.compressionLevel = 1; 330 } else if (compression.equals("force")) { 331 this.compressionLevel = 2; 332 } else if (compression.equals("off")) { 333 this.compressionLevel = 0; 334 } else { 335 try { 336 compressionMinSize = Integer.parseInt(compression); 339 this.compressionLevel = 1; 340 } catch (Exception e) { 341 this.compressionLevel = 0; 342 } 343 } 344 } 345 346 349 public void setCompressionMinSize(int compressionMinSize) { 350 this.compressionMinSize = compressionMinSize; 351 } 352 353 354 361 public void addNoCompressionUserAgent(String userAgent) { 362 try { 363 Pattern nRule = Pattern.compile(userAgent); 364 noCompressionUserAgents = 365 addREArray(noCompressionUserAgents, nRule); 366 } catch (PatternSyntaxException pse) { 367 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 368 } 369 } 370 371 372 377 public void setNoCompressionUserAgents(Pattern [] noCompressionUserAgents) { 378 this.noCompressionUserAgents = noCompressionUserAgents; 379 } 380 381 382 388 public void setNoCompressionUserAgents(String noCompressionUserAgents) { 389 if (noCompressionUserAgents != null) { 390 StringTokenizer st = new StringTokenizer (noCompressionUserAgents, ","); 391 392 while (st.hasMoreTokens()) { 393 addNoCompressionUserAgent(st.nextToken().trim()); 394 } 395 } 396 } 397 398 405 public void addCompressableMimeType(String mimeType) { 406 compressableMimeTypes = 407 addStringArray(compressableMimeTypes, mimeType); 408 } 409 410 411 416 public void setCompressableMimeTypes(String [] compressableMimeTypes) { 417 this.compressableMimeTypes = compressableMimeTypes; 418 } 419 420 421 427 public void setCompressableMimeTypes(String compressableMimeTypes) { 428 if (compressableMimeTypes != null) { 429 StringTokenizer st = new StringTokenizer (compressableMimeTypes, ","); 430 431 while (st.hasMoreTokens()) { 432 addCompressableMimeType(st.nextToken().trim()); 433 } 434 } 435 } 436 437 438 441 public String [] findCompressableMimeTypes() { 442 return (compressableMimeTypes); 443 } 444 445 446 447 449 450 455 protected void addFilter(String className) { 456 try { 457 Class clazz = Class.forName(className); 458 Object obj = clazz.newInstance(); 459 if (obj instanceof InputFilter) { 460 inputBuffer.addFilter((InputFilter) obj); 461 } else if (obj instanceof OutputFilter) { 462 outputBuffer.addFilter((OutputFilter) obj); 463 } else { 464 log.warn(sm.getString("http11processor.filter.unknown", className)); 465 } 466 } catch (Exception e) { 467 log.error(sm.getString("http11processor.filter.error", className), e); 468 } 469 } 470 471 472 478 private String [] addStringArray(String sArray[], String value) { 479 String [] result = null; 480 if (sArray == null) { 481 result = new String [1]; 482 result[0] = value; 483 } 484 else { 485 result = new String [sArray.length + 1]; 486 for (int i = 0; i < sArray.length; i++) 487 result[i] = sArray[i]; 488 result[sArray.length] = value; 489 } 490 return result; 491 } 492 493 494 500 private Pattern [] addREArray(Pattern rArray[], Pattern value) { 501 Pattern [] result = null; 502 if (rArray == null) { 503 result = new Pattern [1]; 504 result[0] = value; 505 } 506 else { 507 result = new Pattern [rArray.length + 1]; 508 for (int i = 0; i < rArray.length; i++) 509 result[i] = rArray[i]; 510 result[rArray.length] = value; 511 } 512 return result; 513 } 514 515 516 522 private boolean inStringArray(String sArray[], String value) { 523 for (int i = 0; i < sArray.length; i++) { 524 if (sArray[i].equals(value)) { 525 return true; 526 } 527 } 528 return false; 529 } 530 531 532 538 private boolean startsWithStringArray(String sArray[], String value) { 539 if (value == null) 540 return false; 541 for (int i = 0; i < sArray.length; i++) { 542 if (value.startsWith(sArray[i])) { 543 return true; 544 } 545 } 546 return false; 547 } 548 549 550 557 public void addRestrictedUserAgent(String userAgent) { 558 try { 559 Pattern nRule = Pattern.compile(userAgent); 560 restrictedUserAgents = addREArray(restrictedUserAgents, nRule); 561 } catch (PatternSyntaxException pse) { 562 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 563 } 564 } 565 566 567 572 public void setRestrictedUserAgents(Pattern [] restrictedUserAgents) { 573 this.restrictedUserAgents = restrictedUserAgents; 574 } 575 576 577 583 public void setRestrictedUserAgents(String restrictedUserAgents) { 584 if (restrictedUserAgents != null) { 585 StringTokenizer st = 586 new StringTokenizer (restrictedUserAgents, ","); 587 while (st.hasMoreTokens()) { 588 addRestrictedUserAgent(st.nextToken().trim()); 589 } 590 } 591 } 592 593 594 597 public String [] findRestrictedUserAgents() { 598 String [] sarr = new String [restrictedUserAgents.length]; 599 600 for (int i = 0; i < restrictedUserAgents.length; i++) 601 sarr[i] = restrictedUserAgents[i].toString(); 602 603 return (sarr); 604 } 605 606 607 612 public void setMaxKeepAliveRequests(int mkar) { 613 maxKeepAliveRequests = mkar; 614 } 615 616 617 620 public int getMaxKeepAliveRequests() { 621 return maxKeepAliveRequests; 622 } 623 624 625 628 public void setMaxSavePostSize(int msps) { 629 maxSavePostSize = msps; 630 } 631 632 633 636 public int getMaxSavePostSize() { 637 return maxSavePostSize; 638 } 639 640 641 644 public void setSSLSupport(SSLSupport sslSupport) { 645 this.sslSupport = sslSupport; 646 } 647 648 649 652 public void setDisableUploadTimeout(boolean isDisabled) { 653 disableUploadTimeout = isDisabled; 654 } 655 656 659 public boolean getDisableUploadTimeout() { 660 return disableUploadTimeout; 661 } 662 663 666 public void setSocketBuffer(int socketBuffer) { 667 this.socketBuffer = socketBuffer; 668 outputBuffer.setSocketBuffer(socketBuffer); 669 } 670 671 674 public int getSocketBuffer() { 675 return socketBuffer; 676 } 677 678 681 public void setTimeout( int timeouts ) { 682 timeout = timeouts ; 683 } 684 685 688 public int getTimeout() { 689 return timeout; 690 } 691 692 693 696 public void setServer( String server ) { 697 if (server==null || server.equals("")) { 698 this.server = null; 699 } else { 700 this.server = server; 701 } 702 } 703 704 707 public String getServer() { 708 return server; 709 } 710 711 712 716 public Request getRequest() { 717 return request; 718 } 719 720 729 public void process(Socket socket) 730 throws IOException { 731 RequestInfo rp = request.getRequestProcessor(); 732 rp.setStage(org.apache.coyote.Constants.STAGE_PARSE); 733 734 remoteAddr = null; 736 remoteHost = null; 737 localAddr = null; 738 localName = null; 739 remotePort = -1; 740 localPort = -1; 741 742 this.socket = socket; 744 inputBuffer.setInputStream(socket.getInputStream()); 745 outputBuffer.setOutputStream(socket.getOutputStream()); 746 747 error = false; 749 keepAlive = true; 750 751 int keepAliveLeft = maxKeepAliveRequests; 752 int soTimeout = socket.getSoTimeout(); 753 int oldSoTimeout = soTimeout; 754 755 int threadRatio = (endpoint.getCurrentThreadsBusy() * 100) 756 / endpoint.getMaxThreads(); 757 if (threadRatio > 75) { 758 keepAliveLeft = 1; 759 } 760 761 if (soTimeout != oldSoTimeout) { 762 try { 763 socket.setSoTimeout(soTimeout); 764 } catch (Throwable t) { 765 log.debug(sm.getString("http11processor.socket.timeout"), t); 766 error = true; 767 } 768 } 769 770 boolean keptAlive = false; 771 772 while (started && !error && keepAlive) { 773 774 try { 776 if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) { 777 socket.setSoTimeout(soTimeout); 778 } 779 inputBuffer.parseRequestLine(); 780 request.setStartTime(System.currentTimeMillis()); 781 keptAlive = true; 782 if (!disableUploadTimeout) { 783 socket.setSoTimeout(timeout); 784 } 785 inputBuffer.parseHeaders(); 786 } catch (IOException e) { 787 error = true; 788 break; 789 } catch (Throwable t) { 790 if (log.isDebugEnabled()) { 791 log.debug(sm.getString("http11processor.header.parse"), t); 792 } 793 response.setStatus(400); 795 error = true; 796 } 797 798 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE); 800 try { 801 prepareRequest(); 802 } catch (Throwable t) { 803 if (log.isDebugEnabled()) { 804 log.debug(sm.getString("http11processor.request.prepare"), t); 805 } 806 response.setStatus(400); 808 error = true; 809 } 810 811 if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0) 812 keepAlive = false; 813 814 if (!error) { 816 try { 817 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 818 adapter.service(request, response); 819 if(keepAlive && !error) { error = response.getErrorException() != null || 826 statusDropsConnection(response.getStatus()); 827 } 828 829 } catch (InterruptedIOException e) { 830 error = true; 831 } catch (Throwable t) { 832 log.error(sm.getString("http11processor.request.process"), t); 833 response.setStatus(500); 835 error = true; 836 } 837 } 838 839 try { 841 rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT); 842 inputBuffer.endRequest(); 843 } catch (IOException e) { 844 error = true; 845 } catch (Throwable t) { 846 log.error(sm.getString("http11processor.request.finish"), t); 847 response.setStatus(500); 849 error = true; 850 } 851 try { 852 rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT); 853 outputBuffer.endRequest(); 854 } catch (IOException e) { 855 error = true; 856 } catch (Throwable t) { 857 log.error(sm.getString("http11processor.response.finish"), t); 858 error = true; 859 } 860 861 if (error) { 864 response.setStatus(500); 865 } 866 request.updateCounters(); 867 868 rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); 869 870 inputBuffer.nextRequest(); 875 outputBuffer.nextRequest(); 876 877 } 878 879 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 880 881 inputBuffer.recycle(); 883 outputBuffer.recycle(); 884 885 sslSupport = null; 887 } 888 889 890 892 893 899 public void action(ActionCode actionCode, Object param) { 900 901 if (actionCode == ActionCode.ACTION_COMMIT) { 902 904 if (response.isCommitted()) 905 return; 906 907 prepareResponse(); 909 try { 910 outputBuffer.commit(); 911 } catch (IOException e) { 912 error = true; 914 } 915 916 } else if (actionCode == ActionCode.ACTION_ACK) { 917 918 920 923 if ((response.isCommitted()) || !expectation) 924 return; 925 926 inputBuffer.setSwallowInput(true); 927 try { 928 outputBuffer.sendAck(); 929 } catch (IOException e) { 930 error = true; 932 } 933 934 } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { 935 936 try { 937 outputBuffer.flush(); 938 } catch (IOException e) { 939 error = true; 941 response.setErrorException(e); 942 } 943 944 } else if (actionCode == ActionCode.ACTION_CLOSE) { 945 947 950 try { 951 outputBuffer.endRequest(); 952 } catch (IOException e) { 953 error = true; 955 } 956 957 } else if (actionCode == ActionCode.ACTION_RESET) { 958 959 961 963 outputBuffer.reset(); 964 965 } else if (actionCode == ActionCode.ACTION_CUSTOM) { 966 967 969 } else if (actionCode == ActionCode.ACTION_START) { 970 971 started = true; 972 973 } else if (actionCode == ActionCode.ACTION_STOP) { 974 975 started = false; 976 977 } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { 978 979 try { 980 if (sslSupport != null) { 981 Object sslO = sslSupport.getCipherSuite(); 982 if (sslO != null) 983 request.setAttribute 984 (SSLSupport.CIPHER_SUITE_KEY, sslO); 985 sslO = sslSupport.getPeerCertificateChain(false); 986 if (sslO != null) 987 request.setAttribute 988 (SSLSupport.CERTIFICATE_KEY, sslO); 989 sslO = sslSupport.getKeySize(); 990 if (sslO != null) 991 request.setAttribute 992 (SSLSupport.KEY_SIZE_KEY, sslO); 993 sslO = sslSupport.getSessionId(); 994 if (sslO != null) 995 request.setAttribute 996 (SSLSupport.SESSION_ID_KEY, sslO); 997 } 998 } catch (Exception e) { 999 log.warn(sm.getString("http11processor.socket.ssl"), e); 1000 } 1001 1002 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) { 1003 1004 if ((remoteAddr == null) && (socket != null)) { 1005 InetAddress inetAddr = socket.getInetAddress(); 1006 if (inetAddr != null) { 1007 remoteAddr = inetAddr.getHostAddress(); 1008 } 1009 } 1010 request.remoteAddr().setString(remoteAddr); 1011 1012 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE) { 1013 1014 if ((localName == null) && (socket != null)) { 1015 InetAddress inetAddr = socket.getLocalAddress(); 1016 if (inetAddr != null) { 1017 localName = inetAddr.getHostName(); 1018 } 1019 } 1020 request.localName().setString(localName); 1021 1022 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) { 1023 1024 if ((remoteHost == null) && (socket != null)) { 1025 InetAddress inetAddr = socket.getInetAddress(); 1026 if (inetAddr != null) { 1027 remoteHost = inetAddr.getHostName(); 1028 } 1029 if(remoteHost == null) { 1030 if(remoteAddr != null) { 1031 remoteHost = remoteAddr; 1032 } else { request.remoteHost().recycle(); 1034 } 1035 } 1036 } 1037 request.remoteHost().setString(remoteHost); 1038 1039 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) { 1040 1041 if (localAddr == null) 1042 localAddr = socket.getLocalAddress().getHostAddress(); 1043 1044 request.localAddr().setString(localAddr); 1045 1046 } else if (actionCode == ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE) { 1047 1048 if ((remotePort == -1 ) && (socket !=null)) { 1049 remotePort = socket.getPort(); 1050 } 1051 request.setRemotePort(remotePort); 1052 1053 } else if (actionCode == ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE) { 1054 1055 if ((localPort == -1 ) && (socket !=null)) { 1056 localPort = socket.getLocalPort(); 1057 } 1058 request.setLocalPort(localPort); 1059 1060 } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) { 1061 if( sslSupport != null) { 1062 1066 InputFilter[] inputFilters = inputBuffer.getFilters(); 1067 ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER]) 1068 .setLimit(maxSavePostSize); 1069 inputBuffer.addActiveFilter 1070 (inputFilters[Constants.BUFFERED_FILTER]); 1071 try { 1072 Object sslO = sslSupport.getPeerCertificateChain(true); 1073 if( sslO != null) { 1074 request.setAttribute 1075 (SSLSupport.CERTIFICATE_KEY, sslO); 1076 } 1077 } catch (Exception e) { 1078 log.warn(sm.getString("http11processor.socket.ssl"), e); 1079 } 1080 } 1081 } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { 1082 ByteChunk body = (ByteChunk) param; 1083 1084 InputFilter savedBody = new SavedRequestInputFilter(body); 1085 savedBody.setRequest(request); 1086 1087 InternalInputBuffer internalBuffer = (InternalInputBuffer) 1088 request.getInputBuffer(); 1089 internalBuffer.addActiveFilter(savedBody); 1090 } 1091 1092 } 1093 1094 1095 1097 1098 1103 public void setAdapter(Adapter adapter) { 1104 this.adapter = adapter; 1105 } 1106 1107 1108 1113 public Adapter getAdapter() { 1114 return adapter; 1115 } 1116 1117 1118 1120 1121 1124 protected void prepareRequest() { 1125 1126 http11 = true; 1127 http09 = false; 1128 contentDelimitation = false; 1129 expectation = false; 1130 if (sslSupport != null) { 1131 request.scheme().setString("https"); 1132 } 1133 MessageBytes protocolMB = request.protocol(); 1134 if (protocolMB.equals(Constants.HTTP_11)) { 1135 http11 = true; 1136 protocolMB.setString(Constants.HTTP_11); 1137 } else if (protocolMB.equals(Constants.HTTP_10)) { 1138 http11 = false; 1139 keepAlive = false; 1140 protocolMB.setString(Constants.HTTP_10); 1141 } else if (protocolMB.equals("")) { 1142 http09 = true; 1144 http11 = false; 1145 keepAlive = false; 1146 } else { 1147 http11 = false; 1149 error = true; 1150 response.setStatus(505); 1152 } 1153 1154 MessageBytes methodMB = request.method(); 1155 if (methodMB.equals(Constants.GET)) { 1156 methodMB.setString(Constants.GET); 1157 } else if (methodMB.equals(Constants.POST)) { 1158 methodMB.setString(Constants.POST); 1159 } 1160 1161 MimeHeaders headers = request.getMimeHeaders(); 1162 1163 MessageBytes connectionValueMB = headers.getValue("connection"); 1165 if (connectionValueMB != null) { 1166 ByteChunk connectionValueBC = connectionValueMB.getByteChunk(); 1167 if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) { 1168 keepAlive = false; 1169 } else if (findBytes(connectionValueBC, 1170 Constants.KEEPALIVE_BYTES) != -1) { 1171 keepAlive = true; 1172 } 1173 } 1174 1175 MessageBytes expectMB = null; 1176 if (http11) 1177 expectMB = headers.getValue("expect"); 1178 if ((expectMB != null) 1179 && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) { 1180 inputBuffer.setSwallowInput(false); 1181 expectation = true; 1182 } 1183 1184 if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) { 1186 MessageBytes userAgentValueMB = headers.getValue("user-agent"); 1187 if(userAgentValueMB != null) { 1190 String userAgentValue = userAgentValueMB.toString(); 1191 for (int i = 0; i < restrictedUserAgents.length; i++) { 1192 if (restrictedUserAgents[i].matcher(userAgentValue).matches()) { 1193 http11 = false; 1194 keepAlive = false; 1195 break; 1196 } 1197 } 1198 } 1199 } 1200 1201 ByteChunk uriBC = request.requestURI().getByteChunk(); 1203 if (uriBC.startsWithIgnoreCase("http", 0)) { 1204 1205 int pos = uriBC.indexOf("://", 0, 3, 4); 1206 int uriBCStart = uriBC.getStart(); 1207 int slashPos = -1; 1208 if (pos != -1) { 1209 byte[] uriB = uriBC.getBytes(); 1210 slashPos = uriBC.indexOf('/', pos + 3); 1211 if (slashPos == -1) { 1212 slashPos = uriBC.getLength(); 1213 request.requestURI().setBytes 1215 (uriB, uriBCStart + pos + 1, 1); 1216 } else { 1217 request.requestURI().setBytes 1218 (uriB, uriBCStart + slashPos, 1219 uriBC.getLength() - slashPos); 1220 } 1221 MessageBytes hostMB = headers.setValue("host"); 1222 hostMB.setBytes(uriB, uriBCStart + pos + 3, 1223 slashPos - pos - 3); 1224 } 1225 1226 } 1227 1228 InputFilter[] inputFilters = inputBuffer.getFilters(); 1230 1231 MessageBytes transferEncodingValueMB = null; 1233 if (http11) 1234 transferEncodingValueMB = headers.getValue("transfer-encoding"); 1235 if (transferEncodingValueMB != null) { 1236 String transferEncodingValue = transferEncodingValueMB.toString(); 1237 int startPos = 0; 1239 int commaPos = transferEncodingValue.indexOf(','); 1240 String encodingName = null; 1241 while (commaPos != -1) { 1242 encodingName = transferEncodingValue.substring 1243 (startPos, commaPos).toLowerCase().trim(); 1244 if (!addInputFilter(inputFilters, encodingName)) { 1245 error = true; 1247 response.setStatus(501); 1249 } 1250 startPos = commaPos + 1; 1251 commaPos = transferEncodingValue.indexOf(',', startPos); 1252 } 1253 encodingName = transferEncodingValue.substring(startPos) 1254 .toLowerCase().trim(); 1255 if (!addInputFilter(inputFilters, encodingName)) { 1256 error = true; 1258 response.setStatus(501); 1260 } 1261 } 1262 1263 long contentLength = request.getContentLengthLong(); 1265 if (contentLength >= 0 && !contentDelimitation) { 1266 inputBuffer.addActiveFilter 1267 (inputFilters[Constants.IDENTITY_FILTER]); 1268 contentDelimitation = true; 1269 } 1270 1271 MessageBytes valueMB = headers.getValue("host"); 1272 1273 if (http11 && (valueMB == null)) { 1275 error = true; 1276 response.setStatus(400); 1278 } 1279 1280 parseHost(valueMB); 1281 1282 if (!contentDelimitation) { 1283 inputBuffer.addActiveFilter 1287 (inputFilters[Constants.VOID_FILTER]); 1288 contentDelimitation = true; 1289 } 1290 1291 } 1292 1293 1294 1297 public void parseHost(MessageBytes valueMB) { 1298 1299 if (valueMB == null || valueMB.isNull()) { 1300 request.setServerPort(socket.getLocalPort()); 1304 InetAddress localAddress = socket.getLocalAddress(); 1305 request.serverName().setString(localAddress.getHostName()); 1308 return; 1309 } 1310 1311 ByteChunk valueBC = valueMB.getByteChunk(); 1312 byte[] valueB = valueBC.getBytes(); 1313 int valueL = valueBC.getLength(); 1314 int valueS = valueBC.getStart(); 1315 int colonPos = -1; 1316 if (hostNameC.length < valueL) { 1317 hostNameC = new char[valueL]; 1318 } 1319 1320 boolean ipv6 = (valueB[valueS] == '['); 1321 boolean bracketClosed = false; 1322 for (int i = 0; i < valueL; i++) { 1323 char b = (char) valueB[i + valueS]; 1324 hostNameC[i] = b; 1325 if (b == ']') { 1326 bracketClosed = true; 1327 } else if (b == ':') { 1328 if (!ipv6 || bracketClosed) { 1329 colonPos = i; 1330 break; 1331 } 1332 } 1333 } 1334 1335 if (colonPos < 0) { 1336 if (sslSupport == null) { 1337 request.setServerPort(80); 1339 } else { 1340 request.setServerPort(443); 1342 } 1343 request.serverName().setChars(hostNameC, 0, valueL); 1344 } else { 1345 1346 request.serverName().setChars(hostNameC, 0, colonPos); 1347 1348 int port = 0; 1349 int mult = 1; 1350 for (int i = valueL - 1; i > colonPos; i--) { 1351 int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; 1352 if (charValue == -1) { 1353 error = true; 1355 response.setStatus(400); 1357 break; 1358 } 1359 port = port + (charValue * mult); 1360 mult = 10 * mult; 1361 } 1362 request.setServerPort(port); 1363 1364 } 1365 1366 } 1367 1368 1369 1372 private boolean isCompressable() { 1373 1374 1377 1381 MessageBytes acceptEncodingMB = 1383 request.getMimeHeaders().getValue("accept-encoding"); 1384 1385 if ((acceptEncodingMB == null) 1386 || (acceptEncodingMB.indexOf("gzip") == -1)) 1387 return false; 1388 1389 MessageBytes contentEncodingMB = 1391 response.getMimeHeaders().getValue("Content-Encoding"); 1392 1393 if ((contentEncodingMB != null) 1394 && (contentEncodingMB.indexOf("gzip") != -1)) 1395 return false; 1396 1397 if (compressionLevel == 2) 1399 return true; 1400 1401 if (noCompressionUserAgents != null) { 1403 MessageBytes userAgentValueMB = 1404 request.getMimeHeaders().getValue("user-agent"); 1405 if(userAgentValueMB != null) { 1406 String userAgentValue = userAgentValueMB.toString(); 1407 1408 for (int i = 0; i < noCompressionUserAgents.length; i++) 1410 if (noCompressionUserAgents[i].matcher(userAgentValue).matches()) 1411 return false; 1412 } 1413 } 1414 1415 long contentLength = response.getContentLengthLong(); 1417 if ((contentLength == -1) 1418 || (contentLength > compressionMinSize)) { 1419 if (compressableMimeTypes != null) { 1421 return (startsWithStringArray(compressableMimeTypes, 1422 response.getContentType())); 1423 } 1424 } 1425 1426 return false; 1427 } 1428 1429 1430 1434 protected void prepareResponse() { 1435 1436 boolean entityBody = true; 1437 contentDelimitation = false; 1438 1439 OutputFilter[] outputFilters = outputBuffer.getFilters(); 1440 1441 if (http09 == true) { 1442 outputBuffer.addActiveFilter 1444 (outputFilters[Constants.IDENTITY_FILTER]); 1445 return; 1446 } 1447 1448 int statusCode = response.getStatus(); 1449 if ((statusCode == 204) || (statusCode == 205) 1450 || (statusCode == 304)) { 1451 outputBuffer.addActiveFilter 1453 (outputFilters[Constants.VOID_FILTER]); 1454 entityBody = false; 1455 contentDelimitation = true; 1456 } 1457 1458 MessageBytes methodMB = request.method(); 1459 if (methodMB.equals("HEAD")) { 1460 outputBuffer.addActiveFilter 1462 (outputFilters[Constants.VOID_FILTER]); 1463 contentDelimitation = true; 1464 } 1465 1466 boolean useCompression = false; 1468 if (entityBody && (compressionLevel > 0)) { 1469 useCompression = isCompressable(); 1470 1471 if (useCompression) { 1473 response.setContentLength(-1); 1474 } 1475 } 1476 1477 MimeHeaders headers = response.getMimeHeaders(); 1478 if (!entityBody) { 1479 response.setContentLength(-1); 1480 } else { 1481 String contentType = response.getContentType(); 1482 if (contentType != null) { 1483 headers.setValue("Content-Type").setString(contentType); 1484 } 1485 String contentLanguage = response.getContentLanguage(); 1486 if (contentLanguage != null) { 1487 headers.setValue("Content-Language") 1488 .setString(contentLanguage); 1489 } 1490 } 1491 1492 long contentLength = response.getContentLengthLong(); 1493 if (contentLength != -1) { 1494 headers.setValue("Content-Length").setLong(contentLength); 1495 outputBuffer.addActiveFilter 1496 (outputFilters[Constants.IDENTITY_FILTER]); 1497 contentDelimitation = true; 1498 } else { 1499 if (entityBody && http11 && keepAlive) { 1500 outputBuffer.addActiveFilter 1501 (outputFilters[Constants.CHUNKED_FILTER]); 1502 contentDelimitation = true; 1503 headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED); 1504 } else { 1505 outputBuffer.addActiveFilter 1506 (outputFilters[Constants.IDENTITY_FILTER]); 1507 } 1508 } 1509 1510 if (useCompression) { 1511 outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]); 1512 headers.setValue("Content-Encoding").setString("gzip"); 1513 headers.setValue("Vary").setString("Accept-Encoding"); 1515 } 1516 1517 String date = null; 1519 if (System.getSecurityManager() != null){ 1520 date = (String )AccessController.doPrivileged( 1521 new PrivilegedAction () { 1522 public Object run(){ 1523 return FastHttpDateFormat.getCurrentDate(); 1524 } 1525 } 1526 ); 1527 } else { 1528 date = FastHttpDateFormat.getCurrentDate(); 1529 } 1530 headers.setValue("Date").setString(date); 1531 1532 1534 if ((entityBody) && (!contentDelimitation)) { 1535 keepAlive = false; 1538 } 1539 1540 keepAlive = keepAlive && !statusDropsConnection(statusCode); 1543 if (!keepAlive) { 1544 headers.addValue(Constants.CONNECTION).setString(Constants.CLOSE); 1545 } else if (!http11 && !error) { 1546 headers.addValue(Constants.CONNECTION).setString(Constants.KEEPALIVE); 1547 } 1548 1549 outputBuffer.sendStatus(); 1551 1552 if (server != null) { 1554 headers.setValue("Server").setString(server); 1555 } else { 1556 outputBuffer.write(Constants.SERVER_BYTES); 1557 } 1558 1559 int size = headers.size(); 1560 for (int i = 0; i < size; i++) { 1561 outputBuffer.sendHeader(headers.getName(i), headers.getValue(i)); 1562 } 1563 outputBuffer.endHeaders(); 1564 1565 } 1566 1567 1568 1571 protected void initializeFilters() { 1572 1573 inputBuffer.addFilter(new IdentityInputFilter()); 1575 outputBuffer.addFilter(new IdentityOutputFilter()); 1576 1577 inputBuffer.addFilter(new ChunkedInputFilter()); 1579 outputBuffer.addFilter(new ChunkedOutputFilter()); 1580 1581 inputBuffer.addFilter(new VoidInputFilter()); 1583 outputBuffer.addFilter(new VoidOutputFilter()); 1584 1585 inputBuffer.addFilter(new BufferedInputFilter()); 1587 1588 outputBuffer.addFilter(new GzipOutputFilter()); 1591 1592 } 1593 1594 1595 1601 protected boolean addInputFilter(InputFilter[] inputFilters, 1602 String encodingName) { 1603 if (encodingName.equals("identity")) { 1604 } else if (encodingName.equals("chunked")) { 1606 inputBuffer.addActiveFilter 1607 (inputFilters[Constants.CHUNKED_FILTER]); 1608 contentDelimitation = true; 1609 } else { 1610 for (int i = 2; i < inputFilters.length; i++) { 1611 if (inputFilters[i].getEncodingName() 1612 .toString().equals(encodingName)) { 1613 inputBuffer.addActiveFilter(inputFilters[i]); 1614 return true; 1615 } 1616 } 1617 return false; 1618 } 1619 return true; 1620 } 1621 1622 1623 1627 protected int findBytes(ByteChunk bc, byte[] b) { 1628 1629 byte first = b[0]; 1630 byte[] buff = bc.getBuffer(); 1631 int start = bc.getStart(); 1632 int end = bc.getEnd(); 1633 1634 int srcEnd = b.length; 1636 1637 for (int i = start; i <= (end - srcEnd); i++) { 1638 if (Ascii.toLower(buff[i]) != first) continue; 1639 int myPos = i+1; 1641 for (int srcPos = 1; srcPos < srcEnd; ) { 1642 if (Ascii.toLower(buff[myPos++]) != b[srcPos++]) 1643 break; 1644 if (srcPos == srcEnd) return i - start; } 1646 } 1647 return -1; 1648 1649 } 1650 1651 1655 protected boolean statusDropsConnection(int status) { 1656 return status == 400 || 1657 status == 408 || 1658 status == 411 || 1659 status == 413 || 1660 status == 414 || 1661 status == 500 || 1662 status == 503 || 1663 status == 501 ; 1664 } 1665 1666} 1667 | Popular Tags |