はじめに
こんにちは。今回はPythonのEVEフレームワークを使ってRESTful APIを開発する方法について、詳しく解説していきます。EVEは人間のために設計された、使いやすいPython製のRESTful APIフレームワークです。MongoDBとの相性が良く、簡単に高機能なWebサービスを構築できます。
以下、15章に分けて、コード例を交えながら丁寧に説明していきます。
第1章: EVEの基本
EVEは、FlaskとCerberusをベースにしたPythonフレームワークです。MongoDBとの連携が容易で、RESTful APIを素早く構築できます。まずは、EVEをインストールし、最小構成のアプリケーションを作成してみましょう。
from eve import Eve
# 設定
settings = {
    'DOMAIN': {'people': {}}
}
# アプリケーションの作成
app = Eve(settings=settings)
if __name__ == '__main__':
    app.run()
この簡単なコードで、/peopleエンドポイントを持つAPIサーバーが立ち上がります。EVEは設定ベースのフレームワークなので、多くの機能がsettingsディクショナリで制御できます。
第2章: スキーマの定義
EVEでは、Cerberusを使ってデータのバリデーションを行います。各リソースのスキーマを定義することで、APIに送信されるデータの検証が可能になります。
schema = {
    'firstname': {
        'type': 'string',
        'minlength': 1,
        'maxlength': 10,
    },
    'lastname': {
        'type': 'string',
        'minlength': 1,
        'maxlength': 15,
        'required': True,
        'unique': True,
    },
    'age': {
        'type': 'integer',
        'min': 0,
    },
    'role': {
        'type': 'list',
        'allowed': ["admin", "user", "manager"],
    },
}
settings = {
    'DOMAIN': {
        'people': {
            'schema': schema
        }
    }
}
このスキーマ定義により、/peopleエンドポイントに送信されるデータは自動的に検証されます。
第3章: HTTPメソッドの制御
EVEでは、各エンドポイントで許可するHTTPメソッドを簡単に制御できます。グローバル設定とリソースごとの設定が可能です。
settings = {
    'RESOURCE_METHODS': ['GET', 'POST', 'DELETE'],
    'ITEM_METHODS': ['GET', 'PATCH', 'PUT', 'DELETE'],
    'DOMAIN': {
        'people': {
            'resource_methods': ['GET', 'POST'],
            'item_methods': ['GET', 'PATCH'],
        }
    }
}
この設定により、/peopleエンドポイントではGETとPOSTのみが許可され、個別のアイテム(/people/)に対してはGETとPATCHのみが許可されます。
第4章: データベース接続
EVEはデフォルトでMongoDBをサポートしています。データベース接続の設定も簡単です。
settings = {
    'MONGO_HOST': 'localhost',
    'MONGO_PORT': 27017,
    'MONGO_DBNAME': 'apidb',
    'DOMAIN': {...}
}
この設定で、EVEは自動的にMongoDBに接続し、指定されたデータベースを使用します。
第5章: ページネーション
大量のデータを扱う場合、ページネーションは重要です。EVEには組み込みのページネーション機能があります。
settings = {
    'PAGINATION': True,
    'PAGINATION_LIMIT': 50,
    'PAGINATION_DEFAULT': 25,
    'DOMAIN': {...}
}
この設定により、クライアントは?page=2&max_results=30のようなクエリパラメータを使用してページネーションを制御できます。
第6章: プロジェクション
クライアントが必要なフィールドのみを取得できるようにするのは、APIのパフォーマンス向上に役立ちます。EVEのプロジェクション機能を使用すると、これが簡単に実現できます。
settings = {
    'DOMAIN': {
        'people': {
            'projection': {'role': 0}  # roleフィールドを除外
        }
    }
}
クライアントは?projection={"firstname": 1, "lastname": 1}のようなクエリを使用して、特定のフィールドのみを取得することもできます。
第7章: データ関係
EVEでは、リソース間の関係を簡単に定義できます。これにより、関連データの取得や整合性の維持が容易になります。
settings = {
    'DOMAIN': {
        'people': {...},
        'companies': {
            'schema': {
                'name': {'type': 'string'},
                'employees': {
                    'type': 'list',
                    'schema': {
                        'type': 'objectid',
                        'data_relation': {
                            'resource': 'people',
                            'field': '_id',
                            'embeddable': True
                        }
                    }
                }
            }
        }
    }
}
この設定により、companiesリソースはpeopleリソースへの参照を持つことができ、?embed={"employees":1}クエリで関連データを埋め込むことができます。
第8章: イベントフック
EVEのイベントフックを使用すると、リクエストの処理前後に独自のロジックを挿入できます。これは認証、ログ記録、データの事前処理などに役立ちます。
def pre_get_callback(request, lookup):
    print('A GET request is about to be processed')
def post_get_callback(request, payload):
    print('A GET request has been processed')
app = Eve()
app.on_pre_GET += pre_get_callback
app.on_post_GET += post_get_callback
このように、様々なHTTPメソッドやリソースに対してフックを定義できます。
第9章: カスタムエンドポイント
EVEはFlaskをベースにしているため、カスタムエンドポイントを追加することが可能です。これにより、標準的なCRUD操作以外の機能を実装できます。
from flask import jsonify
@app.route('/custom')
def custom_endpoint():
    return jsonify({'message': 'This is a custom endpoint'})
このようにして、EVEの標準機能を拡張できます。
第10章: 認証と認可
セキュリティは重要です。EVEには組み込みの認証システムがあり、カスタムの認証ロジックも実装できます。
def check_auth(username, password, allowed_roles, resource, method):
    return username == 'admin' and password == 'secret'
settings = {
    'AUTH_FIELD': 'user',
    'PUBLIC_METHODS': ['GET'],
    'PUBLIC_ITEM_METHODS': ['GET'],
}
app = Eve(auth=check_auth, settings=settings)
この例では、シンプルな認証関数を定義し、GETメソッドを除くすべての操作に認証を要求しています。
第11章: レート制限
APIの乱用を防ぐため、レート制限を設定することが重要です。EVEはFlask-Limiterを使用してこれを実現します。
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["200 per day", "50 per hour"]
)
@limiter.limit("10 per minute")
@app.route("/limited")
def limited():
    return "This endpoint is rate limited"
この設定により、APIの使用回数を制限し、過剰な負荷から保護することができます。
第12章: バージョニング
APIのバージョン管理は、後方互換性を維持しながら機能を進化させるために重要です。EVEでは、URLやヘッダーを使用してバージョンを制御できます。
settings = {
    'API_VERSION': 'v1',
    'URL_PREFIX': 'api',
    'DOMAIN': {
        'people': {
            'url': 'people',
            'datasource': {'source': 'people_v1'}
        }
    }
}
この設定により、/api/v1/peopleのようなURLでAPIにアクセスできるようになります。
第13章: キャッシング
パフォーマンスを向上させるため、EVEはFlask-Cachingを使用してレスポンスをキャッシュすることができます。
from flask_caching import Cache
cache = Cache(app, config={'CACHE_TYPE': 'simple'})
@app.route('/cached')
@cache.cached(timeout=50)
def cached_view():
    return "This response will be cached for 50 seconds"
適切なキャッシュ戦略を実装することで、APIのレスポンス時間を大幅に改善できます。
第14章: ドキュメンテーション
良いAPIには適切なドキュメントが不可欠です。EVEはSwagger/OpenAPIと統合できるので、自動的にAPIドキュメントを生成できます。
from eve_swagger import swagger
app = Eve()
app.register_blueprint(swagger)
# Swagger設定
app.config['SWAGGER_INFO'] = {
    'title': 'My API',
    'version': '1.0',
    'description': 'This is my awesome API',
}
この設定により、/api-docsエンドポイントで自動生成されたSwaggerドキュメントにアクセスできます。
第15章: デプロイメント
最後に、開発したAPIをデプロイする方法を見ていきましょう。EVEアプリケーションは、他のFlaskアプリケーションと同様にデプロイできます。
# wsgi.py
from myapp import app
if __name__ == "__main__":
    app.run()
このWSGIファイルを作成し、GunicornやuWSGIなどのWSGIサーバーで実行することで、本番環境にデプロイできます。
以上、EVEを使ったRESTful API開発の基本から応用までを15章にわたって解説しました。EVEの強力な機能を活用することで、高機能で柔軟なAPIを素早く開発できることがお分かりいただけたと思います。ぜひ、実際にEVEを使ってAPIを開発してみてください。
