Sanic-CORS
Sanic-CORS is a Sanic extension that provides Cross-Origin Resource Sharing (CORS) support, primarily through a decorator. It is based on the popular Flask-CORS library. The current version is 2.2.0, with a release cadence that aligns with critical Sanic updates and bug fixes, typically every few months for major Sanic version compatibility.
Common errors
-
No 'Access-Control-Allow-Origin' header is present on the requested resource.
cause The CORS headers are not being sent by the Sanic server, often due to misconfiguration or `sanic-cors` not being applied to the specific route or application.fixEnsure `CORS(app)` is called at the application level before routes are registered, or that `@cross_origin()` is applied to the specific route handler. Verify the `origins` parameter in `CORS()` or `@cross_origin()` allows the client's origin (e.g., `origins="*"` for development, or a specific domain). -
405 Method Not Allowed (for OPTIONS requests)
cause Sanic is not correctly handling the CORS preflight OPTIONS request, indicating `sanic-cors` is not intercepting or correctly processing it.fixEnsure `automatic_options=True` is passed to `CORS(app)` or `@cross_origin()`. This is often the default, but explicitly setting it can resolve issues. Also, ensure `CORS(app)` is called before any blueprints or routes that require CORS are registered, to allow the middleware to activate correctly. -
AttributeError: 'Request' object has no attribute 'ctx'
cause This error can occur in older Sanic versions or specific setups where `sanic-cors` expects `request.ctx` but it's not available in the request context.fixThis often points to a Sanic version incompatibility. Upgrade Sanic to a more recent version (e.g., Sanic 19.9+ or 21.3+). If upgrading Sanic is not feasible, you might need to use an older compatible `sanic-cors` version (e.g., `0.10.x` for Sanic <= 21.3).
Warnings
- breaking Sanic-CORS v2.0.0 removed compatibility with Sanic-Plugin-Toolkit (SPTK) and Sanic-Plugins-Framework (SPF). Code relying on these prior integration methods will break.
- breaking Sanic-CORS v1.0.0 dropped support for Sanic versions older than 21.3. Attempting to use v1.0.0+ with older Sanic versions will lead to incompatibilities.
- gotcha Compatibility issues can arise with specific Sanic and Sanic-Ext versions due to changes in middleware handling or internal APIs. For example, Sanic-CORS 2.2.0 was needed for Sanic v22.9.0, and 2.1.0 for Sanic-Ext v22.6.0+.
- gotcha The `Vary` header behavior was improved in v2.2.0. Previously, `Vary 'Origin'` might overwrite existing `Vary` headers on a response, leading to unexpected caching behavior.
Install
-
pip install sanic-cors
Imports
- CORS
from sanic_cors import CORS
- cross_origin
from sanic_cors import cross_origin
Quickstart
from sanic import Sanic, response
from sanic_cors import CORS, cross_origin
import os
app = Sanic(__name__)
# Enable CORS for the entire application (or specify options)
CORS(app, origins="*", allow_headers="*", expose_headers="*", automatic_options=True)
@app.route("/", methods=["GET"])
@cross_origin(origins=os.environ.get('ALLOWED_ORIGIN', '*')) # Decorator for specific route
async def hello_world(request):
return response.json({"message": "Hello from Sanic-CORS!"})
@app.route("/data", methods=["GET", "POST"])
# cross_origin() can be omitted if CORS(app) handles it globally
async def get_data(request):
if request.method == "GET":
return response.json({"data": "Some public data"})
elif request.method == "POST":
return response.json({"status": "Data received"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)