モダンな AWS Lambda 用 API フレームワーク
Project description
lambapi
モダンな AWS Lambda 用 API フレームワーク
概要
lambapi は、AWS Lambda で直感的でモダンな API を構築できる軽量フレームワークです。パスパラメータとクエリパラメータの自動注入、型変換、デフォルト値サポートなど、モダンな Web API 開発の機能を提供します。 ドキュメントは https://sskyh0208.github.io/lambapi/ で公開されています。
特徴
- 🚀 直感的な記法: デコレータベースのルート定義
- 📋 自動パラメータ注入: パスパラメータとクエリパラメータを関数引数として直接受け取り
- 🔄 型自動変換:
int,float,bool,strの自動型変換 - 🎯 デフォルト値サポート: クエリパラメータのデフォルト値設定
- 🔧 ミドルウェア対応: CORS など、カスタムミドルウェアの追加
- 📦 軽量: 標準ライブラリのみを使用、外部依存なし
- 🔒 型安全: 型ヒント完全対応
インストール
pip install lambapi
クイックスタート
基本的な使用例
from lambapi import API, Response, create_lambda_handler
def create_app(event, context):
app = API(event, context)
@app.get("/")
def hello():
return {"message": "Hello, lambapi!"}
@app.get("/users/{user_id}")
def get_user(user_id: str):
return {"user_id": user_id, "name": f"User {user_id}"}
@app.get("/search")
def search(q: str = "", limit: int = 10):
return {"query": q, "limit": limit, "results": []}
return app
lambda_handler = create_lambda_handler(create_app)
パスパラメータ + クエリパラメータ
@app.get("/users/{user_id}/posts")
def get_user_posts(user_id: str, limit: int = 10, sort: str = "created_at"):
return {
"user_id": user_id,
"limit": limit,
"sort": sort,
"posts": [f"post-{i}" for i in range(1, limit + 1)]
}
POST リクエストの処理
@app.post("/users")
def create_user(request):
user_data = request.json()
return Response(
{"message": "User created", "user": user_data},
status_code=201
)
型変換とデフォルト値
@app.get("/items")
def get_items(limit: int = 10, offset: int = 0, active: bool = True):
# limit と offset は自動的に int に変換
# active は自動的に bool に変換('true', '1', 'yes', 'on' → True)
return {
"limit": limit, # int 型
"offset": offset, # int 型
"active": active # bool 型
}
API リファレンス
API クラス
メインの API クラスです。
app = API(event, context)
デコレータ
@app.get(path)- GET リクエスト@app.post(path)- POST リクエスト@app.put(path)- PUT リクエスト@app.delete(path)- DELETE リクエスト@app.patch(path)- PATCH リクエスト
Request オブジェクト
従来の方式でリクエスト情報にアクセスする場合:
@app.get("/legacy")
def legacy_handler(request):
method = request.method
path = request.path
query_params = request.query_params
headers = request.headers
body = request.body
json_data = request.json()
path_params = request.path_params
Response オブジェクト
カスタムレスポンスを返す場合:
from lambapi import Response
@app.get("/custom")
def custom_response():
return Response(
{"message": "Custom response"},
status_code=201,
headers={"Custom-Header": "value"}
)
ミドルウェア
def cors_middleware(request, response):
if isinstance(response, Response):
response.headers.update({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
})
return response
app.add_middleware(cors_middleware)
CORS サポート
自動 OPTIONS ハンドリング
lambapi は CORS プリフライトリクエスト(OPTIONS)を自動的に処理します:
from lambapi import API, create_cors_config
def create_app(event, context):
app = API(event, context)
# グローバル CORS 設定
app.enable_cors(
origins=["https://example.com", "https://app.example.com"],
methods=["GET", "POST", "PUT", "DELETE"],
headers=["Content-Type", "Authorization"],
allow_credentials=True,
max_age=3600
)
@app.get("/users")
def get_users():
return {"users": []}
# OPTIONS /users が自動的に処理される
return app
ルートレベル CORS 設定
個別のルートに異なる CORS 設定を適用できます:
# デフォルト CORS 設定
@app.get("/public", cors=True)
def public_endpoint():
return {"message": "Public API"}
# カスタム CORS 設定
strict_cors = create_cors_config(
origins=["https://trusted.example.com"],
methods=["GET"],
allow_credentials=False
)
@app.get("/admin", cors=strict_cors)
def admin_endpoint():
return {"message": "Admin API"}
CORS 設定オプション
| パラメータ | 説明 | デフォルト |
|---|---|---|
origins |
許可するオリジン | "*" |
methods |
許可する HTTP メソッド | ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"] |
headers |
許可するヘッダー | ["Content-Type", "Authorization", "X-Requested-With"] |
allow_credentials |
認証情報の送信を許可 | False |
max_age |
プリフライトキャッシュ時間(秒) | None |
expose_headers |
ブラウザに公開するレスポンスヘッダー | None |
CORS の優先度
- ルートレベル設定 -
@app.get("/", cors=config) - グローバル設定 -
app.enable_cors() - 設定なし - CORS ヘッダーなし
構造化エラーハンドリング
統一されたエラーレスポンス
lambapi は、本番運用に適した構造化されたエラーハンドリングを提供します:
from lambapi import API, ValidationError, NotFoundError
def create_app(event, context):
app = API(event, context)
@app.get("/users/{user_id}")
def get_user(user_id: str):
# バリデーション
if not user_id.isdigit():
raise ValidationError(
"User ID must be numeric",
field="user_id",
value=user_id
)
# 存在チェック
if int(user_id) > 1000:
raise NotFoundError("User", user_id)
return {"id": user_id, "name": f"User {user_id}"}
return app
エラーレスポンス形式
すべてのエラーは統一された形式で返されます:
{
"error": "VALIDATION_ERROR",
"message": "User ID must be numeric",
"status_code": 400,
"field": "user_id",
"value": "abc",
"request_id": "12345678-1234-1234-1234-123456789012"
}
利用可能な例外クラス
| 例外クラス | HTTP ステータス | 用途 |
|---|---|---|
ValidationError |
400 | 入力データのバリデーションエラー |
NotFoundError |
404 | リソースが見つからない |
AuthenticationError |
401 | 認証が必要・失敗 |
AuthorizationError |
403 | 権限不足 |
ConflictError |
409 | データの競合 |
RateLimitError |
429 | レート制限に達した |
TimeoutError |
408 | 処理がタイムアウト |
InternalServerError |
500 | 内部サーバーエラー |
ServiceUnavailableError |
503 | サービス利用不可 |
カスタムエラーハンドラー
独自のエラーハンドリングロジックを定義できます:
class BusinessLogicError(Exception):
def __init__(self, message: str, business_code: str):
self.message = message
self.business_code = business_code
@app.error_handler(BusinessLogicError)
def handle_business_error(error, request, context):
return Response({
"error": "BUSINESS_ERROR",
"message": error.message,
"business_code": error.business_code,
"request_id": context.aws_request_id
}, status_code=422)
@app.get("/business-operation")
def business_operation():
raise BusinessLogicError("Insufficient inventory", "INV001")
サポートされる型変換
| 型注釈 | 変換動作 |
|---|---|
str |
そのまま文字列として渡される |
int |
int() で変換、失敗時は 0 |
float |
float() で変換、失敗時は 0.0 |
bool |
'true', '1', 'yes', 'on' を True として認識 |
ローカル開発
CLI コマンドでの開発
# 新しいプロジェクトを作成
lambapi create my-api --template basic
lambapi create my-crud-api --template crud
# ローカルサーバーを起動
lambapi serve app
lambapi serve app --host 0.0.0.0 --port 3000
Python から直接使用
from lambapi import serve
# ローカルサーバーを起動
serve('app') # app.py を起動
serve('my_app', host='0.0.0.0', port=3000)
ローカル開発の特徴
- ✅ 完全な HTTP メソッド対応: GET, POST, PUT, DELETE, PATCH, OPTIONS
- ✅ パスパラメータ:
/users/{user_id}形式をサポート - ✅ クエリパラメータ:
?name=value&age=25形式をサポート - ✅ リクエストボディ: JSON データの送受信
- ✅ CORS サポート: 開発用に自動で CORS ヘッダーを追加
- ✅ Lambda 互換: 実際の Lambda 環境と同じイベント・コンテキスト形式
- ✅ エラーハンドリング: 例外の適切な HTTP レスポンス変換
プロジェクトテンプレート
Basic テンプレート
lambapi create hello-api --template basic
cd hello-api
lambapi serve app
# テスト
curl http://localhost:8000/
curl http://localhost:8000/hello/world
CRUD テンプレート
lambapi create todo-api --template crud
cd todo-api
lambapi serve app
# テスト
curl http://localhost:8000/items
curl -X POST http://localhost:8000/items -H "Content-Type: application/json" -d '{"name":"テスト項目"}'
ローカルでのテスト
# 基本的なテスト
curl http://localhost:8000/
curl http://localhost:8000/users/123
curl http://localhost:8000/search?q=test&limit=5
# POST リクエスト
curl -X POST http://localhost:8000/users \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@example.com"}'
# PUT リクエスト
curl -X PUT http://localhost:8000/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Updated Name"}'
# DELETE リクエスト
curl -X DELETE http://localhost:8000/users/1
本番デプロイとの互換性
ローカル開発サーバーは実際の Lambda + API Gateway 環境と完全に互換性があります:
| 機能 | ローカル | 本番 |
|---|---|---|
| HTTP メソッド | ✅ 全対応 | ✅ 全対応 |
| パスパラメータ | ✅ /users/{id} |
✅ /users/{id} |
| クエリパラメータ | ✅ ?name=value |
✅ ?name=value |
| リクエストボディ | ✅ JSON | ✅ JSON |
| レスポンス形式 | ✅ 同一 | ✅ 同一 |
| エラーハンドリング | ✅ 同一 | ✅ 同一 |
トラブルシューティング
よくある問題
-
lambda_handler が見つからない
# app.py の最後に必ず追加 lambda_handler = create_lambda_handler(create_app)
-
ポートが使用中
lambapi serve app --port 8001
-
モジュールが見つからない
# 現在のディレクトリを確認 ls app.py # 正しいファイル名を指定 lambapi serve your_app_file
開発
開発環境のセットアップ
git clone https://github.com/your-username/lambapi.git
cd lambapi
pip install -e ".[dev]"
テスト実行
pytest
コードフォーマット
black lambapi tests examples
型チェック
mypy lambapi
ライセンス
MIT License - 詳細は LICENSE ファイルを参照してください。
貢献
プルリクエストや Issue は歓迎します!詳細は CONTRIBUTING.md を参照してください。
関連プロジェクト
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lambapi-0.1.1.tar.gz.
File metadata
- Download URL: lambapi-0.1.1.tar.gz
- Upload date:
- Size: 59.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.13.1 Linux/6.11.0-1018-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86236d407a0a01dfde6d59acaa0d290576677ada9236c407801e6f28cdd22ce6
|
|
| MD5 |
b1b3f1db909ccff5ab6ef0e608828a2e
|
|
| BLAKE2b-256 |
695f23d8f28860d34863e545a554be3811bb722414a374106611a43a529574b7
|
File details
Details for the file lambapi-0.1.1-py3-none-any.whl.
File metadata
- Download URL: lambapi-0.1.1-py3-none-any.whl
- Upload date:
- Size: 32.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.13.1 Linux/6.11.0-1018-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f1f01752443b09e833e3b7827c7abda3b09b081847c74ecdfeef7b9c4e61022
|
|
| MD5 |
43fae1a183ab5282210f3e5c268c46b0
|
|
| BLAKE2b-256 |
f63a38166c7cc25051a362d40096d313e362acd1eb5039d9e957d883e9c79595
|