LoginSignup
1
1

More than 1 year has passed since last update.

aiohttp Server でいちばん雑に CORS 対応する方法

Last updated at Posted at 2020-02-05

aiohttp Server で API サーバを実装する場合の CORS1 対応は、aiohttp 公式で aiohttp_cors というモジュールが用意されている。

しかし Usage を読んでみると、各リソースと各ルートについて cors.add でラップする必要があり、どうも一筋縄ではいかない雰囲気。細かく設定ができるのは便利だが、「今はとにかくすべてのリクエストを許可したいんや」というケースもある。

そこで今回は、aiohttp_cors を使わずに雑に CORS 対応する方法について書く。

from aiohttp import web

@web.middleware
async def cors_middleware(request, handler):
    response = await handler(request)
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

app = web.Application(middlewares=[cors_middleware])

終わりです。

すべてのレスポンスに Access-Control-Allow-Origin: * ヘッダを追加するだけ。

「さすがに * はどうなの」という場合は環境変数で許可する Origin を指定できるようにするといい。

import os
from aiohttp import web

@web.middleware
async def cors_middleware(request, handler):
    response = await handler(request)
    response.headers['Access-Control-Allow-Origin'] = os.environ.get('CORS_ALLOW_ORIGIN', '*')
    return response

app = web.Application(middlewares=[cors_middleware])

ちなみに Preflight Request が飛ぶケースには対応していない。
対応したければ全ての OPTION リクエストに対してよしなに返すやつを作ったらいい。

本当に雑な話なので、セキュリティに大丈夫なのとかそのへんの話は各自よしなに考えていってほしい。

[追記] もうちょっとちゃんとした版

  • [2022.01 追記] Preflight Request にも対応した
  • [2022.02 追記] HTTPException を raise した場合も CORS ヘッダを付与するようにした
from os import getenv
from aiohttp import web

@web.middleware
async def cors_middleware(request, handler):
    headers = {
        "Access-Control-Allow-Headers": "*",
        "Access-Control-Allow-Methods": "*",
        "Access-Control-Allow-Origin": getenv("CORS_ALLOW_ORIGIN", "*"),
    }
    if request.method == "OPTIONS":
        return web.Response(headers=headers)
    try:
        response = await handler(request)
        for key, value in headers.items():
            response.headers[key] = value
        return response
    except web.HTTPException as e:
        for key, value in headers.items():
            e.headers[key] = value
        raise e

app = web.Application(middlewares=[cors_middleware])

[追記] Cookie をあつかう場合

Cookie を扱う場合は以下の変更が必要になる。

  • Access-Control-Allow-Credentials ヘッダに true を設定する必要がある
  • Access-Control-Allow-Headers* を指定できなくなるので個別設定する
@web.middleware
async def cors_middleware(request, handler):
    headers = {
        "Access-Control-Allow-Headers": "Content-Type",  # 使用するヘッダを追加していく
        "Access-Control-Allow-Methods": "*",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Origin": getenv("CORS_ALLOW_ORIGIN", "*"),
    }
    if request.method == "OPTIONS":
        return web.Response(headers=headers)
    try:
        response = await handler(request)
        for key, value in headers.items():
            response.headers[key] = value
        return response
    except web.HTTPException as e:
        for key, value in headers.items():
            e.headers[key] = value
        raise e
  1. オリジン間リソース共有 (CORS) - HTTP | MDN

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1