private void handleRequest(HttpRequest httpRequest) throws Exception {
    writeCallbacksToVerify.clear();
    request =
        useMockNettyRequest ? new MockNettyRequest(httpRequest, ctx.channel(), nettyMetrics, Collections.emptySet())
            : new NettyRequest(httpRequest, ctx.channel(), nettyMetrics, Collections.emptySet());
    restResponseChannel = new NettyResponseChannel(ctx, nettyMetrics, PERFORMANCE_CONFIG, this.nettyConfig);
    restResponseChannel.setRequest(request);
    restResponseChannel.setHeader(RestUtils.Headers.CONTENT_TYPE, "application/octet-stream");
    TestingUri uri = TestingUri.getTestingURI(request.getUri());
    switch (uri) {
      case Close:
        restResponseChannel.close();
        assertFalse("Request channel is not closed", request.isOpen());
        break;
      case CopyHeaders:
        copyHeaders(httpRequest);
        restResponseChannel.onResponseComplete(null);
        assertFalse("Request channel is not closed", request.isOpen());
        break;
      case ImmediateResponseComplete:
        int chunkCount = httpRequest.headers().getInt(CHUNK_COUNT_HEADER_NAME, -1);
        if (chunkCount > 0) {
          restResponseChannel.onResponseComplete(new RestServiceException(
              "Invalid value for header : [" + CHUNK_COUNT_HEADER_NAME + "]. Can only be 0 for [/" + uri + "]",
              RestServiceErrorCode.BadRequest));
        } else if (chunkCount == 0) {
          restResponseChannel.setHeader(RestUtils.Headers.CONTENT_LENGTH, 0);
        }
        restResponseChannel.onResponseComplete(null);
        assertEquals("ResponseStatus differs from default", ResponseStatus.Ok, restResponseChannel.getStatus());
        assertFalse("Request channel is not closed", request.isOpen());
        break;
      case FillWriteBuffer:
        WriteBufferWaterMark writeBufferWaterMark = new WriteBufferWaterMark(1, 2);
        ctx.channel().config().setWriteBufferWaterMark(writeBufferWaterMark);
        break;
      case ModifyResponseMetadataAfterWrite:
        restResponseChannel.write(ByteBuffer.wrap(new byte[0]), null);
        restResponseChannel.setHeader(RestUtils.Headers.CONTENT_TYPE, "application/octet-stream");
        break;
      case MultipleClose:
        restResponseChannel.onResponseComplete(null);
        assertFalse("Request channel is not closed", request.isOpen());
        restResponseChannel.close();
        restResponseChannel.close();
        break;
      case MultipleOnResponseComplete:
        restResponseChannel.onResponseComplete(null);
        assertFalse("Request channel is not closed", request.isOpen());
        restResponseChannel.onResponseComplete(null);
        break;
      case OnResponseCompleteWithRestException:
        onResponseCompleteWithRestException();
        break;
      case OnResponseCompleteWithNonRestException:
        onResponseCompleteWithNonRestException();
        break;
      case CopyHeadersAndOnResponseCompleteWithRestException:
        copyTrackingHeaders(httpRequest);
        onResponseCompleteWithRestException();
        break;
      case CopyHeadersAndOnResponseCompleteWithNonRestException:
        copyTrackingHeaders(httpRequest);
        onResponseCompleteWithNonRestException();
        break;
      case OnResponseCompleteWithEarlyClientTermination:
        restResponseChannel.onResponseComplete(Utils.convertToClientTerminationException(new Exception()));
        assertEquals("ResponseStatus does not reflect error", ResponseStatus.BadRequest,
            restResponseChannel.getStatus());
        assertFalse("Request channel is not closed", request.isOpen());
        break;
      case ResponseFailureMidway:
        ChannelWriteCallback callback = new ChannelWriteCallback();
        callback.setFuture(
            restResponseChannel.write(ByteBuffer.wrap(TestingUri.ResponseFailureMidway.toString().getBytes()),
                callback));
        writeCallbacksToVerify.add(callback);
        restResponseChannel.onResponseComplete(new Exception());
        // this should close the channel and the test will check for that.
        break;
      case ResponseWithContentLength:
        chunkCount = httpRequest.headers().getInt(CHUNK_COUNT_HEADER_NAME, -1);
        if (chunkCount == -1) {
          restResponseChannel.onResponseComplete(
              new RestServiceException("Request should contain header : [" + CHUNK_COUNT_HEADER_NAME + "]",
                  RestServiceErrorCode.BadRequest));
        } else {
          restResponseChannel.setHeader(RestUtils.Headers.CONTENT_LENGTH, chunkCount * CHUNK.length);
          if (chunkCount == 0) {
            // special case check
            callback = new ChannelWriteCallback();
            callback.setFuture(restResponseChannel.write(ByteBuffer.allocate(0), callback));
            writeCallbacksToVerify.add(callback);
          } else {
            for (int i = 0; i < chunkCount; i++) {
              callback = new ChannelWriteCallback();
              callback.setFuture(restResponseChannel.write(ByteBuffer.wrap(CHUNK), callback));
              writeCallbacksToVerify.add(callback);
            }
          }
          restResponseChannel.onResponseComplete(null);
        }
        assertFalse("Request channel is not closed", request.isOpen());
        break;
      case SetNullHeader:
        setNullHeaders();
        break;
      case SetRequest:
        setRequestTest();
        break;
      case SetStatus:
        restResponseChannel.setStatus(ResponseStatus.valueOf(httpRequest.headers().get(STATUS_HEADER_NAME)));
        restResponseChannel.onResponseComplete(null);
        assertFalse("Request channel is not closed", request.isOpen());
        break;
      case WriteAfterClose:
        restResponseChannel.close();
        assertFalse("Request channel is not closed", request.isOpen());
        callback = new ChannelWriteCallback();
        callback.setFuture(
            restResponseChannel.write(ByteBuffer.wrap(TestingUri.WriteAfterClose.toString().getBytes()), callback));
        writeCallbacksToVerify.add(callback);
        break;
      case WriteFailureWithThrowable:
        callback = new ChannelWriteCallback();
        callback.setFuture(
            restResponseChannel.write(ByteBuffer.wrap(TestingUri.WriteFailureWithThrowable.toString().getBytes()),
                callback));
        writeCallbacksToVerify.add(callback);
        break;
      case WriteMoreThanContentLength:
        chunkCount = httpRequest.headers().getInt(CHUNK_COUNT_HEADER_NAME, -1);
        if (chunkCount == -1) {
          restResponseChannel.onResponseComplete(
              new RestServiceException("Request should contain header : [" + CHUNK_COUNT_HEADER_NAME + "]",
                  RestServiceErrorCode.BadRequest));
        } else {
          restResponseChannel.setHeader(RestUtils.Headers.CONTENT_LENGTH, chunkCount * CHUNK.length);
          // write one more chunk than required.
          for (int i = 0; i <= chunkCount; i++) {
            callback = new ChannelWriteCallback();
            callback.setFuture(restResponseChannel.write(ByteBuffer.wrap(CHUNK), callback));
            writeCallbacksToVerify.add(callback);
          }
          restResponseChannel.onResponseComplete(null);
        }
        break;
      case SetFailureReasonInResponse:
        request.setArg(RestUtils.InternalKeys.SEND_FAILURE_REASON, Boolean.TRUE);
        restResponseChannel.onResponseComplete(
            new RestServiceException(TestingUri.SetFailureReasonInResponse.toString(),
                RestServiceErrorCode.InternalServerError));
        break;
      case SetFailureReasonInResponseWithException:
        request.setArg(RestUtils.InternalKeys.SEND_FAILURE_REASON, Boolean.TRUE);
        restResponseChannel.onResponseComplete(new Exception(TestingUri.SetFailureReasonInResponse.toString()));
        break;
    }
  }
Handles a {@link HttpRequest}. If content is awaited, handles some state maintenance. Else handles the request
according to a predefined flow based on the uri.
@param httpRequest the {@link HttpRequest} that needs to be handled.
@throws Exception
ambry-rest/src/test/java/com/github/ambry/rest/NettyResponseChannelTest.java