com.king.platform.net.http.netty.response.HttpClientResponseHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.king.platform.net.http.netty.response.HttpClientResponseHandler.java

Source

// Copyright (C) king.com Ltd 2015
// https://github.com/king/king-http-client
// Author: Magnus Gustafsson
// License: Apache 2.0, https://raw.github.com/king/king-http-client/LICENSE-APACHE

package com.king.platform.net.http.netty.response;

import com.king.platform.net.http.ResponseBodyConsumer;
import com.king.platform.net.http.netty.HttpRequestContext;
import com.king.platform.net.http.netty.eventbus.Event;
import com.king.platform.net.http.netty.eventbus.RequestEventBus;
import com.king.platform.net.http.netty.util.StringUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import org.slf4j.Logger;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import static org.slf4j.LoggerFactory.getLogger;

public class HttpClientResponseHandler {

    private final Logger logger = getLogger(getClass());
    private final HttpRedirector httpRedirector;

    public HttpClientResponseHandler(HttpRedirector httpRedirector) {
        this.httpRedirector = httpRedirector;
    }

    public void handleResponse(ChannelHandlerContext ctx, Object msg) throws Exception {
        HttpRequestContext httpRequestContext = ctx.channel().attr(HttpRequestContext.HTTP_REQUEST_ATTRIBUTE_KEY)
                .get();

        if (httpRequestContext == null) {
            logger.trace("httpRequestContext is null, msg was {}", msg);
            return;
        }

        NettyHttpClientResponse nettyHttpClientResponse = httpRequestContext.getNettyHttpClientResponse();

        RequestEventBus requestEventBus = nettyHttpClientResponse.getRequestEventBus();

        ResponseBodyConsumer responseBodyConsumer = nettyHttpClientResponse.getResponseBodyConsumer();

        try {

            if (msg instanceof HttpResponse) {
                requestEventBus.triggerEvent(Event.TOUCH);

                logger.trace("read HttpResponse");
                HttpResponse response = (HttpResponse) msg;

                HttpResponseStatus httpResponseStatus = response.getStatus();
                HttpHeaders httpHeaders = response.headers();

                nettyHttpClientResponse.setHttpResponseStatus(httpResponseStatus);
                nettyHttpClientResponse.setHttpHeaders(httpHeaders);

                requestEventBus.triggerEvent(Event.onReceivedStatus, httpResponseStatus);
                requestEventBus.triggerEvent(Event.onReceivedHeaders, httpHeaders);

                httpRequestContext.getTimeRecorder().readResponseHttpHeaders();

                if (httpRequestContext.isFollowRedirects()
                        && httpRedirector.isRedirectResponse(httpResponseStatus)) {
                    httpRedirector.redirectRequest(httpRequestContext, httpHeaders);
                    return;
                }

                if (response.getStatus().code() == 100) {
                    requestEventBus.triggerEvent(Event.WRITE_BODY, ctx);
                    return;
                }

                String contentLength = httpHeaders.get(HttpHeaders.Names.CONTENT_LENGTH);

                String contentType = httpHeaders.get(HttpHeaders.Names.CONTENT_TYPE);
                String charset = StringUtil.substringAfter(contentType, '=');
                if (charset == null) {
                    charset = StandardCharsets.ISO_8859_1.name();
                }

                contentType = StringUtil.substringBefore(contentType, ';');

                if (contentLength != null) {
                    long length = Long.parseLong(contentLength);
                    responseBodyConsumer.onBodyStart(contentType, charset, length);
                } else {
                    responseBodyConsumer.onBodyStart(contentType, charset, 0);
                }

                httpRequestContext.getTimeRecorder().responseBodyStart();

            } else if (msg instanceof HttpContent) {
                logger.trace("read HttpContent");
                requestEventBus.triggerEvent(Event.TOUCH);

                HttpResponseStatus httpResponseStatus = nettyHttpClientResponse.getHttpResponseStatus();
                HttpHeaders httpHeaders = nettyHttpClientResponse.getHttpHeaders();

                if (httpResponseStatus == null || (httpRequestContext.isFollowRedirects()
                        && httpRedirector.isRedirectResponse(httpResponseStatus))) {
                    return;
                }

                if (msg == LastHttpContent.EMPTY_LAST_CONTENT
                        && nettyHttpClientResponse.getHttpResponseStatus().code() == 100) {
                    logger.trace("read EMPTY_LAST_CONTENT with status code 100");
                    return;
                }

                HttpContent chunk = (HttpContent) msg;

                ByteBuf content = chunk.content();

                content.resetReaderIndex();

                int readableBytes = content.readableBytes();

                if (readableBytes > 0) {
                    ByteBuffer byteBuffer = content.nioBuffer();

                    responseBodyConsumer.onReceivedContentPart(byteBuffer);
                    requestEventBus.triggerEvent(Event.onReceivedContentPart, readableBytes, content);

                }

                content.release();

                requestEventBus.triggerEvent(Event.TOUCH);

                if (chunk instanceof LastHttpContent) {

                    responseBodyConsumer.onCompletedBody();

                    requestEventBus.triggerEvent(Event.onReceivedCompleted, httpResponseStatus, httpHeaders);
                    httpRequestContext.getTimeRecorder().responseBodyCompleted();

                    com.king.platform.net.http.HttpResponse httpResponse = new com.king.platform.net.http.HttpResponse(
                            httpResponseStatus.code(), responseBodyConsumer);

                    for (Map.Entry<String, String> entry : httpHeaders.entries()) {
                        httpResponse.addHeader(entry.getKey(), entry.getValue());
                    }

                    requestEventBus.triggerEvent(Event.onHttpResponseDone, httpResponse);

                    requestEventBus.triggerEvent(Event.COMPLETED, httpRequestContext);

                }
            }
        } catch (Throwable e) {
            requestEventBus.triggerEvent(Event.ERROR, httpRequestContext, e);
        }
    }

}