@Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            final FullHttpRequest upgradeReq =
                    new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.OPTIONS, "*");

            // Note: There's no need to fill Connection, Upgrade, and HTTP2-Settings headers here
            //       because they are filled by Http2ClientUpgradeCodec.

            assert remoteAddress != null;

            final String host;
            if (remoteAddress instanceof InetSocketAddress) {
                final InetSocketAddress raddr = (InetSocketAddress) remoteAddress;
                host = ArmeriaHttpUtil.authorityHeader(
                        raddr.getHostString(), raddr.getPort(), (isHttps() ? H1 : H1C).defaultPort());
            } else {
                assert remoteAddress instanceof DomainSocketAddress : remoteAddress;
                host = SystemInfo.hostname();
            }

            upgradeReq.headers().set(HttpHeaderNames.HOST, host);
            upgradeReq.headers().set(HttpHeaderNames.USER_AGENT, UserAgentUtil.USER_AGENT);

            ctx.writeAndFlush(upgradeReq);

            final Http2ResponseDecoder responseDecoder = this.responseDecoder;
            final DecodedHttpResponse res = new DecodedHttpResponse(ctx.channel().eventLoop());

            res.init(responseDecoder.inboundTrafficController());
            res.subscribe(new Subscriber<HttpObject>() {

                private boolean notified;

                @Override
                public void onSubscribe(Subscription s) {
                    s.request(Long.MAX_VALUE);
                }

                @Override
                public void onNext(HttpObject o) {
                    if (notified) {
                        // Discard the first response.
                        return;
                    }

                    notified = true;
                    assert upgradeEvt == UpgradeEvent.UPGRADE_SUCCESSFUL;
                    onUpgradeResponse(ctx, true);
                }

                @Override
                public void onError(Throwable t) {
                    ctx.fireExceptionCaught(t);
                }

                @Override
                public void onComplete() {}
            }, ctx.channel().eventLoop());

            responseDecoder.reserveUnfinishedResponse(Integer.MAX_VALUE);
            final DefaultClientRequestContext reqCtx = new DefaultClientRequestContext(
                    ctx.channel().eventLoop(), Flags.meterRegistry(), H1C, RequestId.random(),
                    com.linecorp.armeria.common.HttpMethod.OPTIONS,
                    REQ_TARGET_ASTERISK, EndpointGroup.of(), ClientOptions.of(),
                    HttpRequest.of(com.linecorp.armeria.common.HttpMethod.OPTIONS, "*"),
                    null, REQUEST_OPTIONS_FOR_UPGRADE_REQUEST, CancellationScheduler.noop(),
                    System.nanoTime(), SystemInfo.currentTimeMicros());

            // NB: No need to set the response timeout because we have session creation timeout.
            responseDecoder.addResponse(null, 0, res, reqCtx, ctx.channel().eventLoop());
            ctx.fireChannelActive();
        }
Sends the initial upgrade request, which is {@code "OPTIONS * HTTP/1.1"}.
core/src/main/java/com/linecorp/armeria/client/HttpClientPipelineConfigurator.java