Skip to content

Networking, authentication, real-time events, and resilience

A production network layer translates typed application requests into HTTP, owns transport policy, and returns domain-safe results. Views should not construct URLs, decode API shapes, refresh credentials, or decide retries.

Describe an endpoint

struct Endpoint<Response: Decodable & Sendable>: Sendable {
var path: String
var method: HTTPMethod
var query: [URLQueryItem] = []
var body: Data?
}
protocol HTTPTransport: Sendable {
func send(_ request: URLRequest) async throws -> (Data, HTTPURLResponse)
}
struct APIClient: Sendable {
var baseURL: URL
var transport: any HTTPTransport
var credentials: any CredentialProvider
var decoder: JSONDecoder
func send<Response>(_ endpoint: Endpoint<Response>) async throws -> Response {
let request = try await makeRequest(endpoint)
let (data, response) = try await transport.send(request)
try validate(response)
return try decoder.decode(Response.self, from: data)
}
}

Endpoint definitions own path, method, query, and body shape. DTOs decode the wire contract, then an adapter maps them to domain values so API changes do not leak into views.

Refresh once

Store long-lived credentials using the platform’s protected credential facilities, never source files, preferences, fixtures, or logs. When several requests receive an authentication failure, one refresh operation should run while the others await its result. Retry each original request at most once after successful refresh, then surface reauthentication.

Retry by policy

Retry only operations known to be safe and failures known to be transient. Use bounded exponential backoff with jitter, honor server guidance, and stop on cancellation. Mutation requests need an idempotency contract before automatic replay. Decoding errors, authorization failures, and most client errors should fail without a blind retry.

Model pagination and real-time streams

Pagination returns items plus an opaque continuation value. Deduplicate by stable identity and cancel work for abandoned queries. WebSocket or server-event streams need connection state, heartbeat or liveness policy, bounded reconnect, resume position when supported, duplicate handling, and a fallback to ordinary synchronization.

Log request IDs, timing, status categories, and retry decisions. Redact authorization values, cookies, personal content, and response bodies by default.

Validation boundary

The URLSession architecture is source reviewed. No live service, credential refresh, socket, Apple runtime, or account integration was exercised for this lesson.

Series navigation

References

  • URLSession documents Foundation network sessions and tasks.
  • URL Loading System covers requests, responses, caching, authentication, and protocol loading.
  • WebSocket documents Network framework WebSocket connections.