Home / Class/ HttpServerKeepAliveHandler Class — netty Architecture

HttpServerKeepAliveHandler Class — netty Architecture

Architecture documentation for the HttpServerKeepAliveHandler class in HttpServerKeepAliveHandler.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  08219795_24b6_3fff_1446_c9792531660c["HttpServerKeepAliveHandler"]
  bb5713d4_7022_035f_23dd_140380ed2dfa["HttpServerKeepAliveHandler.java"]
  08219795_24b6_3fff_1446_c9792531660c -->|defined in| bb5713d4_7022_035f_23dd_140380ed2dfa
  8a7331c0_8538_53a5_4f8d_af6ea5f3b2e2["channelRead()"]
  08219795_24b6_3fff_1446_c9792531660c -->|method| 8a7331c0_8538_53a5_4f8d_af6ea5f3b2e2
  db8fa580_b26b_c3cb_8f82_220d29371c8b["write()"]
  08219795_24b6_3fff_1446_c9792531660c -->|method| db8fa580_b26b_c3cb_8f82_220d29371c8b
  a6374c00_c860_8572_b173_8706804dfb6e["trackResponse()"]
  08219795_24b6_3fff_1446_c9792531660c -->|method| a6374c00_c860_8572_b173_8706804dfb6e
  0fc97c94_f864_244f_c666_b10e832aaf95["shouldKeepAlive()"]
  08219795_24b6_3fff_1446_c9792531660c -->|method| 0fc97c94_f864_244f_c666_b10e832aaf95
  f90d5a22_63aa_2c1b_2232_c23c91dfad4a["isSelfDefinedMessageLength()"]
  08219795_24b6_3fff_1446_c9792531660c -->|method| f90d5a22_63aa_2c1b_2232_c23c91dfad4a
  c0e2636f_edd9_86b7_13b8_ef3bde47c463["isInformational()"]
  08219795_24b6_3fff_1446_c9792531660c -->|method| c0e2636f_edd9_86b7_13b8_ef3bde47c463
  e02b7ffd_94d2_eb03_5dbd_61e0353f04f0["isMultipart()"]
  08219795_24b6_3fff_1446_c9792531660c -->|method| e02b7ffd_94d2_eb03_5dbd_61e0353f04f0

Relationship Graph

Source Code

codec-http/src/main/java/io/netty/handler/codec/http/HttpServerKeepAliveHandler.java lines 47–128

public class HttpServerKeepAliveHandler extends ChannelDuplexHandler {
    private static final String MULTIPART_PREFIX = "multipart";

    private boolean persistentConnection = true;
    // Track pending responses to support client pipelining: https://tools.ietf.org/html/rfc7230#section-6.3.2
    private int pendingResponses;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // read message and track if it was keepAlive
        if (msg instanceof HttpRequest) {
            final HttpRequest request = (HttpRequest) msg;
            if (persistentConnection) {
                pendingResponses += 1;
                persistentConnection = isKeepAlive(request);
            }
        }
        super.channelRead(ctx, msg);
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        // modify message on way out to add headers if needed
        if (msg instanceof HttpResponse) {
            final HttpResponse response = (HttpResponse) msg;
            trackResponse(response);
            // Assume the response writer knows if they can persist or not and sets isKeepAlive on the response
            if (!isKeepAlive(response) || !isSelfDefinedMessageLength(response)) {
                // No longer keep alive as the client can't tell when the message is done unless we close connection
                pendingResponses = 0;
                persistentConnection = false;
            }
            // Server might think it can keep connection alive, but we should fix response header if we know better
            if (!shouldKeepAlive()) {
                setKeepAlive(response, false);
            }
        }
        if (msg instanceof LastHttpContent && !shouldKeepAlive()) {
            promise = promise.unvoid().addListener(ChannelFutureListener.CLOSE);
        }
        super.write(ctx, msg, promise);
    }

    private void trackResponse(HttpResponse response) {
        if (!isInformational(response)) {
            pendingResponses -= 1;
        }
    }

    private boolean shouldKeepAlive() {
        return pendingResponses != 0 || persistentConnection;
    }

    /**
     * Keep-alive only works if the client can detect when the message has ended without relying on the connection being
     * closed.
     * <p>
     * <ul>
     *     <li>See <a href="https://tools.ietf.org/html/rfc7230#section-6.3"/></li>
     *     <li>See <a href="https://tools.ietf.org/html/rfc7230#section-3.3.2"/></li>
     *     <li>See <a href="https://tools.ietf.org/html/rfc7230#section-3.3.3"/></li>
     * </ul>
     *
     * @param response The HttpResponse to check
     *
     * @return true if the response has a self defined message length.
     */
    private static boolean isSelfDefinedMessageLength(HttpResponse response) {
        return isContentLengthSet(response) || isTransferEncodingChunked(response) || isMultipart(response) ||
               isInformational(response) || response.status().code() == HttpResponseStatus.NO_CONTENT.code();
    }

    private static boolean isInformational(HttpResponse response) {
        return response.status().codeClass() == HttpStatusClass.INFORMATIONAL;
    }

    private static boolean isMultipart(HttpResponse response) {
        String contentType = response.headers().get(HttpHeaderNames.CONTENT_TYPE);
        return contentType != null &&
               contentType.regionMatches(true, 0, MULTIPART_PREFIX, 0, MULTIPART_PREFIX.length());
    }

Frequently Asked Questions

What is the HttpServerKeepAliveHandler class?
HttpServerKeepAliveHandler is a class in the netty codebase, defined in codec-http/src/main/java/io/netty/handler/codec/http/HttpServerKeepAliveHandler.java.
Where is HttpServerKeepAliveHandler defined?
HttpServerKeepAliveHandler is defined in codec-http/src/main/java/io/netty/handler/codec/http/HttpServerKeepAliveHandler.java at line 47.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free