Skip to content

Commit

Permalink
Support for headers, methods and max_age, closes #5
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Apr 8, 2024
1 parent f45fabe commit 53b126b
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
51 changes: 51 additions & 0 deletions README.md
Expand Up @@ -41,6 +41,57 @@ You can also whitelist patterns like this:
}
```

To allow all origins, use:

```json
{
"plugins": {
"datasette-cors": {
"allow_all": true
}
}
}
```

You can specify allowed headers using the `headers` option:

```json
{
"plugins": {
"datasette-cors": {
"allow_all": true,
"headers": ["Authorization", "Content-Type"]
}
}
}
```

To allow specific HTTP methods, use the `methods` option:

```json
{
"plugins": {
"datasette-cors": {
"allow_all": true,
"methods": ["GET", "POST", "OPTIONS"]
}
}
}
```

You can set the `Access-Control-Max-Age` header using the `max_age` option:

```json
{
"plugins": {
"datasette-cors": {
"allow_all": true,
"max_age": 3600
}
}
}
```

## Testing it

To test this plugin out, run it locally by saving one of the above examples as `metadata.json` and running this:
Expand Down
8 changes: 7 additions & 1 deletion datasette_cors.py
Expand Up @@ -8,16 +8,22 @@ def asgi_wrapper(datasette):
allow_all = config.get("allow_all") or False
hosts = config.get("hosts") or []
host_wildcards = config.get("host_wildcards") or []
headers = config.get("headers") or []
methods = config.get("methods") or []
max_age = config.get("max_age")

def wrap_with_asgi_cors(app):
if not (hosts or host_wildcards or allow_all):
if not (hosts or host_wildcards or allow_all or headers or methods or max_age):
return app

return asgi_cors(
app,
allow_all=allow_all,
hosts=hosts,
host_wildcards=host_wildcards,
headers=headers,
methods=methods,
max_age=max_age,
)

return wrap_with_asgi_cors
64 changes: 64 additions & 0 deletions test_datasette_cors.py
Expand Up @@ -46,3 +46,67 @@ async def test_asgi_cors_hosts(request_origin, expected_cors_header):
assert (
response.headers.get("access-control-allow-origin") == expected_cors_header
)


@pytest.mark.asyncio
async def test_asgi_cors_headers():
async with httpx.AsyncClient(
app=Datasette(
[],
memory=True,
metadata={
"plugins": {
"datasette-cors": {
"allow_all": True,
"headers": ["Authorization", "Content-Type"],
}
}
},
).app()
) as client:
response = await client.get("http://localhost/")
assert response.status_code == 200
assert response.headers["access-control-allow-origin"] == "*"
assert (
response.headers["access-control-allow-headers"]
== "Authorization, Content-Type"
)


@pytest.mark.asyncio
async def test_asgi_cors_methods():
async with httpx.AsyncClient(
app=Datasette(
[],
memory=True,
metadata={
"plugins": {
"datasette-cors": {
"allow_all": True,
"methods": ["GET", "POST", "OPTIONS"],
}
}
},
).app()
) as client:
response = await client.get("http://localhost/")
assert response.status_code == 200
assert response.headers["access-control-allow-origin"] == "*"
assert response.headers["access-control-allow-methods"] == "GET, POST, OPTIONS"


@pytest.mark.asyncio
async def test_asgi_cors_max_age():
async with httpx.AsyncClient(
app=Datasette(
[],
memory=True,
metadata={
"plugins": {"datasette-cors": {"allow_all": True, "max_age": 3600}}
},
).app()
) as client:
response = await client.get("http://localhost/")
assert response.status_code == 200
assert response.headers["access-control-allow-origin"] == "*"
assert response.headers["access-control-max-age"] == "3600"

0 comments on commit 53b126b

Please sign in to comment.