Health API - Swift SDK Documentation
Overview
The Health API provides a simple endpoint to check the health status of the server. It returns basic health information and, when authenticated as a superuser, provides additional diagnostic information about the server state.
Key Features:
- No authentication required for basic health check
- Superuser authentication provides additional diagnostic data
- Lightweight endpoint for monitoring and health checks
- Supports both GET and HEAD methods
Backend Endpoints:
GET /api/health- Check health statusHEAD /api/health- Check health status (HEAD method)
Note: The health endpoint is publicly accessible, but superuser authentication provides additional information.
Authentication
Basic health checks do not require authentication:
import BosBase
let client = try BosBaseClient(baseURLString: "http://127.0.0.1:8090")
// Basic health check (no auth required)
let health: JSONRecord = try await client.health.check()
For additional diagnostic information, authenticate as a superuser:
// Authenticate as superuser for extended health data
try await client
.collection("_superusers")
.authWithPassword(identity: "admin@example.com", password: "password")
let health: JSONRecord = try await client.health.check()
Health Check Response Structure
Basic Response (Guest/Regular User)
[
"code": AnyCodable(200),
"message": AnyCodable("API is healthy."),
"data": AnyCodable([:])
]
Superuser Response
[
"code": AnyCodable(200),
"message": AnyCodable("API is healthy."),
"data": AnyCodable([
"canBackup": AnyCodable(true), // Whether backup operations are allowed
"realIP": AnyCodable("192.168.1.100"), // Real IP address of the client
"requireS3": AnyCodable(false), // Whether S3 storage is required
"possibleProxyHeader": AnyCodable("") // Detected proxy header (if behind reverse proxy)
])
]
Check Health Status
Returns the health status of the API server.
Basic Usage
// Simple health check
let health: JSONRecord = try await client.health.check()
print(health["message"] ?? "") // "API is healthy."
print(health["code"] ?? 0) // 200
With Superuser Authentication
// Authenticate as superuser first
try await client
.collection("_superusers")
.authWithPassword(identity: "admin@example.com", password: "password")
// Get extended health information
let health: JSONRecord = try await client.health.check()
if let data = health["data"]?.value as? JSONRecord {
print(data["canBackup"] ?? false) // true/false
print(data["realIP"] ?? "") // "192.168.1.100"
print(data["requireS3"] ?? false) // false
print(data["possibleProxyHeader"] ?? "") // "" or header name
}
Response Fields
Common Fields (All Users)
| Field | Type | Description |
|---|---|---|
code |
Int | HTTP status code (always 200 for healthy server) |
message |
String | Health status message (“API is healthy.”) |
data |
Dictionary | Health data (empty for non-superusers, populated for superusers) |
Superuser-Only Fields (in data)
| Field | Type | Description |
|---|---|---|
canBackup |
Bool | true if backup/restore operations can be performed, false if a backup/restore is currently in progress |
realIP |
String | The real IP address of the client (useful when behind proxies) |
requireS3 |
Bool | true if S3 storage is required (local fallback disabled), false otherwise |
possibleProxyHeader |
String | Detected proxy header name (e.g., “X-Forwarded-For”, “CF-Connecting-IP”) if the server appears to be behind a reverse proxy, empty string otherwise |
Use Cases
1. Basic Health Monitoring
func checkServerHealth() async throws -> Bool {
do {
let health: JSONRecord = try await client.health.check()
if let code = health["code"]?.value as? Int,
code == 200,
let message = health["message"]?.value as? String,
message == "API is healthy." {
print("✓ Server is healthy")
return true
} else {
print("✗ Server health check failed")
return false
}
} catch {
print("✗ Health check error: \(error)")
return false
}
}
// Use in monitoring
Task {
while true {
let isHealthy = try? await checkServerHealth()
if isHealthy == false {
print("Server health check failed!")
}
try? await Task.sleep(nanoseconds: 60_000_000_000) // Check every minute
}
}
2. Backup Readiness Check
func canPerformBackup() async throws -> Bool {
// Authenticate as superuser
try await client
.collection("_superusers")
.authWithPassword(identity: "admin@example.com", password: "password")
let health: JSONRecord = try await client.health.check()
if let data = health["data"]?.value as? JSONRecord,
let canBackup = data["canBackup"]?.value as? Bool,
canBackup == false {
print("⚠️ Backup operation is currently in progress")
return false
}
print("✓ Backup operations are allowed")
return true
}
// Use before creating backups
if try await canPerformBackup() {
try await client.backups.create(name: "backup.zip")
}
3. Monitoring Dashboard
class HealthMonitor {
let client: BosBaseClient
var isSuperuser = false
init(client: BosBaseClient) {
self.client = client
}
func authenticateAsSuperuser(email: String, password: String) async throws -> Bool {
do {
try await client
.collection("_superusers")
.authWithPassword(identity: email, password: password)
isSuperuser = true
return true
} catch {
print("Superuser authentication failed: \(error)")
return false
}
}
func getHealthStatus() async throws -> [String: Any] {
do {
let health: JSONRecord = try await client.health.check()
var status: [String: Any] = [
"healthy": (health["code"]?.value as? Int) == 200,
"message": health["message"]?.value as? String ?? "",
"timestamp": ISO8601DateFormatter().string(from: Date())
]
if isSuperuser, let data = health["data"]?.value as? JSONRecord {
status["diagnostics"] = [
"canBackup": data["canBackup"]?.value ?? nil,
"realIP": data["realIP"]?.value ?? nil,
"requireS3": data["requireS3"]?.value ?? nil,
"behindProxy": (data["possibleProxyHeader"]?.value as? String) != nil,
"proxyHeader": data["possibleProxyHeader"]?.value ?? nil
]
}
return status
} catch {
return [
"healthy": false,
"error": "\(error)",
"timestamp": ISO8601DateFormatter().string(from: Date())
]
}
}
}
// Usage
let monitor = HealthMonitor(client: client)
try await monitor.authenticateAsSuperuser(email: "admin@example.com", password: "password")
let status = try await monitor.getHealthStatus()
print("Health Status: \(status)")
4. Load Balancer Health Check
// Simple health check for load balancers
func simpleHealthCheck() async throws -> Bool {
do {
let health: JSONRecord = try await client.health.check()
return (health["code"]?.value as? Int) == 200
} catch {
return false
}
}
// Use in server route for load balancer
let isHealthy = try? await simpleHealthCheck()
if isHealthy == true {
// Return 200 OK
} else {
// Return 503 Service Unavailable
}
5. Proxy Detection
func checkProxySetup() async throws -> [String: Any?] {
try await client
.collection("_superusers")
.authWithPassword(identity: "admin@example.com", password: "password")
let health: JSONRecord = try await client.health.check()
let data = health["data"]?.value as? JSONRecord
let proxyHeader = data?["possibleProxyHeader"]?.value as? String
if let proxyHeader = proxyHeader, !proxyHeader.isEmpty {
print("⚠️ Server appears to be behind a reverse proxy")
print(" Detected proxy header: \(proxyHeader)")
print(" Real IP: \(data?["realIP"]?.value ?? "")")
// Provide guidance on trusted proxy configuration
print(" Ensure TrustedProxy settings are configured correctly in admin panel")
} else {
print("✓ No reverse proxy detected (or properly configured)")
}
return [
"behindProxy": proxyHeader != nil && !proxyHeader!.isEmpty,
"proxyHeader": proxyHeader,
"realIP": data?["realIP"]?.value
]
}
Error Handling
func safeHealthCheck() async throws -> [String: Any] {
do {
let health: JSONRecord = try await client.health.check()
return [
"success": true,
"data": health
]
} catch {
// Network errors, server down, etc.
return [
"success": false,
"error": "\(error)",
"code": (error as? ClientResponseError)?.status ?? 0
]
}
}
// Handle different error scenarios
let result = try await safeHealthCheck()
if let success = result["success"] as? Bool, !success {
if let code = result["code"] as? Int, code == 0 {
print("Network error or server unreachable")
} else {
print("Server returned error: \(result["code"] ?? 0)")
}
}
Best Practices
- Monitoring: Use health checks for regular monitoring (e.g., every 30-60 seconds)
- Load Balancers: Configure load balancers to use the health endpoint for health checks
- Pre-flight Checks: Check
canBackupbefore initiating backup operations - Error Handling: Always handle errors gracefully as the server may be down
- Rate Limiting: Don’t poll the health endpoint too frequently (avoid spamming)
- Caching: Consider caching health check results for a few seconds to reduce load
- Logging: Log health check results for troubleshooting and monitoring
- Alerting: Set up alerts for consecutive health check failures
- Superuser Auth: Only authenticate as superuser when you need diagnostic information
- Proxy Configuration: Use
possibleProxyHeaderto detect and configure reverse proxy settings
Response Codes
| Code | Meaning |
|---|---|
| 200 | Server is healthy |
| Network Error | Server is unreachable or down |
Limitations
- No Detailed Metrics: The health endpoint does not provide detailed performance metrics
- Basic Status Only: Returns basic status, not detailed system information
- Superuser Required: Extended diagnostics require superuser authentication
- No Historical Data: Only returns current status, no historical health data
Related Documentation
- Backups API - Using
canBackupto check backup readiness - Authentication - Superuser authentication
- Settings API - Configuring trusted proxy settings