Skip to content

HTTP Client and Request Handling

The HTTP client layer in glean-powershell is designed as a centralized, low-level abstraction that shields generated cmdlets from the complexities of REST communication, authentication, and error handling. By funneling all network traffic through a small set of private functions, the architecture ensures consistent behavior across all operations, simplifies testing via a single mock point, and guarantees that errors are transformed into structured, terminating PowerShell exceptions. This section details the core components: the raw HTTP wrapper, the request executor that handles URI construction and retries, the query string serializer, the cursor-based pagination engine, and the error resolution logic.

The foundation of the HTTP layer is Invoke-GleanHttp, which serves as the single, clean mock point for the entire runtime 1. It is a thin wrapper around PowerShell’s Invoke-RestMethod that normalizes responses into a consistent { StatusCode, Body } object. Crucially, it sets SkipHttpErrorCheck = $true to prevent Invoke-RestMethod from throwing on non-2xx status codes, allowing the caller to handle HTTP errors explicitly. The function accepts standard HTTP parameters including Uri, Method, Headers, Body, ContentType, Form, and WebSession. It dynamically constructs the argument splat for Invoke-RestMethod, ensuring that Form data takes precedence over Body if both are present, and correctly attaches the WebSession if provided.

Invoke-GleanRequest acts as the single HTTP chokepoint for every generated cmdlet 2. It orchestrates the entire request lifecycle: resolving the connection, building the URI, attaching headers, invoking the API, and handling retries or errors.

The function first retrieves the connection object via Get-GleanConnectionOrThrow. It explicitly rejects Cookie auth mode for typed REST cmdlets, throwing an InvalidOperationException and directing users to Invoke-GleanWebRequest or token-based auth. For token-based auth, Get-GleanHeaders constructs the Authorization header using a Bearer token derived from the connection’s secure string. It also merges default headers from the connection and any user-provided headers, skipping empty or null values.

URIs are built by Get-GleanUri, which combines the base URL, an API-specific prefix (e.g., /rest/api/v1 or /api/index/v1), the path, and query parameters. Path parameters are URL-encoded using [uri]::EscapeDataString and substituted into the path string. The client version is appended as a query parameter if present in the connection object.

The executor implements an idempotent-only retry policy for specific HTTP status codes. If the Idempotent switch is set and the response is a 429 or 503, it retries up to MaxRetries (default 3) times. The delay uses an exponential backoff strategy, capped at 30 seconds: min(2^attempt, 30). Non-idempotent requests or other error codes bypass retry and go directly to error resolution.

Query parameters are serialized by ConvertTo-GleanQueryString, which respects OpenAPI serialization metadata (style/explode) defined in QueryMeta 3. The default style is form with explode=true.

For scalar values, the function URL-encodes the name and value. For enumerable values (arrays/lists), it checks the explode flag. If explode is true, each item is serialized as a separate key-value pair (e.g., name=a&name=b). If explode is false, items are joined by commas (e.g., name=a,b,c). Boolean values are converted to lowercase strings (true/false) before serialization.

Cursor-based pagination is handled by Invoke-GleanPage, which is invoked when the -All switch is used 4. This function relies on per-operation metadata baked into the cmdlet’s Paginate hashtable, which specifies the request cursor field, response cursor field, a “more” flag, and the item collection field.

The pager works by maintaining a cursor variable, initially null. In each iteration, it adds the cursor to the request body if present, then calls Invoke-GleanRequest. It extracts items from the response using the ItemField and adds them to a collected list. The loop continues as long as the MoreField is true or the ResponseCursor is non-null. The function returns either the raw array of pages, the collected items, or both, depending on the -Raw switch and metadata.

Non-success HTTP responses are converted into structured, terminating PowerShell errors by Resolve-GleanError 5. It attempts to parse the response body as JSON if it starts with {. If parsing succeeds, it extracts an error message from common fields like errorMessage, message, error, or detail. It also extracts an error code from errorCode, code, or status.

If no message is found in the body, it defaults to a generic message including the HTTP status code. The function creates an ErrorRecord with an HttpRequestException as the inner exception, using a custom error ID (GleanApiError.<StatusCode>) and category InvalidOperation. The error details include the full context: HTTP status, code, message, method, and URI.