add a decorator for CORS.
This commit is contained in:
parent
c5cdcf0f95
commit
49fb34ca2b
50
examples/cors.html
Normal file
50
examples/cors.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Cors Example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
var xhr1 = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr1.onload = function () {
|
||||||
|
console.log(xhr1.responseText)
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr1.open('GET', 'http://127.0.0.1:8000/');
|
||||||
|
xhr1.send();
|
||||||
|
|
||||||
|
var xhr2 = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr2.onload = function () {
|
||||||
|
console.log(xhr2.responseText)
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr2.open('GET', 'http://127.0.0.1:8000/t2');
|
||||||
|
xhr2.send();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var ws = new WebSocket('ws://127.0.0.1:8000/feed'),
|
||||||
|
messages = document.createElement('ul');
|
||||||
|
ws.onmessage = function (event) {
|
||||||
|
var messages = document.getElementsByTagName('ul')[0],
|
||||||
|
message = document.createElement('li'),
|
||||||
|
content = document.createTextNode('Received: ' + event.data);
|
||||||
|
message.appendChild(content);
|
||||||
|
messages.appendChild(message);
|
||||||
|
};
|
||||||
|
document.body.appendChild(messages);
|
||||||
|
window.setInterval(function () {
|
||||||
|
var data = 'bye!';
|
||||||
|
ws.send(data);
|
||||||
|
var messages = document.getElementsByTagName('ul')[0],
|
||||||
|
message = document.createElement('li'),
|
||||||
|
content = document.createTextNode('Sent: ' + data);
|
||||||
|
message.appendChild(content);
|
||||||
|
messages.appendChild(message);
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
examples/cors_example.py
Normal file
31
examples/cors_example.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
from sanic import Sanic
|
||||||
|
from sanic import response
|
||||||
|
|
||||||
|
app = Sanic(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
@response.cors()
|
||||||
|
async def test(request):
|
||||||
|
return response.json({"test": True})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/t2")
|
||||||
|
@response.cors()
|
||||||
|
def test2(request):
|
||||||
|
return response.json({"test": True})
|
||||||
|
|
||||||
|
|
||||||
|
@app.websocket('/feed')
|
||||||
|
@response.cors()
|
||||||
|
async def feed(request, ws):
|
||||||
|
while True:
|
||||||
|
data = 'hello!'
|
||||||
|
print('Sending: ' + data)
|
||||||
|
await ws.send(data)
|
||||||
|
data = await ws.recv()
|
||||||
|
print('Received: ' + data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host="0.0.0.0", port=8000)
|
|
@ -1,5 +1,7 @@
|
||||||
from mimetypes import guess_type
|
from mimetypes import guess_type
|
||||||
from os import path
|
from os import path
|
||||||
|
from functools import wraps
|
||||||
|
from inspect import isawaitable
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ujson import dumps as json_dumps
|
from ujson import dumps as json_dumps
|
||||||
|
@ -9,6 +11,7 @@ except:
|
||||||
from aiofiles import open as open_async
|
from aiofiles import open as open_async
|
||||||
|
|
||||||
from sanic.cookies import CookieJar
|
from sanic.cookies import CookieJar
|
||||||
|
from sanic.constants import HTTP_METHODS
|
||||||
|
|
||||||
COMMON_STATUS_CODES = {
|
COMMON_STATUS_CODES = {
|
||||||
200: b'OK',
|
200: b'OK',
|
||||||
|
@ -427,3 +430,45 @@ def redirect(to, headers=None, status=302,
|
||||||
status=status,
|
status=status,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
content_type=content_type)
|
content_type=content_type)
|
||||||
|
|
||||||
|
|
||||||
|
def cors(origin=None, allow_methods=None):
|
||||||
|
if isinstance(allow_methods, (list, tuple, set)):
|
||||||
|
allow_methods = ', '.join(
|
||||||
|
filter(
|
||||||
|
lambda x: x in HTTP_METHODS,
|
||||||
|
map(
|
||||||
|
lambda x: x.upper(),
|
||||||
|
allow_methods
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif allow_methods:
|
||||||
|
raise ValueError('allow_methods must be instance of list, tuple or set.')
|
||||||
|
|
||||||
|
cors_headers = {
|
||||||
|
'Access-Control-Allow-Credentials': 'true',
|
||||||
|
'Access-Control-Allow-Methods': allow_methods or 'GET',
|
||||||
|
'Access-Control-Allow-Origin': origin or '*'
|
||||||
|
}
|
||||||
|
|
||||||
|
def decorator(fn):
|
||||||
|
@wraps(fn)
|
||||||
|
def wrap(*args, **kwargs):
|
||||||
|
res = fn(*args, **kwargs)
|
||||||
|
if isinstance(res, BaseHTTPResponse):
|
||||||
|
res.headers.update(cors_headers)
|
||||||
|
return res
|
||||||
|
elif isawaitable(res):
|
||||||
|
async def make_cors():
|
||||||
|
response = await res
|
||||||
|
response.headers.update(cors_headers)
|
||||||
|
return response
|
||||||
|
|
||||||
|
return make_cors()
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
return wrap
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
Loading…
Reference in New Issue
Block a user