Tomcat 에서 protocol을 org.apache.coyote.http11.Http11NioProtocol 을 사용하는 상황에서 응답을 무시하거나 505 HTTP Version Not Found Exception이 발생되었다.

6.0.20버젼으로 다운그레이드하니 Exception 발생이 안된다..

 

원인은 Nio connnector 연결 관련해서 처리 코드가 잘못하였다. 그래서, 505 Http Version Not Found Exception이 발생되었을 뿐 아니라. Async Http 연결을 처리하는 부분에서 문제가 있었다.

관련 50505 버그는 Blank responses (이슈 https://issues.apache.org/bugzilla/show_bug.cgi?id=50072) 문제와 함께 처리되었다.

문제가 되는 버젼은  다음과 같다.
- tomcat 6.0.21~29, tomcat 7.0.1~ 7.0.4까지

 톰캣은 6.0.30와 7.0.5에서 패치되었다.

http://tomcat.apache.org/tomcat-6.0-doc/changelog.html

50072: NIO connector can mis-read request line if not sent in a single packet. (markt/kkolinko)

http://tomcat.apache.org/tomcat-7.0-doc/changelog.html

50072: Fix issues when using a non-blocking read for the request line with the NIO connector that could result in the request line being mis-read. (markt)

 

패치 내용은 소켓상태에 대한 처리와 패킷 파싱하는 부분이다.

 

Index: java/org/apache/coyote/http11/Http11NioProtocol.java
===================================================================
--- java/org/apache/coyote/http11/Http11NioProtocol.java (revision 1022282)
+++ java/org/apache/coyote/http11/Http11NioProtocol.java (working copy)
@@ -720,21 +720,24 @@
 
                 SocketState state = processor.process(socket);
                 if (state == SocketState.LONG) {
-                    // Associate the connection with the processor. The next request
-                    // processed by this thread will use either a new or a recycled
-                    // processor.
-                    //if (log.isDebugEnabled()) log.debug("Not recycling ["+processor+"] Comet="+((NioEndpoint.KeyAttachment)socket.getAttachment(false)).getComet());
+                    // In the middle of processing a request/response. Keep the
+                    // socket associated with the processor.
                     connections.put(socket, processor);
+
                     if (processor.comet) {
                         NioEndpoint.KeyAttachment att = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
                         socket.getPoller().add(socket,att.getCometOps());
                     } else {
-                     //we should not hold on to the processor objects
-                     release(socket);
                         socket.getPoller().add(socket);
                     }
+                } else if (state == SocketState.OPEN) {
+                    // In keep-alive but between requests. OK to recycle
+                    // processor. Continue to poll for the next request.
+                    socket.getPoller().add(socket);
+                    release(socket);
                 } else {
-                    recycledProcessors.offer(processor);
+                    // Connection closed. OK to recycle the processor.
+                    release(socket);
                 }
                 return state;
 

 


Index: java/org/apache/coyote/http11/InternalNioInputBuffer.java
===================================================================
--- java/org/apache/coyote/http11/InternalNioInputBuffer.java (revision 1022282)
+++ java/org/apache/coyote/http11/InternalNioInputBuffer.java (working copy)
@@ -404,7 +404,7 @@
      * @return true if data is properly fed; false if no data is available
      * immediately and thread should be freed
      */
-    public boolean parseRequestLine(boolean useAvailableData)
+    public boolean parseRequestLine(boolean useAvailableDataOnly)
         throws IOException {
 
         //check state
@@ -418,7 +418,7 @@
                
                 // Read new bytes if needed
                 if (pos >= lastValid) {
-                    if (useAvailableData) {
+                    if (useAvailableDataOnly) {
                         return false;
                     }
                     // Do a simple read with a short timeout
@@ -434,7 +434,7 @@
             // Mark the current buffer position
            
             if (pos >= lastValid) {
-                if (useAvailableData) {
+                if (useAvailableDataOnly) {
                     return false;
                 }
                 // Do a simple read with a short timeout
@@ -465,7 +465,6 @@
                 }
                 pos++;
             }
-            parsingRequestLineStart = pos;
             parsingRequestLinePhase = 3;
         }
         if ( parsingRequestLinePhase == 3 ) {
@@ -483,13 +482,17 @@
                     space = false;
                 }
             }
-
+            parsingRequestLineStart = pos;
+            parsingRequestLinePhase = 4;
+        }
+        if (parsingRequestLinePhase == 4) {
             // Mark the current buffer position
            
             int end = 0;
             //
             // Reading the URI
             //
+            boolean space = false;
             while (!space) {
                 // Read new bytes if needed
                 if (pos >= lastValid) {
@@ -519,10 +522,9 @@
             } else {
                 request.requestURI().setBytes(buf, parsingRequestLineStart, end - parsingRequestLineStart);
             }
-            parsingRequestLineStart = pos;
-            parsingRequestLinePhase = 4;
+            parsingRequestLinePhase = 5;
         }
-        if ( parsingRequestLinePhase == 4 ) {
+        if ( parsingRequestLinePhase == 5 ) {
             // Spec says single SP but also be tolerant of multiple and/or HT
             boolean space = true;
             while (space) {
@@ -537,7 +539,10 @@
                     space = false;
                 }
             }
-
+            parsingRequestLineStart = pos;
+            parsingRequestLinePhase = 6;
+        }
+        if (parsingRequestLinePhase == 6) {
             // Mark the current buffer position
            
             end = 0;
@@ -548,7 +553,7 @@
             while (!parsingRequestLineEol) {
                 // Read new bytes if needed
                 if (pos >= lastValid) {
-                    if (!fill(true, false)) //reques line parsing
+                    if (!fill(true, false)) //request line parsing
                         return false;
                 }

 

Posted by '김용환'
,