class HttpServerHandler extends SimpleChannelInboundHandler<HttpRequest> {

    public static final FastThreadLocal<WebContext> WEB_CONTEXT_THREAD_LOCAL = new FastThreadLocal<>();

    static final StaticFileHandler staticFileHandler = new StaticFileHandler(WebContext.blade());

    static final RouteMatcher routeMatcher = WebContext.blade().routeMatcher();

    private final RouteMethodHandler routeHandler = new RouteMethodHandler();
    private final Set<String> notStaticUri = new LRUSet<>(128);

    private boolean recordRequestLog() {
        return WebContext.blade().environment()
                .getBoolean(ENV_KEY_REQUEST_LOG, true);
    }

    private boolean enablePerformance() {
        return WebContext.blade().environment()
                .getBoolean(ENV_KEY_PERFORMANCE, false);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpRequest httpRequest) {
        CompletableFuture<HttpRequest> future = CompletableFuture.completedFuture(httpRequest);

        Executor executor = ctx.executor();

        future.thenApplyAsync(req -> buildWebContext(ctx, req), executor)
                .thenApplyAsync(this::executeLogic, executor)
                .thenApplyAsync(this::buildResponse, executor)
                .exceptionally(this::handleException)
                .thenAcceptAsync(msg -> writeResponse(ctx, future, msg), ctx.channel().eventLoop());
    }

    private WebContext buildWebContext(ChannelHandlerContext ctx,
                                       HttpRequest req) {
        return WebContext.create(req, new HttpResponse(), ctx);
    }

    private void writeResponse(ChannelHandlerContext ctx, CompletableFuture<HttpRequest> future, io.netty.handler.codec.http.HttpResponse msg) {
        ctx.writeAndFlush(msg);
        future.complete(null);
    }

    private io.netty.handler.codec.http.HttpResponse handleException(Throwable e) {
        Request request = WebContext.request();
        String method = request.method();
        String uri = request.uri();

        Exception srcException = (Exception) e.getCause().getCause();
        if (srcException instanceof BladeException) {
        } else {
            log500(log, method, uri);
        }
        if (null != WebContext.blade().exceptionHandler()) {
            WebContext.blade().exceptionHandler().handle(srcException);
        } else {
            log.error("", srcException);
        }
        return routeHandler.handleResponse(WebContext.get());
    }

    private io.netty.handler.codec.http.HttpResponse buildResponse(WebContext webContext) {
        WebContext.set(webContext);
        return routeHandler.handleResponse(webContext);
    }

    private WebContext executeLogic(WebContext webContext) {
        try {
            WebContext.set(webContext);
            Request request = webContext.getRequest();
            HttpMethod method = request.httpMethod();
            String uri = request.uri();
            Instant start = Instant.now();

            if (isStaticFile(method, uri)) {
                staticFileHandler.handle(webContext);
                return webContext;
            }

            Route route = routeMatcher.lookupRoute(method.name(), uri);
            if (null != route) {
                webContext.setRoute(route);
            } else {
                throw new NotFoundException(uri);
            }
            routeHandler.handle(webContext);

            if (enablePerformance()) {
                return webContext;
            }

            if (recordRequestLog()) {
                long cost = log200AndCost(log, start, BladeCache.getPaddingMethod(method.name()), uri);
                request.attribute(REQUEST_COST_TIME_ATTR, cost);
            }
            return webContext;
        } catch (Exception e) {
            throw BladeException.wrapper(e);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {<FILL_FUNCTION_BODY>}

    private boolean isStaticFile(HttpMethod method, String uri) {
        if (!HttpMethod.GET.equals(method) || notStaticUri.contains(uri)) {
            return false;
        }

        if (FAVICON_PATH.equals(uri)) {
            return true;
        }

        Set<String> paths = WebContext.blade().staticOptions().getPaths();
        if (paths.stream().noneMatch(s -> s.equals(uri) || uri.startsWith(s))) {
            notStaticUri.add(uri);
            return false;
        }

        return true;
    }

}

        if (!ExceptionHandler.isResetByPeer(cause)) {
            log.error(cause.getMessage(), cause);
            io.netty.handler.codec.http.HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
            ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        }
    
<no_super_class>