Class UltiCloudRequests
The framework deliberately never exposes the cloud credential to module code: the session that
holds it is package-private, and no public static member of this package accepts or returns a
TokenEntity (the Phase 16 token-non-exposure rule, enforced by a structural test). Some
module features nevertheless need UltiCloud to know that a request really comes from this server
-- UltiLogin's /panel link is the first. This class is the only way to get that: the
framework attaches the current session's bearer to one connection it opens itself, sends the
request, and returns only the HTTP status and response body.
Allow-list (exact match per method). Only these two requests are made:
POST /auth/magic-link-- create a web login link (post(String, String))GET /auth/magic-link/poll-- poll that link's outcome (get(String, Map))
.., //, \, %, ? or # -- is answered with
UltiCloudRequests.Outcome.PATH_NOT_ALLOWED and no request is made. Query parameters travel only through the
query map. The list grows only by a documented contract change in a framework release; a
module cannot widen it.
The token is never exposed. It is never returned, the framework itself never logs it, it is
never placed in an exception message that reaches the caller or in UltiCloudRequests.Result.toString(), and
no public member of this class or of UltiCloudRequests.Result is typed TokenEntity. Redirects are not
followed, so the bearer is never re-sent to the host a Location header names; a 3xx is
returned to the caller as an ordinary result. One limit lies outside the framework: the JDK's own
HTTP client logger (sun.net.www.protocol.http.HttpURLConnection) prints request headers,
the bearer included, when an operator raises it to FINE or lower. Its default level does
not, and the same applies to every request the framework sends with this credential; do not enable
that logger on a production server.
Threading. Both methods block on network I/O (connect timeout 10 s, read timeout 30 s) and
refuse to run on the server's primary thread with an IllegalStateException. Call them from
an asynchronous task and hop back to the primary thread to act on the result.
Side effects. Besides the single HTTP exchange this class writes nothing: no file, no configuration, no log line.
The order of checks is fixed: primary thread, then path, then session (UltiCloudRequests.Outcome.NOT_CONNECTED
when this server is not logged in to UltiCloud -- for example after /ulticloud logout),
then the HTTP exchange (UltiCloudRequests.Outcome.OK for any completed exchange whatever its status,
UltiCloudRequests.Outcome.IO_ERROR when the exchange could not complete).
- Since:
- 6.3.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumWhat happened to a request.static final classThe result of one call: anUltiCloudRequests.Outcome, and for a completed exchange its status and body. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final intprivate static final StringThe one pathpost(String, String)accepts.private static final String[]Character sequences that are never part of an allowed path, checked before the exact match.private static final StringThe one pathget(String, Map)accepts.private static final int -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate static Stringprivate static StringencodeQuery(Map<String, String> query) private static UltiCloudRequests.Resultstatic UltiCloudRequests.ResultSendsGET <api-url><path>?<query>with this server's UltiCloud bearer.private static booleanstatic UltiCloudRequests.ResultSendsPOST <api-url><path>withjsonBodyand this server's UltiCloud bearer.private static StringreadBody(HttpURLConnection connection, int status) private static voidprivate static String
-
Field Details
-
CREATE_PATH
The one pathpost(String, String)accepts.- See Also:
-
POLL_PATH
The one pathget(String, Map)accepts.- See Also:
-
FORBIDDEN_SEQUENCES
Character sequences that are never part of an allowed path, checked before the exact match. -
CONNECT_TIMEOUT_MS
private static final int CONNECT_TIMEOUT_MS- See Also:
-
READ_TIMEOUT_MS
private static final int READ_TIMEOUT_MS- See Also:
-
-
Constructor Details
-
UltiCloudRequests
private UltiCloudRequests()
-
-
Method Details
-
post
SendsPOST <api-url><path>withjsonBodyand this server's UltiCloud bearer.- Parameters:
path- must be exactly/auth/magic-linkjsonBody- the JSON request body, sent as UTF-8 withContent-Type: application/json; charset=utf-8;nullsends an empty body- Returns:
- the outcome; never
null - Throws:
IllegalStateException- if called on the server's primary thread
-
get
SendsGET <api-url><path>?<query>with this server's UltiCloud bearer.- Parameters:
path- must be exactly/auth/magic-link/pollquery- query parameters, each name and value URL-encoded as UTF-8;nullor empty sends no query string; an entry with anullname is skipped and anullvalue is sent as an empty value- Returns:
- the outcome; never
null - Throws:
IllegalStateException- if called on the server's primary thread
-
requireOffPrimaryThread
private static void requireOffPrimaryThread() -
isAllowed
-
currentBearer
- Returns:
- the current session's access token value, or
nullwhen not connected
-
encodeQuery
-
urlEncode
-
exchange
private static UltiCloudRequests.Result exchange(String method, String pathAndQuery, String bearer, byte[] body) -
readBody
- Throws:
IOException
-