/** * Copyright 2016 LinkedIn Corp. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ package com.github.ambry.rest; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.DefaultHttpContent; import io.netty.handler.codec.http.DefaultHttpResponse; import io.netty.handler.codec.http.DefaultLastHttpContent; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpContent; import io.netty.handler.codec.http.HttpObject; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpUtil; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.LastHttpContent; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Handler to echo the Method type of the request. * Used purely for testing purposes */ public class EchoMethodHandler extends SimpleChannelInboundHandler<HttpObject> { private final Logger logger = LoggerFactory.getLogger(getClass()); public static final String IS_CHUNKED = "is_chunked_header"; public static final String DISCONNECT_URI = "disconnect"; public static final String CLOSE_URI = "close"; private FullHttpResponse response; private HttpResponse httpResponse; private List<HttpContent> httpContentList; private String requestUri; public static final String RESPONSE_HEADER_KEY_PREFIX = "response_Header_Key"; public static final String RESPONSE_HEADER_KEY_1 = RESPONSE_HEADER_KEY_PREFIX + "_1"; public static final String RESPONSE_HEADER_KEY_2 = RESPONSE_HEADER_KEY_PREFIX + "_2"; @Override public void channelRead0(ChannelHandlerContext ctx, HttpObject obj) throws Exception { logger.trace("Reading on channel {}", ctx.channel()); if (obj instanceof HttpRequest) { HttpRequest request = (HttpRequest) obj; logger.trace("Handling incoming request " + request); requestUri = request.uri(); byte[] methodBytes = request.method().toString().getBytes(); if (request.headers().get(IS_CHUNKED) == null || !request.headers().get(IS_CHUNKED).equals("true")) { response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(methodBytes)); updateHeaders(response, request, methodBytes.length); } else { httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); HttpUtil.setTransferEncodingChunked(httpResponse, true); httpContentList = new ArrayList<>(); ByteBuf content = Unpooled.wrappedBuffer(methodBytes); HttpContent httpContent = new DefaultHttpContent(content); httpContentList.add(httpContent); httpContentList.add(httpContent); updateHeaders(httpResponse, request, methodBytes.length); } } else if (obj instanceof LastHttpContent) { if (requestUri.equals(DISCONNECT_URI)) { ctx.disconnect(); } else if (requestUri.equals(CLOSE_URI)) { ctx.close(); } else { if (response != null) { ctx.writeAndFlush(response); } else if (httpResponse != null) { ctx.writeAndFlush(httpResponse); for (HttpContent httpContent : httpContentList) { ctx.writeAndFlush(httpContent); } ctx.writeAndFlush(new DefaultLastHttpContent()); } } } } private void updateHeaders(HttpResponse response, HttpRequest request, int contentLength) { HttpUtil.setContentLength(response, contentLength); if (request.headers().get(RESPONSE_HEADER_KEY_1) != null) { response.headers().set(RESPONSE_HEADER_KEY_1, request.headers().get(RESPONSE_HEADER_KEY_1)); } if (request.headers().get(RESPONSE_HEADER_KEY_2) != null) { response.headers().set(RESPONSE_HEADER_KEY_2, request.headers().get(RESPONSE_HEADER_KEY_2)); } } }