Skip to content

Commit b031134

Browse files
committed
add cors support
1 parent a96f31c commit b031134

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Tyron is a web app for events pushing.
77

88
It is written in python and developed as a Flask application.
99

10-
** Gevent is required to run Tyron **
10+
**Gevent is required to run Tyron**
1111

1212
The messaging backend utilises the redis pub/sub feature.
1313

tyron/tyron.py

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import os
1414
import logging
1515
import redis
16+
from .utils import crossdomain
17+
1618

1719
monkey.patch_all()
1820

@@ -82,6 +84,7 @@ def health():
8284
return 'OK'
8385

8486
@application.route('/<channel>/', methods=('GET', 'POST', 'OPTIONS'))
87+
@crossdomain(origin='*')
8588
def subscribe(channel):
8689
timeout = application.config['LONGPOLLING_TIMEOUT']
8790
try:

tyron/utils.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from datetime import timedelta
2+
from flask import make_response, request, current_app
3+
from functools import update_wrapper
4+
5+
"""
6+
A Flask crossdomain decorator written by Armin Ronacher
7+
8+
http://flask.pocoo.org/snippets/56/
9+
10+
"""
11+
12+
def crossdomain(origin=None, methods=None, headers=None,
13+
max_age=21600, attach_to_all=True,
14+
automatic_options=True):
15+
if methods is not None:
16+
methods = ', '.join(sorted(x.upper() for x in methods))
17+
if headers is not None and not isinstance(headers, basestring):
18+
headers = ', '.join(x.upper() for x in headers)
19+
if not isinstance(origin, basestring):
20+
origin = ', '.join(origin)
21+
if isinstance(max_age, timedelta):
22+
max_age = max_age.total_seconds()
23+
24+
def get_methods():
25+
if methods is not None:
26+
return methods
27+
28+
options_resp = current_app.make_default_options_response()
29+
return options_resp.headers['allow']
30+
31+
def decorator(f):
32+
def wrapped_function(*args, **kwargs):
33+
if automatic_options and request.method == 'OPTIONS':
34+
resp = current_app.make_default_options_response()
35+
else:
36+
resp = make_response(f(*args, **kwargs))
37+
if not attach_to_all and request.method != 'OPTIONS':
38+
return resp
39+
40+
h = resp.headers
41+
42+
h['Access-Control-Allow-Origin'] = origin
43+
h['Access-Control-Allow-Methods'] = get_methods()
44+
h['Access-Control-Max-Age'] = str(max_age)
45+
if headers is not None:
46+
h['Access-Control-Allow-Headers'] = headers
47+
return resp
48+
49+
f.provide_automatic_options = False
50+
return update_wrapper(wrapped_function, f)
51+
return decorator

0 commit comments

Comments
 (0)