private boolean handleRequest(HttpRequest httpRequest) throws RestServiceException {
    boolean success = true;
    if (responseChannel == null || requestContentFullyReceived) {
      // Once all content associated with a request has been received, this channel is clear to receive new requests.
      // If the client sends a request without waiting for the response, it is possible to screw things up a little
      // but doing so would constitute an error and no proper client would do that.
      long processingStartTime = System.currentTimeMillis();
      resetState();
      nettyMetrics.requestArrivalRate.mark();
      if (!httpRequest.decoderResult().isSuccess()) {
        success = false;
        logger.warn("Decoder failed because of malformed request on channel {}", ctx.channel(),
            httpRequest.decoderResult().cause());
        nettyMetrics.malformedRequestError.inc();
        onRequestAborted(new RestServiceException("Decoder failed because of malformed request",
            RestServiceErrorCode.MalformedRequest));
      } else {
        try {
          // We need to maintain state about the request itself for the subsequent parts (if any) that come in. We will
          // attach content to the request as the content arrives.
          if ((HttpMethod.POST.equals(httpRequest.method()) || HttpMethod.PUT.equals(httpRequest.method()))
              && HttpPostRequestDecoder.isMultipart(httpRequest)) {
            nettyMetrics.multipartPostRequestRate.mark();
            request = new NettyMultipartRequest(httpRequest, ctx.channel(), nettyMetrics,
                nettyConfig.nettyServerDenyListedQueryParams, nettyConfig.nettyMultipartPostMaxSizeBytes);
          } else {
            request =
                new NettyRequest(httpRequest, ctx.channel(), nettyMetrics, nettyConfig.nettyServerDenyListedQueryParams);
          }
          responseChannel.setRequest(request);
          logger.trace("Channel {} now handling request {}", ctx.channel(), request.getUri());
          // We send POST that is not multipart for handling immediately since we expect valid content with it that will
          // be streamed in. In the case of POST that is multipart, all the content has to be received for Netty's
          // decoder and NettyMultipartRequest to work. So it is scheduled for handling when LastHttpContent is received.
          // With any other method that we support, we do not expect any valid content. LastHttpContent is a Netty thing.
          // So we wait for LastHttpContent (throw an error if we don't receive it or receive something else) and then
          // schedule the other methods for handling in handleContent().
          if ((request.getRestMethod().equals(RestMethod.POST) || request.getRestMethod().equals(RestMethod.PUT))
              && !HttpPostRequestDecoder.isMultipart(httpRequest)) {
            requestHandler.handleRequest(request, responseChannel);
          }
        } catch (RestServiceException e) {
          success = false;
          onRequestAborted(e);
        } finally {
          if (request != null) {
            request.getMetricsTracker().nioMetricsTracker.addToRequestProcessingTime(
                System.currentTimeMillis() - processingStartTime);
          }
        }
      }
    } else {
      // We have received a request when we were not expecting one. This shouldn't happen and the channel is closed
      // because it is in a bad state.
      success = false;
      logger.error("New request received when previous request is yet to be fully received on channel {}. Request under"
          + " processing: {}. Unexpected request: {}", ctx.channel(), request.getUri(), httpRequest.uri());
      nettyMetrics.duplicateRequestError.inc();
      onRequestAborted(new RestServiceException("Received request in the middle of another request",
          RestServiceErrorCode.BadRequest));
    }
    return success;
  }
Handles a {@link HttpRequest}.
<p/>
Does some state maintenance for all HTTP methods by creating a {@link RestRequest} wrapping this
{@link HttpRequest}
<p/>
In case of POST, delegates handling of {@link RestRequest} to the {@link RestRequestHandler}.
@param httpRequest the {@link HttpRequest} that needs to be handled.
@return {@code true} if the handling succeeded without problems.
@throws RestServiceException if there is an error handling the current {@link HttpRequest}.
ambry-rest/src/main/java/com/github/ambry/rest/NettyMessageProcessor.java