1from datetime import timedelta
2from flask import make_response, request, current_app
3from functools import update_wrapper
4
5
6def crossdomain(
7 origin=None,
8 methods=None,
9 headers=None,
10 expose_headers=None,
11 max_age=21600,
12 attach_to_all=True,
13 automatic_options=True,
14 credentials=False,
15):
16 """
17 https://web.archive.org/web/20190128010149/http://flask.pocoo.org/snippets/56/
18 """
19 if methods is not None:
20 methods = ", ".join(sorted(x.upper() for x in methods))
21 if headers is not None and not isinstance(headers, str):
22 headers = ", ".join(x.upper() for x in headers)
23 if expose_headers is not None and not isinstance(expose_headers, str):
24 expose_headers = ", ".join(x.upper() for x in expose_headers)
25 if not isinstance(origin, str):
26 origin = ", ".join(origin)
27 if isinstance(max_age, timedelta):
28 max_age = max_age.total_seconds()
29
30 def get_methods():
31 if methods is not None:
32 return methods
33
34 options_resp = current_app.make_default_options_response()
35 return options_resp.headers["allow"]
36
37 def decorator(f):
38 def wrapped_function(*args, **kwargs):
39 if automatic_options and request.method == "OPTIONS":
40 resp = current_app.make_default_options_response()
41 else:
42 resp = make_response(f(*args, **kwargs))
43 if not attach_to_all and request.method != "OPTIONS":
44 return resp
45
46 h = resp.headers
47
48 h["Access-Control-Allow-Origin"] = origin
49 h["Access-Control-Allow-Methods"] = get_methods()
50 h["Access-Control-Max-Age"] = str(max_age)
51 if credentials:
52 h["Access-Control-Allow-Credentials"] = "true"
53 if headers is not None:
54 h["Access-Control-Allow-Headers"] = headers
55 if expose_headers is not None:
56 h["Access-Control-Expose-Headers"] = expose_headers
57 return resp
58
59 f.provide_automatic_options = False
60 return update_wrapper(wrapped_function, f)
61
62 return decorator