[grizzly~git:d635cb82] [master] Changes for https://java.net/jira/browse/GRIZZLY-1603 (Make HTTP

  • From: rlubke@...
  • To: commits@...
  • Subject: [grizzly~git:d635cb82] [master] Changes for https://java.net/jira/browse/GRIZZLY-1603 (Make HTTP
  • Date: Thu, 7 Nov 2013 23:15:27 +0000

Project:    grizzly
Repository: git
Revision:   d635cb82b8a1c66347a831514888526d4e5b6433
Author:     rlubke
Date:       2013-11-07 23:15:17 UTC
Link:       

Log Message:
------------
[master] Changes for https://java.net/jira/browse/GRIZZLY-1603 ;(Make HTTP 
Host header parsing lazy).

(cherry picked from commit 0c36aed022f88bbc45e7f22749a9f868f509a0c6)



Revisions:
----------
d635cb82b8a1c66347a831514888526d4e5b6433


Modified Paths:
---------------
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpHandlerChain.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpServer.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/DispatcherHelper.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/Mapper.java
modules/http-servlet/src/main/java/org/glassfish/grizzly/servlet/WebappContext.java
modules/http/src/main/java/org/glassfish/grizzly/http/HttpRequestPacket.java
modules/http/src/main/java/org/glassfish/grizzly/http/HttpServerFilter.java
modules/http/src/main/java/org/glassfish/grizzly/http/util/HttpCodecUtils.java
modules/spdy/src/main/java/org/glassfish/grizzly/spdy/SpdyHandlerFilter.java
modules/websockets/src/main/java/org/glassfish/grizzly/websockets/DefaultWebSocket.java
modules/websockets/src/main/java/org/glassfish/grizzly/websockets/WebSocketEngine.java


Diffs:
------
--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpHandlerChain.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpHandlerChain.java
@@ -46,6 +46,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.glassfish.grizzly.Grizzly;
+import org.glassfish.grizzly.http.HttpRequestPacket;
 import org.glassfish.grizzly.http.server.jmxbase.JmxEventListener;
 import org.glassfish.grizzly.http.server.jmxbase.Monitorable;
 import org.glassfish.grizzly.http.server.util.DispatcherHelper;
@@ -171,10 +172,10 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
             
             final MappingData mappingData = request.obtainMappingData();
 
-            mapper.mapUriWithSemicolon(request.getRequest().serverName(),
-                    decodedURI,
-                    mappingData,
-                    0);
+            mapper.mapUriWithSemicolon(request.getRequest(),
+                                       decodedURI,
+                                       mappingData,
+                                       0);
 
 
             HttpHandler httpHandler;
@@ -345,7 +346,7 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
 
     @Override
     public synchronized void destroy() {
-        mapperUpdateLock.readLock().lock();
+        mapperUpdateLock.writeLock().lock();
         
         try {
             for (Entry<HttpHandler, String[]> handler : handlers.entrySet()) 
{
@@ -353,7 +354,7 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
                 a.destroy();
             }
         } finally {
-            mapperUpdateLock.readLock().unlock();
+            mapperUpdateLock.writeLock().unlock();
         }
         started = false;
     }
@@ -419,10 +420,10 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
     private final class DispatchHelperImpl implements DispatcherHelper {
 
         @Override
-        public void mapPath(final DataChunk host, final DataChunk path,
+        public void mapPath(final HttpRequestPacket requestPacket, final 
DataChunk path,
                 final MappingData mappingData) throws Exception {
             
-            mapper.map(host, path, mappingData);
+            mapper.map(requestPacket, path, mappingData);
         }
 
         @Override--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpServer.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpServer.java
@@ -113,7 +113,7 @@ public class HttpServer {
      * Future to control graceful shutdown status
      */
     private FutureImpl<HttpServer> shutdownFuture;
-
+    
     /**
      * HttpHandler, which processes HTTP requests
      */
@@ -238,19 +238,6 @@ public class HttpServer {
     }
 
     /**
-     * @return a {@link GrizzlyFuture} that will be considered complete
-     *  once the {@link HttpServer} has been shutdown.
-     *
-     * @since 2.3.8
-     */
-    public synchronized GrizzlyFuture<HttpServer> shutdownFuture() {
-        if (shutdownFuture == null) {
-            shutdownFuture = Futures.createSafeFuture();
-        }
-        return shutdownFuture;
-    }
-
-    /**
      * <p>
      * Starts the <code>HttpServer</code>.
      * </p>
@@ -267,7 +254,9 @@ public class HttpServer {
                     + " shutdown state. You have to either wait for shutdown 
to"
                     + " complete or force it by calling shutdownNow()");
         }
-
+        state = State.RUNNING;
+        shutdownFuture = null;
+        
         configureAuxThreadPool();
 
         delayedExecutor = new DelayedExecutor(auxExecutorService);
@@ -304,8 +293,6 @@ public class HttpServer {
             }
         }
 
-        state = State.RUNNING;
-
         if (LOGGER.isLoggable(Level.INFO)) {
             LOGGER.log(Level.INFO, "[{0}] Started.", 
getServerConfiguration().getName());
         }
@@ -378,9 +365,7 @@ public class HttpServer {
                     Futures.createReadyFuture(this);
         }
 
-        if (shutdownFuture == null) {
-            shutdownFuture = Futures.createSafeFuture();
-        }
+        shutdownFuture = Futures.createSafeFuture();
         state = State.STOPPING;
 
         final int listenersCount = listeners.size();
@@ -408,6 +393,7 @@ public class HttpServer {
             listener.shutdown(gracePeriod, 
timeUnit).addCompletionHandler(shutdownCompletionHandler);
         }
 
+
         return shutdownFuture;
     }
 
@@ -430,6 +416,8 @@ public class HttpServer {
         if (state == State.STOPPED) {
             return;
         }
+        state = State.STOPPED;
+
         try {
 
             if (serverConfig.isJmxEnabled()) {
@@ -463,14 +451,10 @@ public class HttpServer {
                         listener.getTransport().getFilterChain();
                 filterChain.clear();
             }
-
-            state = State.STOPPED;
-
+            
             if (shutdownFuture != null) {
                 shutdownFuture.result(this);
-                shutdownFuture = null;
             }
-
         }
 
     }--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/DispatcherHelper.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/DispatcherHelper.java
@@ -40,6 +40,7 @@
 
 package org.glassfish.grizzly.http.server.util;
 
+import org.glassfish.grizzly.http.HttpRequestPacket;
 import org.glassfish.grizzly.http.util.DataChunk;
 
 /**
@@ -48,7 +49,7 @@ import org.glassfish.grizzly.http.util.DataChunk;
  * @author Alexey Stashok
  */
 public interface DispatcherHelper {
-    public void mapPath(DataChunk host, DataChunk path, MappingData 
mappingData)
+    public void mapPath(HttpRequestPacket requestPacket, DataChunk path, 
MappingData mappingData)
             throws Exception;
 
     public void mapName(DataChunk name, MappingData mappingData) throws 
Exception;--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/Mapper.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/Mapper.java
@@ -58,6 +58,7 @@
 
 package org.glassfish.grizzly.http.server.util;
 
+import org.glassfish.grizzly.http.HttpRequestPacket;
 import org.glassfish.grizzly.http.util.Constants;
 import java.io.IOException;
 import java.util.logging.Level;
@@ -77,6 +78,8 @@ import org.glassfish.grizzly.http.util.CharChunk;
 import org.glassfish.grizzly.http.util.DataChunk;
 import org.glassfish.grizzly.http.util.MessageBytes;
 
+import static org.glassfish.grizzly.http.util.DataChunk.Type.*;
+
 /**
  * Mapper, which implements the servlet API mapping rules (which are derived
  * from the HTTP rules).
@@ -801,6 +804,46 @@ public class Mapper {
      * may have a semicolon with extra data followed, which shouldn't be a 
part
      * of mapping process.
      *
+     * @param requestPacket the request packet containing the host 
information
+     *                      to be used by the mapping process.
+     * @param decodedURI   decoded URI
+     * @param mappingData  {@link MappingData} based on the URI.
+     * @param semicolonPos semicolon position. Might be <tt>0</tt> if 
position
+     *                     wasn't resolved yet (so it will be resolved in 
the method),
+     *                     or <tt>-1</tt> if there is no semicolon in the 
URI.
+     * @throws Exception if an error occurs mapping the request
+     */
+    public void mapUriWithSemicolon(final HttpRequestPacket requestPacket,
+                                    final DataChunk decodedURI,
+                                    final MappingData mappingData,
+                                    int semicolonPos) throws Exception {
+        final CharChunk charChunk = decodedURI.getCharChunk();
+        final int oldEnd = charChunk.getEnd();
+
+        if (semicolonPos == 0) {
+            semicolonPos = decodedURI.indexOf(';', 0);
+        }
+
+        DataChunk localDecodedURI = decodedURI;
+        if (semicolonPos >= 0) {
+            charChunk.setEnd(semicolonPos);
+            // duplicate the URI path, because Mapper may corrupt the 
attributes,
+            // which follow the path
+            localDecodedURI = mappingData.tmpMapperDC;
+            localDecodedURI.duplicate(decodedURI);
+        }
+
+
+        map(requestPacket, localDecodedURI, mappingData);
+        charChunk.setEnd(oldEnd);
+    }
+
+
+    /**
+     * Maps the decodedURI to the corresponding HttpHandler, considering 
that URI
+     * may have a semicolon with extra data followed, which shouldn't be a 
part
+     * of mapping process.
+     *
      * @param serverName the server name as described by the Host header.
      * @param decodedURI decoded URI
      * @param mappingData {@link MappingData} based on the URI.
@@ -851,8 +894,9 @@ public class Mapper {
         if (host.isNull()) {
             host.getCharChunk().append(defaultHostName);
         }
-        
-        host.toChars(Constants.DEFAULT_HTTP_CHARSET);
+        if (host.getType() == Bytes || host.getType() == Buffer) {
+            host.toChars(Constants.DEFAULT_HTTP_CHARSET);
+        }
         uri.toChars(null);
         internalMap(host.getCharChunk(), uri.getCharChunk(), mappingData);
 
@@ -860,6 +904,28 @@ public class Mapper {
 
 
     /**
+     * Map the specified host name and URI, mutating the given mapping data.
+     *
+     * @param requestPacket the http request containing host name information
+     *                      used by the mapping process.
+     * @param uri         URI
+     * @param mappingData This structure will contain the result of the 
mapping
+     *                    operation
+     */
+    public void map(final HttpRequestPacket requestPacket, final DataChunk 
uri,
+                    final MappingData mappingData) throws Exception {
+
+        uri.toChars(null);
+        internalMap(((hosts.length > 1)
+                        ? requestPacket.serverName().getCharChunk()
+                        : null),
+                    uri.getCharChunk(),
+                    mappingData);
+
+    }
+
+
+    /**
      * Map the specified URI relative to the context,
      * mutating the given mapping data.
      *
@@ -899,7 +965,10 @@ public class Mapper {
         // Virtual host mapping
         if (mappingData.host == null) {
             Host[] newHosts = hosts;
-            int pos = findIgnoreCase(newHosts, host);
+            int pos = -1;
+            if (host != null && host.isNull()) {
+                pos = findIgnoreCase(newHosts, host);
+            }
             if (pos != -1 && host.equalsIgnoreCase(newHosts[pos].name)) {
                 mappingData.host = newHosts[pos].object;
                 hostPos = pos;--- 
a/modules/http-servlet/src/main/java/org/glassfish/grizzly/servlet/WebappContext.java
+++ 
b/modules/http-servlet/src/main/java/org/glassfish/grizzly/servlet/WebappContext.java
@@ -987,7 +987,7 @@ public class WebappContext implements ServletContext {
 
         try {
             uriDC.setString(uri);
-            dispatcherHelper.mapPath(dd.hostDC, uriDC, mappingData);
+            dispatcherHelper.mapPath(null, uriDC, mappingData);
             if (mappingData.context == null) {
                 return null;
             }
@@ -1187,7 +1187,7 @@ public class WebappContext implements ServletContext {
             } else {
                 uriDC.setString(contextPath + path);
             }
-            dispatcherHelper.mapPath(dd.hostDC, uriDC, mappingData);
+            dispatcherHelper.mapPath(null, uriDC, mappingData);
             if (mappingData.wrapper == null) {
                 return null;
             }
@@ -2193,20 +2193,17 @@ public class WebappContext implements ServletContext {
      */
     private static final class DispatchData {
 
-        public final DataChunk hostDC;
         public final DataChunk uriDC;
         public final DataChunk servletNameDC;
         public final MappingData mappingData;
 
         public DispatchData() {
-            hostDC = DataChunk.newInstance();
             uriDC = DataChunk.newInstance();
             servletNameDC = DataChunk.newInstance();
             mappingData = new MappingData();
         }
 
         public void recycle() {
-            hostDC.recycle();
             uriDC.recycle();
             servletNameDC.recycle();
             mappingData.recycle();--- 
a/modules/http/src/main/java/org/glassfish/grizzly/http/HttpRequestPacket.java
+++ 
b/modules/http/src/main/java/org/glassfish/grizzly/http/HttpRequestPacket.java
@@ -43,6 +43,7 @@ package org.glassfish.grizzly.http;
 import org.glassfish.grizzly.Connection;
 import org.glassfish.grizzly.http.util.DataChunk;
 import org.glassfish.grizzly.http.util.Header;
+import org.glassfish.grizzly.http.util.HttpCodecUtils;
 import org.glassfish.grizzly.http.util.MimeHeaders;
 import org.glassfish.grizzly.http.util.RequestURIRef;
 
@@ -100,6 +101,8 @@ public abstract class HttpRequestPacket extends 
HttpHeader {
 
     private boolean requiresAcknowledgement;
 
+    private boolean hostHeaderParsed;
+
     /**
      * Internal notes associated with this request by Catalina components
      * and event listeners.
@@ -266,15 +269,19 @@ public abstract class HttpRequestPacket extends 
HttpHeader {
      * Host: header.
      */
     public DataChunk serverName() {
+        parseHostHeader();
         return serverNameC;
     }
 
 
+
+
     /**
      * @return Returns the integer value of the Internet Protocol (IP) port 
as
      *  specified in the <code>Host</code> request header.
      */
     public int getServerPort() {
+        parseHostHeader();
         return serverPort;
     }
 
@@ -680,13 +687,26 @@ public abstract class HttpRequestPacket extends 
HttpHeader {
     }
 
 
-    // ------------------------------------------------- Package Private 
Methods
+    // ------------------------------------------------------- Protected 
Methods
 
 
     protected void setResponse(HttpResponsePacket response) {
         this.response = response;
     }
 
+
+    // --------------------------------------------------------- Private 
Methods
+
+
+    private void parseHostHeader() {
+        if (!hostHeaderParsed) {
+            HttpCodecUtils.parseHost(getHeaders().getValue(Header.Host),
+                                     serverNameC,
+                                     this);
+            hostHeaderParsed = true;
+        }
+    }
+
     
     // ---------------------------------------------------------- Nested 
Classes
 --- 
a/modules/http/src/main/java/org/glassfish/grizzly/http/HttpServerFilter.java
+++ 
b/modules/http/src/main/java/org/glassfish/grizzly/http/HttpServerFilter.java
@@ -229,7 +229,7 @@ public class HttpServerFilter extends HttpCodecFilter {
         this.maxRequestHeaders = maxRequestHeaders;
         this.maxResponseHeaders = maxResponseHeaders;
     }
-
+    
     // ----------------------------------------------------------- Parsing
     
     /**
@@ -249,7 +249,7 @@ public class HttpServerFilter extends HttpCodecFilter {
      */
     @Override
     public NextAction handleRead(final FilterChainContext ctx) throws 
IOException {
-        final Buffer input = (Buffer) ctx.getMessage();
+        final Buffer input = ctx.getMessage();
         final Connection connection = ctx.getConnection();
         HttpContext context = HttpContext.get(ctx);
         if (context == null) {
@@ -648,7 +648,7 @@ public class HttpServerFilter extends HttpCodecFilter {
                     uriBC.setStart(uriBCStart + slashPos);
                     uriBC.setEnd(uriBC.getEnd());
                 }
-                hostDC = headers.setValue("host");
+                hostDC = headers.setValue(Header.Host);
                 hostDC.set(uriBC, uriBCStart + pos + 3, uriBCStart + 
slashPos);
             }
 
@@ -663,14 +663,7 @@ public class HttpServerFilter extends HttpCodecFilter {
         final boolean isHttp11 = protocol == Protocol.HTTP_1_1;
         
         // Check host header
-        if (hostDC == null && isHttp11) {
-            state.error = true;
-            return;
-        }
-
-        parseHost(hostDC, request, response, state);
-
-        if (isHttp11 && request.serverName().getLength() == 0) {
+        if (isHttp11 && (hostDC == null || hostDC.getLength() == 0)) {
             state.error = true;
             return;
         }--- 
a/modules/http/src/main/java/org/glassfish/grizzly/http/util/HttpCodecUtils.java
+++ 
b/modules/http/src/main/java/org/glassfish/grizzly/http/util/HttpCodecUtils.java
@@ -47,8 +47,6 @@ import org.glassfish.grizzly.Buffer;
 import org.glassfish.grizzly.Connection;
 import org.glassfish.grizzly.http.HttpCodecFilter;
 import org.glassfish.grizzly.http.HttpRequestPacket;
-import org.glassfish.grizzly.http.HttpResponsePacket;
-import org.glassfish.grizzly.http.ProcessingState;
 import org.glassfish.grizzly.memory.MemoryManager;
 
 /**
@@ -60,9 +58,8 @@ public class HttpCodecUtils {
     private static final int[] DEC = HexUtils.getDecBytes();
     
     public static void parseHost(final DataChunk hostDC,
-                                  final HttpRequestPacket request,
-                                  final HttpResponsePacket response,
-                                  final ProcessingState state) {
+                                 final DataChunk serverNameDC,
+                                 final HttpRequestPacket request) {
 
         if (hostDC == null) {
             // HTTP/1.0
@@ -107,20 +104,19 @@ public class HttpCodecUtils {
                     // 443 - Default HTTPS port
                     request.setServerPort(443);
                 }
-                request.serverName().setBytes(valueB, valueS, valueS + 
valueL);
+
+                serverNameDC.setBytes(valueB, valueS, valueS + valueL);
             } else {
-                request.serverName().setBytes(valueB, valueS, valueS + 
colonPos);
+                serverNameDC.setBytes(valueB, valueS, valueS + colonPos);
 
                 int port = 0;
                 int mult = 1;
                 for (int i = valueL - 1; i > colonPos; i--) {
                     int charValue = DEC[(int) valueB[i + valueS]];
                     if (charValue == -1) {
-                        // Invalid character
-                        state.setError(true);
-                        // 400 - Bad request
-                        HttpStatus.BAD_REQUEST_400.setValues(response);
-                        return;
+                        throw new IllegalStateException(
+                                String.format("Host header %s contained a 
non-decimal value in the port definition.",
+                                              hostDC.toString()));
                     }
                     port = port + (charValue * mult);
                     mult = 10 * mult;
@@ -157,9 +153,9 @@ public class HttpCodecUtils {
                     // 443 - Default HTTPS port
                     request.setServerPort(443);
                 }
-                request.serverName().setBuffer(valueB, valueS, valueS + 
valueL);
+                serverNameDC.setBuffer(valueB, valueS, valueS + valueL);
             } else {
-                request.serverName().setBuffer(valueB, valueS, valueS + 
colonPos);
+                serverNameDC.setBuffer(valueB, valueS, valueS + colonPos);
 
                 int port = 0;
                 int mult = 1;
@@ -167,10 +163,9 @@ public class HttpCodecUtils {
                     int charValue = DEC[(int) valueB.get(i + valueS)];
                     if (charValue == -1) {
                         // Invalid character
-                        state.setError(true);
-                        // 400 - Bad request
-                        HttpStatus.BAD_REQUEST_400.setValues(response);
-                        return;
+                        throw new IllegalStateException(
+                                String.format("Host header %s contained a 
non-decimal value in the port definition.",
+                                              hostDC.toString()));
                     }
                     port = port + (charValue * mult);
                     mult = 10 * mult;--- 
a/modules/spdy/src/main/java/org/glassfish/grizzly/spdy/SpdyHandlerFilter.java
+++ 
b/modules/spdy/src/main/java/org/glassfish/grizzly/spdy/SpdyHandlerFilter.java
@@ -71,7 +71,6 @@ import org.glassfish.grizzly.http.Protocol;
 import org.glassfish.grizzly.http.TransferEncoding;
 import org.glassfish.grizzly.http.util.DataChunk;
 import org.glassfish.grizzly.http.util.Header;
-import org.glassfish.grizzly.http.util.HttpCodecUtils;
 import org.glassfish.grizzly.http.util.HttpStatus;
 import org.glassfish.grizzly.http.util.MimeHeaders;
 import org.glassfish.grizzly.npn.ClientSideNegotiator;
@@ -1070,16 +1069,10 @@ public class SpdyHandlerFilter extends HttpBaseFilter 
{
         final DataChunk hostDC = headers.getValue(Header.Host);
 
         // Check host header
-        if (hostDC == null) {
+        if (hostDC == null || hostDC.getLength() == 0) {
             state.setError(true);
-            return;
         }
 
-        HttpCodecUtils.parseHost(hostDC, request, response, state);
-
-        if (request.serverName().getLength() == 0) {
-            state.setError(true);
-        }
     }
     
     private void prepareOutgoingRequest(final HttpRequestPacket request) 
{--- 
a/modules/websockets/src/main/java/org/glassfish/grizzly/websockets/DefaultWebSocket.java
+++ 
b/modules/websockets/src/main/java/org/glassfish/grizzly/websockets/DefaultWebSocket.java
@@ -257,7 +257,7 @@ public class DefaultWebSocket extends SimpleWebSocket {
 
                 final MappingData mappingData = request.obtainMappingData();
 
-                mapper.mapUriWithSemicolon(request.getRequest().serverName(),
+                mapper.mapUriWithSemicolon(request.getRequest(),
                         decodedURI,
                         mappingData,
                         0);--- 
a/modules/websockets/src/main/java/org/glassfish/grizzly/websockets/WebSocketEngine.java
+++ 
b/modules/websockets/src/main/java/org/glassfish/grizzly/websockets/WebSocketEngine.java
@@ -118,7 +118,7 @@ public class WebSocketEngine {
             // try the Mapper first...
             MappingData data = new MappingData();
             try {
-                mapper.mapUriWithSemicolon(request.serverName(),
+                mapper.mapUriWithSemicolon(request,
                         request.getRequestURIRef().getDecodedRequestURIBC(),
                                     data,
                                     0);





[grizzly~git:d635cb82] [master] Changes for https://java.net/jira/browse/GRIZZLY-1603 (Make HTTP

rlubke 11/07/2013
Terms of Use; Privacy Policy; Copyright ©2013-2015 (revision 20150226.965aeb8)
 
 
Close
loading
Please Confirm
Close