Example #1
0
 /**
  * Called primarily from HTTPMethod to do the bulk of the execution. Assumes HTTPMethod has
  * inserted its headers into request.
  *
  * @param method
  * @param methoduri
  * @param rb
  * @return Request+Response pair
  * @throws HTTPException
  */
 ExecState execute(HTTPMethod method, URI methoduri, RequestBuilder rb) throws HTTPException {
   this.execution = new ExecState();
   this.requestURI = methoduri;
   AuthScope methodscope = HTTPAuthUtil.uriToAuthScope(methoduri);
   AuthScope target = HTTPAuthUtil.authscopeUpgrade(this.scope, methodscope);
   synchronized (this) { // keep coverity happy
     // Merge Settings;
     Settings merged = HTTPUtil.merge(globalsettings, localsettings);
     if (!this.cachevalid) {
       RequestConfig.Builder rcb = RequestConfig.custom();
       this.cachedconfig = configureRequest(rcb, merged);
       HttpClientBuilder cb = HttpClients.custom();
       configClient(cb, merged);
       setAuthenticationAndProxy(cb);
       this.cachedclient = cb.build();
       rb.setConfig(this.cachedconfig);
       this.cachevalid = true;
     }
   }
   this.execution.request = (HttpRequestBase) rb.build();
   try {
     HttpHost targethost = HTTPAuthUtil.authscopeToHost(target);
     this.execution.response =
         cachedclient.execute(targethost, this.execution.request, this.sessioncontext);
   } catch (IOException ioe) {
     throw new HTTPException(ioe);
   }
   return this.execution;
 }
  public synchronized void shutdown() {
    if (sessions != null) {
      sessions.clear();
      sessions = null;
    }

    if (httpClient != null) {
      try {
        httpClient.close();
      } catch (IOException e) {
        log.warn("Failed to close httpClient object due to: " + e);
      } finally {
        httpClient = null;
      }
    } else {
      log.error("Already shutdown.");
    }
  }
  public void postJsonToPipeline(String endpoint, List docs, int requestId) throws Exception {

    FusionSession fusionSession = null;

    long currTime = System.nanoTime();
    synchronized (this) {
      fusionSession = sessions.get(endpoint);

      // ensure last request within the session timeout period, else reset the session
      if (fusionSession == null
          || (currTime - fusionSession.sessionEstablishedAt) > maxNanosOfInactivity) {
        log.info(
            "Fusion session is likely expired (or soon will be) for endpoint "
                + endpoint
                + ", "
                + "pre-emptively re-setting this session before processing request "
                + requestId);
        fusionSession = resetSession(endpoint);
        if (fusionSession == null)
          throw new IllegalStateException(
              "Failed to re-connect to "
                  + endpoint
                  + " after session loss when processing request "
                  + requestId);
      }
    }

    HttpEntity entity = null;
    try {
      HttpPost postRequest = new HttpPost(endpoint);

      // stream the json directly to the HTTP output
      EntityTemplate et = new EntityTemplate(new JacksonContentProducer(jsonObjectMapper, docs));
      et.setContentType("application/json; charset=utf-8");
      et.setContentEncoding("gzip"); // StandardCharsets.UTF_8.name());
      postRequest.setEntity(et); // new BufferedHttpEntity(et));

      HttpClientContext context = HttpClientContext.create();
      context.setCookieStore(cookieStore);

      HttpResponse response = httpClient.execute(postRequest, context);
      entity = response.getEntity();
      int statusCode = response.getStatusLine().getStatusCode();
      if (statusCode == 401) {
        // unauth'd - session probably expired? retry to establish
        log.warn(
            "Unauthorized error (401) when trying to send request "
                + requestId
                + " to Fusion at "
                + endpoint
                + ", will re-try to establish session");

        // re-establish the session and re-try the request
        try {
          EntityUtils.consume(entity);
        } catch (Exception ignore) {
          log.warn("Failed to consume entity due to: " + ignore);
        } finally {
          entity = null;
        }

        synchronized (this) {
          fusionSession = resetSession(endpoint);
          if (fusionSession == null)
            throw new IllegalStateException(
                "After re-establishing session when processing request "
                    + requestId
                    + ", endpoint "
                    + endpoint
                    + " is no longer active! Try another endpoint.");
        }

        log.info(
            "Going to re-try request "
                + requestId
                + " after session re-established with "
                + endpoint);
        response = httpClient.execute(postRequest, context);
        entity = response.getEntity();
        statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200 || statusCode == 204) {
          log.info(
              "Re-try request " + requestId + " after session timeout succeeded for: " + endpoint);
        } else {
          raiseFusionServerException(endpoint, entity, statusCode, response, requestId);
        }
      } else if (statusCode != 200 && statusCode != 204) {
        raiseFusionServerException(endpoint, entity, statusCode, response, requestId);
      } else {
        // OK!
      }
    } finally {

      if (entity != null) {
        try {
          EntityUtils.consume(entity);
        } catch (Exception ignore) {
          log.warn("Failed to consume entity due to: " + ignore);
        } finally {
          entity = null;
        }
      }
    }
  }
  protected FusionSession establishSession(String url, String user, String password, String realm)
      throws Exception {

    FusionSession fusionSession = new FusionSession();

    if (realm != null) {
      int at = url.indexOf("/api");
      String proxyUrl = url.substring(0, at);
      String sessionApi = proxyUrl + "/api/session?realmName=" + realm;
      String jsonString =
          "{\"username\":\"" + user + "\", \"password\":\"" + password + "\"}"; // TODO: ugly!

      URL sessionApiUrl = new URL(sessionApi);
      String sessionHost = sessionApiUrl.getHost();

      try {
        clearCookieForHost(sessionHost);
      } catch (Exception exc) {
        log.warn("Failed to clear session cookie for " + sessionHost + " due to: " + exc);
      }

      HttpPost postRequest = new HttpPost(sessionApiUrl.toURI());
      postRequest.setEntity(
          new StringEntity(
              jsonString, ContentType.create("application/json", StandardCharsets.UTF_8)));

      HttpClientContext context = HttpClientContext.create();
      context.setCookieStore(cookieStore);

      HttpResponse response = httpClient.execute(postRequest, context);
      HttpEntity entity = response.getEntity();
      try {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200 && statusCode != 201 && statusCode != 204) {
          String body = extractResponseBodyText(entity);
          throw new SolrException(
              SolrException.ErrorCode.getErrorCode(statusCode),
              "POST credentials to Fusion Session API ["
                  + sessionApi
                  + "] failed due to: "
                  + response.getStatusLine()
                  + ": "
                  + body);
        } else if (statusCode == 401) {
          // retry in case this is an expired error
          String body = extractResponseBodyText(entity);
          if (body != null && body.indexOf("session-idle-timeout") != -1) {
            EntityUtils.consume(
                entity); // have to consume the previous entity before re-trying the request

            log.warn(
                "Received session-idle-timeout error from Fusion Session API, re-trying to establish a new session to "
                    + url);
            try {
              clearCookieForHost(sessionHost);
            } catch (Exception exc) {
              log.warn("Failed to clear session cookie for " + sessionHost + " due to: " + exc);
            }

            response = httpClient.execute(postRequest, context);
            entity = response.getEntity();
            statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200 && statusCode != 201 && statusCode != 204) {
              body = extractResponseBodyText(entity);
              throw new SolrException(
                  SolrException.ErrorCode.getErrorCode(statusCode),
                  "POST credentials to Fusion Session API ["
                      + sessionApi
                      + "] failed due to: "
                      + response.getStatusLine()
                      + ": "
                      + body);
            }
          }
        }
      } finally {
        if (entity != null) EntityUtils.consume(entity);
      }
      log.info(
          "Established secure session with Fusion Session API on "
              + url
              + " for user "
              + user
              + " in realm "
              + realm);
    }

    fusionSession.sessionEstablishedAt = System.nanoTime();

    URL fusionUrl = new URL(url);
    String hostAndPort = fusionUrl.getHost() + ":" + fusionUrl.getPort();

    return fusionSession;
  }