protected NamedList executeMethod()

in solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java [535:729]


  protected NamedList<Object> executeMethod(
      HttpRequestBase method,
      Principal userPrincipal,
      final ResponseParser processor,
      final boolean isV2Api)
      throws SolrServerException {
    method.addHeader("User-Agent", USER_AGENT);

    org.apache.http.client.config.RequestConfig.Builder requestConfigBuilder =
        HttpClientUtil.createDefaultRequestConfigBuilder();
    requestConfigBuilder.setSocketTimeout(soTimeout);
    requestConfigBuilder.setConnectTimeout(connectionTimeout);

    if (followRedirects != null) {
      requestConfigBuilder.setRedirectsEnabled(followRedirects);
    }

    method.setConfig(requestConfigBuilder.build());

    HttpEntity entity = null;
    InputStream respBody = null;
    boolean shouldClose = true;
    try {
      // Execute the method.
      HttpClientContext httpClientRequestContext =
          HttpClientUtil.createNewHttpClientRequestContext();
      if (userPrincipal != null) {
        // Normally the context contains a static userToken to enable reuse resources. However, if a
        // personal Principal object exists, we use that instead, also as a means to transfer
        // authentication information to Auth plugins that wish to intercept the request later
        httpClientRequestContext.setUserToken(userPrincipal);
      }
      final HttpResponse response = httpClient.execute(method, httpClientRequestContext);

      int httpStatus = response.getStatusLine().getStatusCode();

      // Read the contents
      entity = response.getEntity();
      respBody = entity.getContent();
      String mimeType = null;
      Charset charset = null;
      String charsetName = null;

      ContentType contentType = ContentType.get(entity);
      if (contentType != null) {
        mimeType = contentType.getMimeType().trim().toLowerCase(Locale.ROOT);
        charset = contentType.getCharset();

        if (charset != null) {
          charsetName = charset.name();
        }
      }

      // handle some http level checks before trying to parse the response
      switch (httpStatus) {
        case HttpStatus.SC_OK:
        case HttpStatus.SC_BAD_REQUEST:
        case HttpStatus.SC_CONFLICT: // 409
          break;
        case HttpStatus.SC_MOVED_PERMANENTLY:
        case HttpStatus.SC_MOVED_TEMPORARILY:
          if (!followRedirects) {
            throw new SolrServerException(
                "Server at " + getBaseURL() + " sent back a redirect (" + httpStatus + ").");
          }
          break;
        default:
          if (processor == null || contentType == null) {
            throw new SolrClient.RemoteSolrException(
                baseUrl,
                httpStatus,
                "non ok status: "
                    + httpStatus
                    + ", message:"
                    + response.getStatusLine().getReasonPhrase(),
                null);
          }
      }
      if (processor == null || processor instanceof InputStreamResponseParser) {
        // no processor specified, return raw stream
        final var rsp =
            InputStreamResponseParser.createInputStreamNamedList(
                response.getStatusLine().getStatusCode(), respBody);
        rsp.add("closeableResponse", response);
        // Only case where stream should not be closed
        shouldClose = false;
        return rsp;
      }

      final Collection<String> processorSupportedContentTypes = processor.getContentTypes();
      if (!processorSupportedContentTypes.isEmpty()) {
        final Collection<String> processorMimeTypes =
            processorSupportedContentTypes.stream()
                .map(ct -> ContentType.parse(ct).getMimeType().trim().toLowerCase(Locale.ROOT))
                .collect(Collectors.toSet());
        if (!processorMimeTypes.contains(mimeType)) {
          if (isUnmatchedErrorCode(mimeType, httpStatus)) {
            throw new SolrClient.RemoteSolrException(
                baseUrl,
                httpStatus,
                "non ok status: "
                    + httpStatus
                    + ", message:"
                    + response.getStatusLine().getReasonPhrase(),
                null);
          }

          // unexpected mime type
          final String combinedMimeTypes = String.join(", ", processorMimeTypes);
          String prefix =
              "Expected mime type in [" + combinedMimeTypes + "] but got " + mimeType + ". ";
          Charset exceptionCharset = charset != null ? charset : FALLBACK_CHARSET;
          try {
            ByteArrayOutputStream body = new ByteArrayOutputStream();
            respBody.transferTo(body);
            throw new SolrClient.RemoteSolrException(
                baseUrl, httpStatus, prefix + body.toString(exceptionCharset), null);
          } catch (IOException e) {
            throw new SolrClient.RemoteSolrException(
                baseUrl,
                httpStatus,
                "Could not parse response with encoding " + exceptionCharset,
                e);
          }
        }
      }

      NamedList<Object> rsp = null;
      try {
        rsp = processor.processResponse(respBody, charsetName);
      } catch (Exception e) {
        throw new SolrClient.RemoteSolrException(baseUrl, httpStatus, e.getMessage(), e);
      }
      Object error = rsp == null ? null : rsp.get("error");
      if (error != null
          && (isV2Api
              || String.valueOf(getObjectByPath(error, true, errPath))
                  .endsWith("ExceptionWithErrObject"))) {
        throw RemoteExecutionException.create(baseUrl, rsp);
      }
      if (httpStatus != HttpStatus.SC_OK && !isV2Api) {
        NamedList<String> metadata = null;
        String reason = null;
        try {
          if (error != null) {
            reason = (String) Utils.getObjectByPath(error, false, Collections.singletonList("msg"));
            if (reason == null) {
              reason =
                  (String) Utils.getObjectByPath(error, false, Collections.singletonList("trace"));
            }
            Object metadataObj =
                Utils.getObjectByPath(error, false, Collections.singletonList("metadata"));
            if (metadataObj instanceof NamedList) {
              metadata = (NamedList<String>) metadataObj;
            } else if (metadataObj instanceof List) {
              // NamedList parsed as List convert to NamedList again
              List<Object> list = (List<Object>) metadataObj;
              metadata = new NamedList<>(list.size() / 2);
              for (int i = 0; i < list.size(); i += 2) {
                metadata.add((String) list.get(i), (String) list.get(i + 1));
              }
            } else if (metadataObj instanceof Map) {
              metadata = new NamedList((Map) metadataObj);
            }
          }
        } catch (Exception ex) {
        }
        if (reason == null) {
          StringBuilder msg = new StringBuilder();
          msg.append(response.getStatusLine().getReasonPhrase())
              .append("\n\n")
              .append("request: ")
              .append(method.getURI());
          reason = java.net.URLDecoder.decode(msg.toString(), FALLBACK_CHARSET);
        }
        SolrClient.RemoteSolrException rss =
            new SolrClient.RemoteSolrException(baseUrl, httpStatus, reason, null);
        if (metadata != null) rss.setMetadata(metadata);
        throw rss;
      }
      return rsp;
    } catch (ConnectException e) {
      throw new SolrServerException("Server refused connection at: " + getBaseURL(), e);
    } catch (SocketTimeoutException e) {
      throw new SolrServerException(
          "Timeout occurred while waiting response from server at: " + getBaseURL(), e);
    } catch (IOException e) {
      throw new SolrServerException(
          "IOException occurred when talking to server at: " + getBaseURL(), e);
    } finally {
      if (shouldClose) {
        Utils.consumeFully(entity);
      }
    }
  }