Class CloudHttp

java.lang.Object
com.ultikits.ultitools.utils.CloudHttp

final class CloudHttp extends Object
The single JSON REST exchange the protocol v2 client uses against UltiCloud (/v1/*).

It keeps these exchange rules (the ones the 6.3.0 UltiCloudRequests exchange kept), because the server credential travels through it:

  • No redirect is followed. Following one would re-send the Authorization header to whatever host the Location header names; a 3xx is returned as a status.
  • No exception, log line or CloudHttp.Response.toString() carries a request header. The JDK puts the whole header value into some exception messages (an unchecked IllegalArgumentException for a value with CR or LF), so every failure of the exchange becomes CloudHttp.Outcome.IO_ERROR and the exception itself is dropped.
  • Network failure and HTTP status stay distinct. CloudHttp.Outcome.OK means an exchange completed, whatever its status; the caller reads CloudHttp.Response.status().
  • The host is not caller-controlled. The base URL is the jar's build-time env.yml api-url (HttpRequestUtils.getBaseUrl()); callers pass only a constant path.
Timeouts: connect 10 s, read 15 s. The response body is read from the error stream for a status of 400 or more and capped at 65536 bytes. Retry-After is exposed only in its delta-seconds form (CloudHttp.Response.retryAfterSeconds()).

UltiCloudRequests makes no HTTP request in 6.3.1 (plan 22-17 removed its exchange), so this class is the one REST exchange implementation the framework uses.

Since:
6.3.1
  • Field Details

    • MAX_BODY_BYTES

      static final int MAX_BODY_BYTES
      Upper bound on the bytes read from one response body.
      See Also:
    • CONNECT_TIMEOUT_MS

      private static final int CONNECT_TIMEOUT_MS
      See Also:
    • READ_TIMEOUT_MS

      private static final int READ_TIMEOUT_MS
      See Also:
    • MAX_RETRY_AFTER_SECONDS

      private static final long MAX_RETRY_AFTER_SECONDS
      See Also:
    • MAX_RETRY_AFTER_DIGITS

      private static final int MAX_RETRY_AFTER_DIGITS
      Longest digit string parsed as a Retry-After value; anything longer is clamped.
      See Also:
  • Constructor Details

    • CloudHttp

      private CloudHttp()
  • Method Details

    • postJson

      static CloudHttp.Response postJson(String path, com.google.gson.JsonObject bodyOrNull, String bearerOrNull)
      Sends POST <api-url><path>.
      Parameters:
      path - a constant path beginning with /
      bodyOrNull - the JSON body, sent as UTF-8 with Content-Type: application/json; charset=utf-8; null sends an empty POST without a JSON Content-Type (the JDK may add its default form media type)
      bearerOrNull - the value after Bearer in the Authorization header, or null for a public route
      Returns:
      the outcome; never null
      Throws:
      IllegalStateException - if called on the server's primary thread
    • requireOffPrimaryThread

      private static void requireOffPrimaryThread()
    • baseUrl

      private static String baseUrl()
      Returns:
      the configured base URL without trailing slashes, or null when blank
    • exchange

      private static CloudHttp.Response exchange(String url, byte[] body, String bearer)
    • parseRetryAfter

      static long parseRetryAfter(String header)
      Parameters:
      header - the raw Retry-After value, or null
      Returns:
      the delay in seconds clamped to 0..3600, or -1 when the header is absent or not in delta-seconds form (an HTTP date, a negative number, any other text)
    • readBody

      private static String readBody(HttpURLConnection connection, int status) throws IOException
      Throws:
      IOException