Back to OSS
swift-api-client
async/await対応の軽量HTTPクライアント - 型安全なAPI通信をSwiftで実現
Swift
http-clientasync-awaitnetworking
swift-api-client
モダンな async/await をサポートした軽量な Swift 製 HTTP API クライアントパッケージ
概要
swift-api-client は、Swift アプリケーションで HTTP API 呼び出しをシンプルかつ型安全に行うためのパッケージです。iOS および macOS プラットフォームに対応し、モダンな並行処理機能をサポートしています。
主な機能
- ✅ モダンな async/await API - Swift 6.0 の並行処理機能をフル活用
- ✅ 型安全なリクエスト/レスポンス - コンパイル時の型チェックで安全性を保証
- ✅ 自動 JSON デコーディング - Codable を使った簡単なレスポンス処理
- ✅ 柔軟なエラーハンドリング - 詳細なエラー情報を提供
- ✅ 認証サポート - トークンプロバイダーによる認証統合
- ✅ HTTP イベントストリーム - 認証エラー・レート制限等の重要イベントをAsyncStreamで通知
- ✅ HTTP ログストリーム - 全リクエスト/レスポンスをAsyncStreamで監視可能
- ✅ ゼロ依存 - 外部ライブラリを使わない軽量設計
- ✅ クロスプラットフォーム - iOS および macOS 対応
必要要件
- iOS 17.0+
- macOS 14.0+
- Swift 6.0+
インストール
Swift Package Manager
Package.swift に以下を追加してください:
dependencies: [
.package(url: "https://github.com/no-problem-dev/swift-api-client.git", from: "1.0.0")
]
または Xcode で:
- File > Add Package Dependencies
- パッケージ URL を入力:
https://github.com/no-problem-dev/swift-api-client.git - バージョンを選択:
1.0.0以降
クイックスタート
最もシンプルな使用例:
import APIClient
// API クライアントを作成
let client = APIClientImpl(baseURL: URL(string: "https://api.example.com")!)
// エンドポイントを定義
let endpoint = APIEndpoint(
path: "/users/123",
method: .get
)
// リクエストを実行
let data = try await client.request(endpoint)
使い方
基本的な GET リクエスト
import APIClient
// レスポンス型を定義
struct User: Codable {
let id: String
let name: String
let email: String
}
// API クライアントを作成
let client = APIClientImpl(baseURL: URL(string: "https://api.example.com")!)
// エンドポイントを定義
let endpoint = APIEndpoint(
path: "/users/123",
method: .get
)
// リクエストを実行してデコード
let user: User = try await client.request(endpoint)
print(user.name)
POST リクエスト(JSON ボディ付き)
struct CreateUserRequest: Codable {
let name: String
let email: String
}
let requestBody = CreateUserRequest(name: "John Doe", email: "john@example.com")
let jsonData = try JSONEncoder().encode(requestBody)
let endpoint = APIEndpoint(
path: "/users",
method: .post,
headers: ["Content-Type": "application/json"],
body: jsonData
)
let newUser: User = try await client.request(endpoint)
クエリパラメータ付きリクエスト
let endpoint = APIEndpoint(
path: "/users",
method: .get,
queryItems: [
URLQueryItem(name: "page", value: "1"),
URLQueryItem(name: "limit", value: "20")
]
)
let users: [User] = try await client.request(endpoint)
エラーハンドリング
do {
let user: User = try await client.request(endpoint)
print("Success: \(user.name)")
} catch APIError.unauthorized {
print("認証エラー")
} catch APIError.networkError(let error) {
print("ネットワークエラー: \(error.localizedDescription)")
} catch APIError.httpError(let statusCode, _) {
print("HTTP エラー: \(statusCode)")
} catch APIError.decodingError(let error) {
print("デコードエラー: \(error.localizedDescription)")
} catch {
print("予期しないエラー: \(error)")
}
認証トークンの使用
// トークンプロバイダーを実装
class MyTokenProvider: AuthTokenProvider {
func getToken() async throws -> String? {
// トークン取得ロジック(例:Keychain から取得)
return "your-auth-token"
}
}
// クライアント作成時にトークンプロバイダーを指定
let client = APIClientImpl(
baseURL: URL(string: "https://api.example.com")!,
authTokenProvider: MyTokenProvider()
)
// リクエスト時に自動的に Authorization ヘッダーが追加されます
let user: User = try await client.request(endpoint)
HTTP イベントの監視
重要なHTTPレスポンス(401, 403, 429, 503, 5xx)をアプリ全体で監視できます。
// 認証エラーやサービス停止を一元的にハンドリング
Task {
for await event in await client.events {
switch event {
case .unauthorized:
await authManager.handleLogout()
case .rateLimited(_, let retryAfter, _):
print("レート制限: \(retryAfter ?? 0)秒後にリトライ")
case .serviceUnavailable:
await router.showMaintenanceScreen()
default:
break
}
}
}
HTTP ログの監視
全リクエスト/レスポンスをAsyncStreamで監視できます。
// デバッグ用コンソール出力(CustomStringConvertibleによる整形済み出力)
Task {
for await log in await client.logs {
print(log) // 自動的に整形されたログが出力されます
}
}
// カスタム処理(Analytics送信など)
Task {
for await log in await client.logs {
switch log {
case .success(let endpoint, let statusCode, _):
analytics.trackSuccess(endpoint: endpoint.path, statusCode: statusCode)
case .httpError(let endpoint, let statusCode, _):
analytics.trackError(endpoint: endpoint.path, statusCode: statusCode)
case .decodingError(let endpoint, _, _, let targetType):
analytics.trackDecodingError(endpoint: endpoint.path, type: targetType)
}
}
}
ライセンス
このプロジェクトは MIT ライセンスの下で公開されています。詳細は LICENSE ファイルをご覧ください。
サポート
問題が発生した場合や機能リクエストがある場合は、GitHub の Issue を作成してください。