@Override
  public void handleRequest(
      final RestRequest request, final RestChannel channel, final Client client) {
    final GetRequest getRequest =
        new GetRequest(request.param("index"), request.param("type"), request.param("id"));
    getRequest.operationThreaded(true);
    getRequest.refresh(request.paramAsBoolean("refresh", getRequest.refresh()));
    getRequest.routing(
        request.param(
            "routing")); // order is important, set it after routing, so it will set the routing
    getRequest.parent(request.param("parent"));
    getRequest.preference(request.param("preference"));
    getRequest.realtime(request.paramAsBoolean("realtime", getRequest.realtime()));
    // don't get any fields back...
    getRequest.fields(Strings.EMPTY_ARRAY);
    // TODO we can also just return the document size as Content-Length

    client.get(
        getRequest,
        new RestResponseListener<GetResponse>(channel) {
          @Override
          public RestResponse buildResponse(GetResponse response) {
            if (!response.isExists()) {
              return new BytesRestResponse(NOT_FOUND);
            } else {
              return new BytesRestResponse(OK);
            }
          }
        });
  }
  private RestChannelConsumer parseExistingDocPercolate(
      PercolateRequest percolateRequest, RestRequest restRequest, NodeClient client) {
    String index = restRequest.param("index");
    String type = restRequest.param("type");
    percolateRequest.indices(
        Strings.splitStringByCommaToArray(restRequest.param("percolate_index", index)));
    percolateRequest.documentType(restRequest.param("percolate_type", type));

    GetRequest getRequest = new GetRequest(index, type, restRequest.param("id"));
    getRequest.routing(restRequest.param("routing"));
    getRequest.preference(restRequest.param("preference"));
    getRequest.refresh(restRequest.paramAsBoolean("refresh", getRequest.refresh()));
    getRequest.realtime(restRequest.paramAsBoolean("realtime", getRequest.realtime()));
    getRequest.version(RestActions.parseVersion(restRequest));
    getRequest.versionType(
        VersionType.fromString(restRequest.param("version_type"), getRequest.versionType()));

    percolateRequest.getRequest(getRequest);
    percolateRequest.routing(restRequest.param("percolate_routing"));
    percolateRequest.preference(restRequest.param("percolate_preference"));
    percolateRequest.source(restRequest.contentOrSourceParam());

    percolateRequest.indicesOptions(
        IndicesOptions.fromRequest(restRequest, percolateRequest.indicesOptions()));
    return channel -> executePercolate(client, percolateRequest, channel);
  }
  @Override
  protected void doExecute(
      final MultiPercolateRequest request, final ActionListener<MultiPercolateResponse> listener) {
    final ClusterState clusterState = clusterService.state();
    clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ);

    final List<Object> percolateRequests = new ArrayList<>(request.requests().size());
    // Can have a mixture of percolate requests. (normal percolate requests & percolate existing
    // doc),
    // so we need to keep track for what percolate request we had a get request
    final IntArrayList getRequestSlots = new IntArrayList();
    List<GetRequest> existingDocsRequests = new ArrayList<>();
    for (int slot = 0; slot < request.requests().size(); slot++) {
      PercolateRequest percolateRequest = request.requests().get(slot);
      percolateRequest.startTime = System.currentTimeMillis();
      percolateRequests.add(percolateRequest);
      if (percolateRequest.getRequest() != null) {
        existingDocsRequests.add(percolateRequest.getRequest());
        getRequestSlots.add(slot);
      }
    }

    if (!existingDocsRequests.isEmpty()) {
      final MultiGetRequest multiGetRequest = new MultiGetRequest(request);
      for (GetRequest getRequest : existingDocsRequests) {
        multiGetRequest.add(
            new MultiGetRequest.Item(getRequest.index(), getRequest.type(), getRequest.id())
                .routing(getRequest.routing()));
      }

      multiGetAction.execute(
          multiGetRequest,
          new ActionListener<MultiGetResponse>() {

            @Override
            public void onResponse(MultiGetResponse multiGetItemResponses) {
              for (int i = 0; i < multiGetItemResponses.getResponses().length; i++) {
                MultiGetItemResponse itemResponse = multiGetItemResponses.getResponses()[i];
                int slot = getRequestSlots.get(i);
                if (!itemResponse.isFailed()) {
                  GetResponse getResponse = itemResponse.getResponse();
                  if (getResponse.isExists()) {
                    PercolateRequest originalRequest =
                        (PercolateRequest) percolateRequests.get(slot);
                    percolateRequests.set(
                        slot,
                        new PercolateRequest(originalRequest, getResponse.getSourceAsBytesRef()));
                  } else {
                    logger.trace("mpercolate existing doc, item[{}] doesn't exist", slot);
                    percolateRequests.set(
                        slot,
                        new DocumentMissingException(
                            null, getResponse.getType(), getResponse.getId()));
                  }
                } else {
                  logger.trace(
                      "mpercolate existing doc, item[{}] failure {}",
                      slot,
                      itemResponse.getFailure());
                  percolateRequests.set(slot, itemResponse.getFailure());
                }
              }
              new ASyncAction(request, percolateRequests, listener, clusterState).run();
            }

            @Override
            public void onFailure(Throwable e) {
              listener.onFailure(e);
            }
          });
    } else {
      new ASyncAction(request, percolateRequests, listener, clusterState).run();
    }
  }