[grizzly~git:242e0667] [master] + fix issue #1584

  • From: oleksiys@...
  • To: commits@...
  • Subject: [grizzly~git:242e0667] [master] + fix issue #1584
  • Date: Fri, 13 Sep 2013 21:01:04 +0000

Project:    grizzly
Repository: git
Revision:   242e0667abfb6edaed6058d4b9ea97d8497d7656
Author:     oleksiys
Date:       2013-09-13 20:36:36 UTC
Link:       

Log Message:
------------
[master] + fix issue #1584
https://java.net/jira/browse/GRIZZLY-1584
"Error page sometimes is sent with content-length == 0"

+ implement feature #1585
https://java.net/jira/browse/GRIZZLY-1585
"Introduce error page generation API"



Revisions:
----------
242e0667abfb6edaed6058d4b9ea97d8497d7656


Modified Paths:
---------------
extras/grizzly-httpservice/src/main/java/org/glassfish/grizzly/osgi/httpservice/OSGiMainHandler.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpHandler.java
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/HttpServerFilter.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/NetworkListener.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/Request.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/Response.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/ServerFilterConfiguration.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/StaticHttpHandlerBase.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/io/ServerOutputBuffer.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/HtmlHelper.java
modules/http-servlet/src/main/java/org/glassfish/grizzly/servlet/DefaultServlet.java
modules/http-servlet/src/main/java/org/glassfish/grizzly/servlet/ServletHandler.java
modules/http/src/main/java/org/glassfish/grizzly/http/util/HttpStatus.java


Added Paths:
------------
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/DefaultErrorPageGenerator.java
modules/http-server/src/main/java/org/glassfish/grizzly/http/server/ErrorPageGenerator.java
modules/http-server/src/test/java/org/glassfish/grizzly/http/server/ErrorPageTest.java


Diffs:
------
--- 
a/extras/grizzly-httpservice/src/main/java/org/glassfish/grizzly/osgi/httpservice/OSGiMainHandler.java
+++ 
b/extras/grizzly-httpservice/src/main/java/org/glassfish/grizzly/osgi/httpservice/OSGiMainHandler.java
@@ -141,9 +141,8 @@ public class OSGiMainHandler extends HttpHandler 
implements OSGiHandler {
             }
         }
         if (!invoked) {
-            response.setStatus(HttpStatus.NOT_FOUND_404);
             try {
-                customizedErrorPage(request, response);
+                response.sendError(404);
             } catch (Exception e) {
                 logger.warn("Failed to commit 404 status.", e);
             }--- /dev/null
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/DefaultErrorPageGenerator.java
@@ -0,0 +1,67 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the 
License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or 
GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package org.glassfish.grizzly.http.server;
+
+import org.glassfish.grizzly.http.server.util.HtmlHelper;
+import org.glassfish.grizzly.http.util.HttpStatus;
+
+/**
+ * Default Grizzly {@link ErrorPageGenerator}.
+ */
+public class DefaultErrorPageGenerator implements ErrorPageGenerator {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String generate(final Request request,
+            final int status, final String reasonPhrase,
+            final String description, final Throwable exception) {
+        if (status == 404) {
+            return 
HtmlHelper.getErrorPage(HttpStatus.NOT_FOUND_404.getReasonPhrase(),
+                    "Resource identified by path '" + 
request.getRequestURI() + "', does not exist.",
+                    request.getServerFilter().getFullServerName());
+        }
+
+        return HtmlHelper.getExceptionErrorPage(reasonPhrase, description,
+                request.getServerFilter().getFullServerName(),
+                exception);
+    }
+}--- /dev/null
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/ErrorPageGenerator.java
@@ -0,0 +1,69 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the 
License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or 
GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package org.glassfish.grizzly.http.server;
+
+/**
+ * Error page generator interface, which is responsible for generating of an
+ * error page corresponding to the given response status.
+ * 
+ * The <tt>ErrorPageGenerator</tt> is mainly used by {@link 
Response#sendError(int)} and
+ * {@link Response#sendError(int, java.lang.String)} methods.
+ * 
+ * The <tt>ErrorPageGenerator</tt> might be set per
+ * 1) {@link HttpServer}: {@link HttpServer#getServerConfiguration()};
+ * 2) {@link NetworkListener}: {@link 
NetworkListener#setDefaultErrorPageGenerator(org.glassfish.grizzly.http.server.ErrorPageGenerator)};
+ * 3) {@link Response}: {@link 
Response#setErrorPageGenerator(org.glassfish.grizzly.http.server.ErrorPageGenerator)};
+ */
+public interface ErrorPageGenerator {
+    /**
+     * Returns the HTML representation of the error page corresponding to the
+     * given HTTP response status.
+     * 
+     * @param request {@link Request}
+     * @param status response status
+     * @param reasonPhrase response reason phrase
+     * @param description extra description. Might be <tt>null</tt>
+     * @param exception {@link Throwable}, that caused the error. Might be 
<tt>null</tt>
+     * @return 
+     */
+    public String generate(final Request request,
+            final int status, final String reasonPhrase,
+            final String description, final Throwable exception);
+}--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpHandler.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpHandler.java
@@ -42,7 +42,6 @@ package org.glassfish.grizzly.http.server;
 
 import java.io.CharConversionException;
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.util.concurrent.ExecutorService;
 import java.util.logging.Level;
@@ -51,7 +50,6 @@ import org.glassfish.grizzly.Connection;
 import org.glassfish.grizzly.Grizzly;
 import org.glassfish.grizzly.filterchain.FilterChainContext;
 import org.glassfish.grizzly.http.HttpRequestPacket;
-import org.glassfish.grizzly.http.io.OutputBuffer;
 import org.glassfish.grizzly.http.server.util.DispatcherHelper;
 import org.glassfish.grizzly.http.server.util.HtmlHelper;
 import org.glassfish.grizzly.http.server.util.MappingData;
@@ -143,6 +141,7 @@ public abstract class HttpHandler {
      *  from the invocation of {@link #service(Request, Response)}
      */
     boolean doHandle(final Request request, final Response response) throws 
Exception {
+        response.setErrorPageGenerator(getErrorPageGenerator(request));
 
         if (request.requiresAcknowledgement()) {
             if (!sendAcknowledgment(request, response)) {
@@ -175,8 +174,10 @@ public abstract class HttpHandler {
             return runService(request, response);
         } catch (Exception t) {
             LOGGER.log(Level.FINE, "service exception", t);
-            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
-            response.setDetailMessage("Internal Error");
+            HtmlHelper.setErrorAndSendErrorPage(request, response,
+                    response.getErrorPageGenerator(),
+                    500, 
HttpStatus.INTERNAL_SERVER_ERROR_500.getReasonPhrase(),
+                    HttpStatus.INTERNAL_SERVER_ERROR_500.getReasonPhrase(), 
t);
         }
         
         return true;
@@ -219,22 +220,14 @@ public abstract class HttpHandler {
                         LOGGER.log(Level.FINE, "service exception", e);
                         if (!response.isCommitted()) {
                             response.reset();
-                            
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
-                            final ServerFilterConfiguration config =
-                                    httpServerFilter.getConfiguration();
-                            final String name = config.getHttpServerName() + 
' '
-                                    + config.getHttpServerVersion();
-                            response.setDetailMessage("Internal Error");
                             try {
-                                ByteBuffer bb =
-                                        HtmlHelper.getExceptionErrorPage(
-                                                "Internal Error",
-                                                name,
-                                                e);
-                                
response.getOutputBuffer().writeByteBuffer(bb);
-                                response.flush();
+                                HtmlHelper.setErrorAndSendErrorPage(
+                                        request, response,
+                                        response.getErrorPageGenerator(),
+                                        500, 
HttpStatus.INTERNAL_SERVER_ERROR_500.getReasonPhrase(),
+                                        
HttpStatus.INTERNAL_SERVER_ERROR_500.getReasonPhrase(),
+                                        e);
                             } catch (IOException ignored) {
-
                             }
                         }
                         wasSuspended = false;
@@ -362,33 +355,18 @@ public abstract class HttpHandler {
     }
 
     /**
-     * Customize the error page.
-     * @param req The {@link Request} object
-     * @param res The {@link Response} object
-     * @throws Exception
+     * Returns the {@link ErrorPageGenerator}, that might be used
+     * (if an error occurs) during {@link Request} processing.
+     * 
+     * @param request {@link Request}
+     * 
+     * @return Returns the {@link ErrorPageGenerator}, that might be used
+     * (if an error occurs) during {@link Request} processing
      */
-    protected void customizedErrorPage(final Request req,
-                                       final Response res)
-            throws Exception {
-
-        /**
-         * With Grizzly, we just return a 404 with a simple error message.
-         */
-        res.setStatus(HttpStatus.NOT_FOUND_404);
-        final String serverName = req.getServerFilter().getFullServerName();
-        
-        final ByteBuffer bb = HtmlHelper.getErrorPage("Not Found",
-                                                "Resource identified by path 
'" + req.getRequestURI() + "', does not exist.",
-                                                serverName);
-        res.setContentLength(bb.limit());
-        res.setContentType("text/html");
-        OutputBuffer out = res.getOutputBuffer();
-        out.prepareCharacterEncoder();
-        out.write(bb.array(), bb.arrayOffset() + bb.position(), 
bb.remaining());
-        out.close();
+    protected ErrorPageGenerator getErrorPageGenerator(final Request 
request) {
+        return 
request.getHttpFilter().getConfiguration().getDefaultErrorPageGenerator();
     }
-
-
+    
     /**
      * The default implementation will acknowledge an <code>Expect: 
100-Continue</code>
      * with a response line with the status 100 followed by the final 
response--- 
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
@@ -39,6 +39,7 @@
  */
 package org.glassfish.grizzly.http.server;
 
+import java.io.IOException;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentMap;
@@ -173,6 +174,8 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
     @Override
     boolean doHandle(final Request request, final Response response)
             throws Exception {
+        response.setErrorPageGenerator(getErrorPageGenerator(request));
+        
         try {
             final HttpHandler rootHttpHandlerLocal = rootHttpHandler;
             
@@ -206,8 +209,7 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
 
                 return httpHandler.doHandle(request, response);
             } else {
-                response.setStatus(HttpStatus.NOT_FOUND_404);
-                customizedErrorPage(request, response);
+                response.sendError(404);
             }
         } catch (Exception t) {
             try {
@@ -281,11 +283,9 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
                             final HttpHandler a = new HttpHandler() {
 
                                 @Override
-                                public void service(Request request, 
Response response) {
-                                    try {
-                                        customizedErrorPage(request, 
response);
-                                    } catch (Exception ignored) {
-                                    }
+                                public void service(Request request,
+                                        Response response) throws 
IOException {
+                                    response.sendError(404);
                                 }
                             };
                             mapper.addContext(LOCAL_HOST, ctx, a,
@@ -296,12 +296,6 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
                         }
                     }
                     mapper.addWrapper(LOCAL_HOST, ctx, wrapper, httpHandler);
-
-
-    //                String ctx = getContextPath(mapping);
-    //                mapper.addContext(LOCAL_HOST, ctx, httpHandler,
-    //                        new String[]{"index.html", "index.htm"}, null);
-    //                mapper.addWrapper(LOCAL_HOST, ctx, 
mapping.substring(ctx.length()), httpHandler);
                 }
                 
                 // Check if the only one HttpHandler is registered
@@ -442,7 +436,7 @@ public class HttpHandlerChain extends HttpHandler 
implements JmxEventListener {
     }
 
     private String getContextPath(String mapping) {
-        String ctx = "";
+        String ctx;
         int slash = mapping.indexOf("/", 1);
         if (slash != -1) {
             ctx = mapping.substring(0, slash);--- 
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
@@ -670,10 +670,6 @@ public class HttpServer {
 
             final ServerFilterConfiguration config = new 
ServerFilterConfiguration(serverConfig);
 
-            final HttpServerFilter httpServerFilter = new HttpServerFilter(
-                    config,
-                    delayedExecutor);
-            
             if (listener.isSendFileExplicitlyConfigured()) {
                 config.setSendFileEnabled(listener.isSendFileEnabled());
                 fileCache.setFileSendEnabled(listener.isSendFileEnabled());
@@ -683,11 +679,18 @@ public class HttpServer {
                 config.setBackendConfiguration(listener.getBackendConfig());
             }
             
+            if (listener.getDefaultErrorPageGenerator() != null) {
+                
config.setDefaultErrorPageGenerator(listener.getDefaultErrorPageGenerator());
+            }
+            
             config.setTraceEnabled(config.isTraceEnabled() || 
listener.isTraceEnabled());
             
             config.setMaxFormPostSize(listener.getMaxFormPostSize());
             config.setMaxBufferedPostSize(listener.getMaxBufferedPostSize());
             
+            final HttpServerFilter httpServerFilter = new HttpServerFilter(
+                    config,
+                    delayedExecutor);
             httpServerFilter.setHttpHandler(httpHandlerChain);
             
             httpServerFilter.getMonitoringConfig().addProbes(--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpServerFilter.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/HttpServerFilter.java
@@ -40,7 +40,6 @@
 
 package org.glassfish.grizzly.http.server;
 
-import org.glassfish.grizzly.Buffer;
 import org.glassfish.grizzly.Connection;
 import org.glassfish.grizzly.Grizzly;
 import org.glassfish.grizzly.ReadHandler;
@@ -56,11 +55,9 @@ import org.glassfish.grizzly.http.HttpResponsePacket;
 import org.glassfish.grizzly.http.Method;
 import org.glassfish.grizzly.http.server.util.HtmlHelper;
 import org.glassfish.grizzly.http.util.HttpStatus;
-import org.glassfish.grizzly.memory.MemoryManager;
 import org.glassfish.grizzly.utils.DelayedExecutor;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.Level;
@@ -70,7 +67,6 @@ import org.glassfish.grizzly.EmptyCompletionHandler;
 
 import org.glassfish.grizzly.http.util.Header;
 
-import org.glassfish.grizzly.memory.Buffers;
 import org.glassfish.grizzly.monitoring.DefaultMonitoringConfig;
 import org.glassfish.grizzly.monitoring.MonitoringAware;
 import org.glassfish.grizzly.monitoring.MonitoringConfig;
@@ -186,12 +182,6 @@ public class HttpServerFilter extends BaseFilter
                 
                 activeRequestsCounter.incrementAndGet();
                 
-                if (isShuttingDown) { // if we're in the shutting down phase 
- serve shutdown page and exit
-                    onRequestCompleteAndResponseFlushed();
-                    serveShutDownPage(ctx, request, response);
-                    return ctx.getStopAction();
-                }
-                
                 handlerRequest = Request.create();
                 
handlerRequest.parameters.setLimit(config.getMaxRequestParameters());
                 httpRequestInProgress.set(context, handlerRequest);
@@ -211,15 +201,24 @@ public class HttpServerFilter extends BaseFilter
                 try {
                     ctx.setMessage(handlerResponse);
 
-                    if (!config.isPassTraceRequest()
-                            && request.getMethod() == Method.TRACE) {
-                        onTraceRequest(handlerRequest, handlerResponse);
-                    } else {
-                        final HttpHandler httpHandlerLocal = httpHandler;
-                        if (httpHandlerLocal != null) {
-                            wasSuspended = !httpHandlerLocal.doHandle(
-                                    handlerRequest, handlerResponse);
+                    if (!isShuttingDown) {
+                        if (!config.isPassTraceRequest()
+                                && request.getMethod() == Method.TRACE) {
+                            onTraceRequest(handlerRequest, handlerResponse);
+                        } else {
+                            final HttpHandler httpHandlerLocal = httpHandler;
+                            if (httpHandlerLocal != null) {
+                                wasSuspended = !httpHandlerLocal.doHandle(
+                                        handlerRequest, handlerResponse);
+                            }
                         }
+                    } else { // if we're in the shutting down phase - serve 
shutdown page and exit
+                        
handlerResponse.getResponse().getProcessingState().setError(true);
+                        HtmlHelper.setErrorAndSendErrorPage(
+                                handlerRequest, handlerResponse,
+                                config.getDefaultErrorPageGenerator(),
+                                503, 
HttpStatus.SERVICE_UNAVAILABLE_503.getReasonPhrase(),
+                                "The server is being shutting down...", 
null);
                     }
                 } catch (Exception t) {
                     LOGGER.log(Level.WARNING, "Exception during HttpHandler 
invokation", t);
@@ -227,7 +226,12 @@ public class HttpServerFilter extends BaseFilter
                     request.getProcessingState().setError(true);
                     
                     if (!response.isCommitted()) {
-                        serveInternalServerErrorPage(ctx, handlerResponse, 
t);
+                            HtmlHelper.setErrorAndSendErrorPage(
+                                    handlerRequest, handlerResponse,
+                                    config.getDefaultErrorPageGenerator(),
+                                    500, 
HttpStatus.INTERNAL_SERVER_ERROR_500.getReasonPhrase(),
+                                    
HttpStatus.INTERNAL_SERVER_ERROR_500.getReasonPhrase(),
+                                    t);
                     }
                 } catch (Throwable t) {
                     LOGGER.log(Level.WARNING, "Unexpected error", t);
@@ -352,16 +356,6 @@ public class HttpServerFilter extends BaseFilter
 
         final HttpContext context = HttpContext.get(ctx);
         httpRequestInProgress.remove(context);
-        if (!response.isCommitted()
-                && response.getStatus() >= 400
-                && response.getOutputBuffer().getBufferedDataSize() == 0) {
-            final String name = getFullServerName();
-            final ByteBuffer bb = 
HtmlHelper.getErrorPage(response.getStatus() + ' ' + response.getMessage(),
-                                                          
response.getMessage(),
-                                                          name);
-            response.getOutputBuffer().writeByteBuffer(bb);
-            response.flush();
-        }
         response.finish();
         request.onAfterService();
         
@@ -392,48 +386,6 @@ public class HttpServerFilter extends BaseFilter
     }
 
     /**
-     * Serve the shutdown page.
-     */
-    private void serveShutDownPage(final FilterChainContext ctx,
-            final HttpRequestPacket request,
-            final HttpResponsePacket response) throws IOException {
-        request.getProcessingState().setError(true);
-
-        final ByteBuffer b = HtmlHelper.getErrorPage(
-                "The server is being shutting down...",
-                "The server is being shutting down...",
-                getFullServerName());
-        
-        response.setStatus(HttpStatus.SERVICE_UNAVAILABLE_503);
-        response.setContentType("text/html");
-        response.setCharacterEncoding("UTF-8");
-        
-        final MemoryManager mm = ctx.getMemoryManager();
-        final Buffer buf = Buffers.wrap(mm, b);
-        final HttpContent httpContent = HttpContent.builder(response)
-                .last(true)
-                .content(buf)
-                .build();
-        
-        ctx.write(httpContent);
-    }
-
-    private static void serveInternalServerErrorPage(
-            final FilterChainContext ctx, final Response response,
-            final Exception error) throws IOException {
-        
-        final ByteBuffer b = HtmlHelper.getExceptionErrorPage(
-                "Internal Server Error", "Grizzly/2.0", error);
-        response.reset();
-        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
-        response.setContentType("text/html");
-        response.setCharacterEncoding("UTF-8");
-        final MemoryManager mm = ctx.getMemoryManager();
-        final Buffer buf = Buffers.wrap(mm, b);
-        response.getOutputBuffer().writeBuffer(buf);
-    }
-
-    /**
      * Will be called, once HTTP request processing is complete and response 
is
      * flushed.
      */--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/NetworkListener.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/NetworkListener.java
@@ -137,6 +137,11 @@ public class NetworkListener {
      */
     private TCPNIOServerConnection serverConnection;    
     
+    /**
+     * The default error page generator
+     */
+    private ErrorPageGenerator defaultErrorPageGenerator;    
+    
     {
         final TCPNIOTransportBuilder builder = 
TCPNIOTransportBuilder.newInstance();
         final int coresCount = Runtime.getRuntime().availableProcessors() * 
2;
@@ -993,6 +998,23 @@ public class NetworkListener {
         this.sendFileEnabled = sendFileEnabled;
     }
 
+    /**
+     * Returns the <tt>NetworkListener</tt> default {@link 
ErrorPageGenerator}.
+     */
+    public ErrorPageGenerator getDefaultErrorPageGenerator() {
+        return defaultErrorPageGenerator;
+    }
+
+    /**
+     * Sets the <tt>NetworkListener</tt> default {@link ErrorPageGenerator}.
+     * 
+     * @param defaultErrorPageGenerator 
+     */
+    public void setDefaultErrorPageGenerator(
+            final ErrorPageGenerator defaultErrorPageGenerator) {
+        this.defaultErrorPageGenerator = defaultErrorPageGenerator;
+    }
+    
     boolean isSendFileExplicitlyConfigured() {
         return (sendFileEnabled != null);
     }--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/Request.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/Request.java
@@ -485,11 +485,9 @@ public class Request {
 
     // --------------------------------------------------------- Public 
Methods
 
-    public void initialize(/*final Response response,*/
-                           final HttpRequestPacket request,
+    public void initialize(final HttpRequestPacket request,
                            final FilterChainContext ctx,
                            final HttpServerFilter httpServerFilter) {
-//        this.response = response;
         this.request = request;
         this.ctx = ctx;
         this.httpServerFilter = httpServerFilter;
@@ -615,7 +613,6 @@ public class Request {
 
         request.recycle();
         request = null;
-//        response = null;
         ctx = null;
         httpServerFilter = null;
 --- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/Response.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/Response.java
@@ -91,6 +91,7 @@ import org.glassfish.grizzly.http.io.NIOOutputStream;
 import org.glassfish.grizzly.http.io.NIOWriter;
 import org.glassfish.grizzly.http.io.OutputBuffer;
 import org.glassfish.grizzly.http.server.io.ServerOutputBuffer;
+import org.glassfish.grizzly.http.server.util.HtmlHelper;
 import org.glassfish.grizzly.http.util.CharChunk;
 import org.glassfish.grizzly.http.util.CookieSerializerUtils;
 import org.glassfish.grizzly.http.util.FastHttpDateFormat;
@@ -215,12 +216,6 @@ public class Response {
 
 
     /**
-     * The set of Cookies associated with this Response.
-     */
-//    protected final List<Cookie> cookies = new ArrayList<Cookie>(4);
-
-
-    /**
      * Using output stream flag.
      */
     protected boolean usingOutputStream = false;
@@ -253,6 +248,8 @@ public class Response {
     private SuspendStatus suspendStatus;
     private boolean sendFileEnabled;
     
+    private ErrorPageGenerator errorPageGenerator;
+    
     // --------------------------------------------------------- Public 
Methods
 
     public void initialize(final Request request,
@@ -297,7 +294,6 @@ public class Response {
      */
     protected void recycle() {
         delayQueue = null;
-//        suspendedContext.reset();
         outputBuffer.recycle();
         outputStream.recycle();
         writer.recycle();
@@ -305,6 +301,7 @@ public class Response {
         usingWriter = false;
         appCommitted = false;
         error = false;
+        errorPageGenerator = null;
         request = null;
         response.recycle();
         sendFileEnabled = false;
@@ -313,8 +310,6 @@ public class Response {
         suspendState = SuspendState.NONE;
 
         cacheEnabled = false;
-//
-//        ThreadCache.putToCache(CACHE_IDX, this);
     }
 
 
@@ -465,6 +460,23 @@ public class Response {
         return error;
     }
 
+    /**
+     * Returns the {@link ErrorPageGenerator} to be used by
+     * {@link #sendError(int)} or {@link #sendError(int, java.lang.String)}.
+     */
+    public ErrorPageGenerator getErrorPageGenerator() {
+        return errorPageGenerator;
+    }
+
+    /**
+     * Sets the {@link ErrorPageGenerator} to be used by
+     * {@link #sendError(int)} or {@link #sendError(int, java.lang.String)}.
+     * 
+     * @param errorPageGenerator 
+     */
+    public void setErrorPageGenerator(ErrorPageGenerator errorPageGenerator) 
{
+        this.errorPageGenerator = errorPageGenerator;
+    }
 
     // BEGIN S1AS 4878272
     /**
@@ -756,7 +768,7 @@ public class Response {
 
         outputBuffer.reset();
 
-        if(resetWriterStreamFlags) {
+        if (resetWriterStreamFlags) {
             usingOutputStream = false;
             usingWriter = false;
         }
@@ -1223,24 +1235,41 @@ public class Response {
      *  already been committed
      * @exception java.io.IOException if an input/output error occurs
      */
-    public void sendError(int status, String message) throws IOException {
+    public void sendError(final int status, final String message)
+            throws IOException {
         checkResponse();
         if (isCommitted())
             throw new IllegalStateException("Illegal attempt to call 
sendError() after the response has been committed.");
 
         setError();
 
-        response.setStatus(status);
-        response.setReasonPhrase(message);
-        //response.setMessage(message);
-
-        // Clear any data content that has been buffered
-        resetBuffer();
-
+        response.getHeaders().removeHeader(Header.TransferEncoding);
+        response.setContentLanguage(null);
+        response.setContentLengthLong(-1L);
+        response.setChunked(false);
+        response.setCharacterEncoding(null);
+        response.setContentType(null);
+        response.setLocale(null);
+        outputBuffer.reset();
+        usingWriter = false;
+        usingOutputStream = false;
+        
+        setStatus(status, message);
+        
+        String nonNullMsg = message;
+        if (nonNullMsg == null) {
+            final HttpStatus httpStatus = HttpStatus.getHttpStatus(status);
+            if (httpStatus != null && httpStatus.getReasonPhrase() != null) {
+                nonNullMsg = httpStatus.getReasonPhrase();
+            } else {
+                nonNullMsg = "Unknown Error";
+            }
+        }
+        
+        HtmlHelper.sendErrorPage(request, this, getErrorPageGenerator(),
+                status, nonNullMsg, nonNullMsg, null);
+        
         finish();
-        // Cause the response to be finished (from the application 
perspective)
-//        setSuspended(true);
-
     }
 
 
@@ -1300,13 +1329,10 @@ public class Response {
                 }
             }
         } catch (IllegalArgumentException e) {
-            setStatus(HttpStatus.NOT_FOUND_404);
+            sendError(404);
         }
 
         finish();
-        // Cause the response to be finished (from the application 
perspective)
-//        setSuspended(true);
-
     }
 
 --- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/ServerFilterConfiguration.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/ServerFilterConfiguration.java
@@ -77,6 +77,11 @@ public class ServerFilterConfiguration {
      * Default query string encoding (query part of request URI).
      */
     private Charset defaultQueryEncoding;
+    
+    /**
+     * The default error page generator
+     */
+    private ErrorPageGenerator defaultErrorPageGenerator;
 
     public ServerFilterConfiguration() {
         this("Grizzly", Grizzly.getDotedVersion());
@@ -86,9 +91,11 @@ public class ServerFilterConfiguration {
         this.httpServerName = serverName;
         this.httpServerVersion = serverVersion;
         configureSendFileSupport();
+        
+        defaultErrorPageGenerator = new DefaultErrorPageGenerator();
     }
 
-    public ServerFilterConfiguration(ServerFilterConfiguration 
configuration) {
+    public ServerFilterConfiguration(final ServerFilterConfiguration 
configuration) {
         this.httpServerName = configuration.httpServerName;
         this.httpServerVersion = configuration.httpServerVersion;
         this.sendFileEnabled = configuration.sendFileEnabled;
@@ -100,6 +107,7 @@ public class ServerFilterConfiguration {
         this.maxFormPostSize = configuration.maxFormPostSize;
         this.maxBufferedPostSize = configuration.maxBufferedPostSize;
         this.defaultQueryEncoding = configuration.defaultQueryEncoding;
+        this.defaultErrorPageGenerator = 
configuration.defaultErrorPageGenerator;
     }
     
     /**
@@ -361,6 +369,23 @@ public class ServerFilterConfiguration {
     public void setDefaultQueryEncoding(final Charset defaultQueryEncoding) {
         this.defaultQueryEncoding = defaultQueryEncoding;
     }
+
+    /**
+     * Returns the default {@link ErrorPageGenerator}.
+     */
+    public ErrorPageGenerator getDefaultErrorPageGenerator() {
+        return defaultErrorPageGenerator;
+    }
+
+    /**
+     * Sets the default {@link ErrorPageGenerator}.
+     * 
+     * @param defaultErrorPageGenerator 
+     */
+    public void setDefaultErrorPageGenerator(
+            final ErrorPageGenerator defaultErrorPageGenerator) {
+        this.defaultErrorPageGenerator = defaultErrorPageGenerator;
+    }
     
     // --------------------------------------------------------- Private 
Methods
 --- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/StaticHttpHandlerBase.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/StaticHttpHandlerBase.java
@@ -270,8 +270,7 @@ public abstract class StaticHttpHandlerBase extends 
HttpHandler {
      */
     protected void onMissingResource(final Request request, final Response 
response)
             throws Exception {
-        response.setStatus(HttpStatus.NOT_FOUND_404);
-        customizedErrorPage(request, response);
+        response.sendError(404);
     }
 
     /**--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/io/ServerOutputBuffer.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/io/ServerOutputBuffer.java
@@ -47,7 +47,6 @@ import org.glassfish.grizzly.http.io.OutputBuffer;
 import org.glassfish.grizzly.http.server.Response;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.logging.Level;
 
 public class ServerOutputBuffer extends OutputBuffer {--- 
a/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/HtmlHelper.java
+++ 
b/modules/http-server/src/main/java/org/glassfish/grizzly/http/server/util/HtmlHelper.java
@@ -42,10 +42,7 @@ package org.glassfish.grizzly.http.server.util;
 
 import java.io.IOException;
 import java.io.Writer;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
+import org.glassfish.grizzly.http.server.ErrorPageGenerator;
 import org.glassfish.grizzly.http.server.Request;
 import org.glassfish.grizzly.http.server.Response;
 import org.glassfish.grizzly.http.util.HttpStatus;
@@ -69,47 +66,77 @@ public class HtmlHelper{
             "HR {color : #999966;}";
 
     /**
-     * <code>CharBuffer</code> used to store the HTML response, containing
-     * the headers and the body of the response.
+     * Generate and send an error page for the given HTTP response status.
+     * Unlike {@link 
#setErrorAndSendErrorPage(org.glassfish.grizzly.http.server.Request, 
org.glassfish.grizzly.http.server.Response, 
org.glassfish.grizzly.http.server.ErrorPageGenerator, int, java.lang.String, 
java.lang.String, java.lang.Throwable)},
+     * this method doesn't change the {@link Response} status code and 
reason phrase.
+     * 
+     * @param request
+     * @param response
+     * @param generator
+     * @param status
+     * @param reasonPhrase
+     * @param description
+     * @param exception
+     * 
+     * @throws IOException 
      */
-    private static CharBuffer reponseBuffer = CharBuffer.allocate(4096);
-
-
-    /**
-     * Encoder used to encode the HTML response
-     */
-    private static CharsetEncoder encoder =
-                                          
Charset.forName("UTF-8").newEncoder();
-
-
+    public static void sendErrorPage(
+            final Request request, final Response response,
+            final ErrorPageGenerator generator,
+            final int status, final String reasonPhrase,
+            final String description, final Throwable exception) throws 
IOException {
+        
+        if (generator != null && !response.isCommitted() &&
+                response.getOutputBuffer().getBufferedDataSize() == 0) {
+            final String errorPage = generator.generate(request, status,
+                    reasonPhrase, description, exception);
+            
+            final Writer writer = response.getWriter();
+            
+            if (errorPage != null) {
+                response.setContentType("text/html");
+                writer.write(errorPage);
+            }
+            writer.close();
+        }
+    }
+    
     /**
-     *
-     * @return A {@link ByteBuffer} containing the HTTP response.
+     * Generate and send an error page for the given HTTP response status.
+     * Unlike {@link 
#setErrorAndSendErrorPage(org.glassfish.grizzly.http.server.Request, 
org.glassfish.grizzly.http.server.Response, 
org.glassfish.grizzly.http.server.ErrorPageGenerator, int, java.lang.String, 
java.lang.String, java.lang.Throwable)},
+     * this method does change the {@link Response} status code and reason 
phrase.
+     * 
+     * @param request
+     * @param response
+     * @param generator
+     * @param status
+     * @param reasonPhrase
+     * @param description
+     * @param exception
+     * 
+     * @throws IOException 
      */
-    public synchronized static ByteBuffer getErrorPage(String headerMessage,
-                                                       String message,
-                                                       String serverName)
-    throws IOException {
-
-        String body = prepareBody(headerMessage, message, serverName);
-        reponseBuffer.clear();
-        reponseBuffer.put(body);
-        reponseBuffer.flip();
-        return encoder.encode(reponseBuffer);
-
-    }
-
-
-    public synchronized static ByteBuffer getExceptionErrorPage(String 
message,
-                                                                String 
serverName,
-                                                                Throwable t)
-    throws IOException {
-        String body = prepareExceptionBody(message, serverName, t);
-        reponseBuffer.clear();
-        reponseBuffer.put(body);
-        reponseBuffer.flip();
-        return encoder.encode(reponseBuffer);
-
+    public static void setErrorAndSendErrorPage(
+            final Request request, final Response response,
+            final ErrorPageGenerator generator,
+            final int status, final String reasonPhrase,
+            final String description, final Throwable exception) throws 
IOException {
+        
+        response.setStatus(status, reasonPhrase);
+        
+        if (generator != null && !response.isCommitted() &&
+                response.getOutputBuffer().getBufferedDataSize() == 0) {
+            final String errorPage = generator.generate(request, status,
+                    reasonPhrase, description, exception);
+            
+            final Writer writer = response.getWriter();
+            
+            if (errorPage != null) {
+                response.setContentType("text/html");
+                writer.write(errorPage);
+            }
+            writer.close();
+        }
     }
 
     public static void writeTraceMessage(final Request request,
@@ -128,11 +155,27 @@ public class HtmlHelper{
             }
         }
     }
-    
+
+    /**
+     *
+     * @return A {@link String} containing the HTTP response.
+     */
+    public static String getErrorPage(String headerMessage,
+            String message, String serverName) {
+        return prepareBody(headerMessage, message, serverName);
+    }
+
+
+    public static String getExceptionErrorPage(String headerMessage,
+            String message, String serverName, Throwable t) {
+        return prepareExceptionBody(headerMessage, message, serverName, t);
+    }
+
     /**
      * Prepare the HTTP body containing the error messages.
      */
-    private static String prepareBody(String headerMessage, String message, 
String serverName){
+    private static String prepareBody(String headerMessage, String message,
+            String serverName) {
         final StringBuilder sb = new StringBuilder();
 
         sb.append("<html><head><title>");
@@ -155,13 +198,13 @@ public class HtmlHelper{
 
 
     @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"})
-    private static String prepareExceptionBody(String message,
-                                               String serverName,
-                                               Throwable t) {
+    private static String prepareExceptionBody(String headerMessage,
+            String message, String serverName, Throwable t) {
 
         if (t == null) {
-            throw new IllegalArgumentException();
+            return prepareBody(headerMessage, message, serverName);
         }
+        
         Throwable rootCause = getRootCause(t);
 
         StackTraceElement[] elements = t.getStackTrace();
@@ -175,10 +218,10 @@ public class HtmlHelper{
         if (rootCause != null) {
             formatStackElements(rootCauseElements, rootBuilder);
         }
-        String exMessage = t.getMessage();
-        if (exMessage == null) {
-            exMessage = t.toString();
-        }
+        
+        final String exMessage = t.getMessage() != null ?
+                t.getMessage() : t.toString();
+        
         StringBuilder sb = new StringBuilder();
         sb.append("<html><head><title>");
         sb.append(serverName);
@@ -188,7 +231,7 @@ public class HtmlHelper{
         sb.append("--></style> ");
         sb.append("</head><body>");
         sb.append("<div class=\"header\">");
-        sb.append(message);
+        sb.append(headerMessage);
         sb.append("</div>");
         sb.append("<div class=\"body\">");
         sb.append("<b>").append(exMessage).append("</b>");--- /dev/null
+++ 
b/modules/http-server/src/test/java/org/glassfish/grizzly/http/server/ErrorPageTest.java
@@ -0,0 +1,266 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the 
License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or 
GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package org.glassfish.grizzly.http.server;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.grizzly.Buffer;
+import org.glassfish.grizzly.Connection;
+import org.glassfish.grizzly.Grizzly;
+import org.glassfish.grizzly.filterchain.BaseFilter;
+import org.glassfish.grizzly.filterchain.FilterChainBuilder;
+import org.glassfish.grizzly.filterchain.FilterChainContext;
+import org.glassfish.grizzly.filterchain.NextAction;
+import org.glassfish.grizzly.filterchain.TransportFilter;
+import org.glassfish.grizzly.http.HttpClientFilter;
+import org.glassfish.grizzly.http.HttpContent;
+import org.glassfish.grizzly.http.HttpPacket;
+import org.glassfish.grizzly.http.HttpRequestPacket;
+import org.glassfish.grizzly.http.HttpResponsePacket;
+import org.glassfish.grizzly.http.Method;
+import org.glassfish.grizzly.http.Protocol;
+import org.glassfish.grizzly.impl.FutureImpl;
+import org.glassfish.grizzly.impl.SafeFutureImpl;
+import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
+import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
+import org.glassfish.grizzly.utils.ChunkingFilter;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * Test the error page generation.
+ */
+public class ErrorPageTest {
+    private static final int PORT = 18906;
+    
+    @Test
+    public void testNoPage() throws Exception {
+        final HttpPacket request = createRequest("/index.html", null);
+        final HttpContent responseContent = doTest(request, 10, new 
HttpHandler() {
+
+            @Override
+            public void service(Request request, Response response) throws 
Exception {
+                response.setStatus(500);
+            }
+        });
+
+        final HttpResponsePacket responsePacket =
+                (HttpResponsePacket) responseContent.getHttpHeader();
+        assertEquals(500, responsePacket.getStatus());
+        assertEquals(0, responsePacket.getContentLength());
+        assertFalse(responseContent.getContent().hasRemaining());
+    }
+    
+    @Test
+    public void testSendError() throws Exception {
+        final HttpPacket request = createRequest("/index.html", null);
+        final HttpContent responseContent = doTest(request, 10, new 
HttpHandler() {
+
+            @Override
+            public void service(Request request, Response response) throws 
Exception {
+                response.sendError(500);
+            }
+        });
+
+        final HttpResponsePacket responsePacket =
+                (HttpResponsePacket) responseContent.getHttpHeader();
+        assertEquals(500, responsePacket.getStatus());
+        assertTrue(responseContent.getContent().hasRemaining());
+    }
+    
+    @Test
+    public void testUncaughtException() throws Exception {
+        final HttpPacket request = createRequest("/index.html", null);
+        final HttpContent responseContent = doTest(request, 10, new 
HttpHandler() {
+
+            @Override
+            public void service(Request request, Response response) throws 
Exception {
+                throw new IOException("TestError");
+            }
+        });
+
+        final HttpResponsePacket responsePacket =
+                (HttpResponsePacket) responseContent.getHttpHeader();
+        assertEquals(500, responsePacket.getStatus());
+        assertTrue(responseContent.getContent().hasRemaining());
+        
+        String errorPage = responseContent.getContent().toStringContent();
+        System.out.println(errorPage);
+        assertTrue(errorPage.contains("TestError"));
+        assertTrue(errorPage.contains("service")); // check the stacktrace
+    }
+    
+    
+    private HttpPacket createRequest(String uri, Map<String, String> 
headers) {
+
+        HttpRequestPacket.Builder b = HttpRequestPacket.builder();
+        
b.method(Method.GET).protocol(Protocol.HTTP_1_1).uri(uri).header("Host", 
"localhost:" + PORT);
+        if (headers != null) {
+            for (Map.Entry<String, String> entry : headers.entrySet()) {
+                b.header(entry.getKey(), entry.getValue());
+            }
+        }
+
+        return b.build();
+    }
+    
+    private HttpContent doTest(
+            final HttpPacket request,
+            final int timeout,
+            final HttpHandler... httpHandlers)
+            throws Exception {
+
+        final TCPNIOTransport clientTransport =
+                TCPNIOTransportBuilder.newInstance().build();
+        final HttpServer server = createWebServer(httpHandlers);
+        try {
+            final FutureImpl<HttpContent> testResultFuture = 
SafeFutureImpl.create();
+
+            server.start();
+            FilterChainBuilder clientFilterChainBuilder = 
FilterChainBuilder.stateless();
+            clientFilterChainBuilder.add(new TransportFilter());
+            client
[truncated due to length]



[grizzly~git:242e0667] [master] + fix issue #1584

oleksiys 09/13/2013
Terms of Use; Privacy Policy; Copyright ©2013-2014 (revision 20140418.2d69abc)
 
 
Close
loading
Please Confirm
Close