private void handleRequestOrResponseComplete() {
            try {
                if (!requestOrResponseComplete) {
                    // This will make this method is called only once after
                    // both request and response are complete.
                    requestOrResponseComplete = true;
                    return;
                }
                if (req.isHttp1WebSocket()) {
                    serverPortMetric.decreaseActiveHttp1WebSocketRequests();
                } else if (protocol.isExplicitHttp1()) {
                    serverPortMetric.decreaseActiveHttp1Requests();
                } else if (protocol.isExplicitHttp2()) {
                    serverPortMetric.decreaseActiveHttp2Requests();
                }

                // NB: logBuilder.endResponse() is called by HttpResponseSubscriber.
                if (!isTransientService) {
                    gracefulShutdownSupport.dec();
                }

                // This callback could be called by `req.abortResponse(cause, cancel)` in `cleanup()`.
                // As `unfinishedRequests` is being iterated, `unfinishedRequests` should not be removed.
                if (!isCleaning) {
                    unfinishedRequests.remove(req);
                }

                if (!isNeedsDisconnection() && responseEncoder instanceof ServerHttp2ObjectEncoder) {
                    ((ServerHttp2ObjectEncoder) responseEncoder)
                            .maybeResetStream(req.streamId(), Http2Error.CANCEL);
                }

                final boolean needsDisconnection = ctx.channel().isActive() &&
                                                   (handledLastRequest || isNeedsDisconnection());
                if (needsDisconnection) {
                    // Graceful shutdown mode: If a connection needs to be closed by `KeepAliveHandler`
                    // such as a max connection age or `ServiceRequestContext.initiateConnectionShutdown()`,
                    // new requests will be ignored and the connection is closed after completing all
                    // unfinished requests.
                    if (protocol.isMultiplex()) {
                        // Initiates channel close, connection will be closed after all streams are closed.
                        ctx.channel().close();
                    } else {
                        // Stop receiving new requests.
                        handledLastRequest = true;
                        if (unfinishedRequests.isEmpty()) {
                            final long closeDelay = Flags.defaultHttp1ConnectionCloseDelayMillis();
                            if (closeDelay == 0) {
                                ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(CLOSE);
                            } else {
                                ctx.channel().eventLoop().schedule(() -> {
                                    if (ctx.channel().isActive()) {
                                        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(CLOSE);
                                    }
                                }, closeDelay, TimeUnit.MILLISECONDS);
                            }
                        }
                    }
                }
            } catch (Throwable t) {
                logger.warn("Unexpected exception:", t);
            }
        }
Sets the 'content-length' header to the response.
core/src/main/java/com/linecorp/armeria/server/HttpServerHandler.java