Browse Source

support cors preflight and better cors support

Guénaël Muller 6 years ago
parent
commit
44659595ce
3 changed files with 81 additions and 8 deletions
  1. 4 3
      tracim/__init__.py
  2. 77 0
      tracim/lib/utils/cors.py
  3. 0 5
      tracim/lib/utils/pyramid_events.py

+ 4 - 3
tracim/__init__.py View File

@@ -3,13 +3,11 @@ import json
3 3
 import time
4 4
 
5 5
 from pyramid.config import Configurator
6
-from pyramid.events import NewResponse
7 6
 from pyramid.authentication import BasicAuthAuthenticationPolicy
8 7
 from hapic.ext.pyramid import PyramidContext
9 8
 
10 9
 from tracim.extensions import hapic
11 10
 from tracim.config import CFG
12
-from tracim.lib.utils.pyramid_events import cors_headers
13 11
 from tracim.lib.utils.request import TracimRequest
14 12
 from tracim.lib.utils.authentification import basic_auth_check_credentials
15 13
 from tracim.lib.utils.authentification import BASIC_AUTH_WEBUI_REALM
@@ -18,6 +16,7 @@ from tracim.lib.utils.authorization import TRACIM_DEFAULT_PERM
18 16
 from tracim.views import BASE_API_V2
19 17
 from tracim.views.core_api.session_controller import SessionController
20 18
 from tracim.views.errors import ErrorSchema
19
+from tracim.lib.utils.cors import add_cors_support
21 20
 
22 21
 
23 22
 def main(global_config, **settings):
@@ -33,6 +32,9 @@ def main(global_config, **settings):
33 32
         basic_auth_check_credentials,
34 33
         realm=BASIC_AUTH_WEBUI_REALM,
35 34
     )
35
+    configurator.include(add_cors_support)
36
+    # make sure to add this before other routes to intercept OPTIONS
37
+    configurator.add_cors_preflight_handler()
36 38
     # Default authorization : Accept anything.
37 39
     configurator.set_authorization_policy(AcceptAllAuthorizationPolicy())
38 40
     configurator.set_authentication_policy(authn_policy)
@@ -46,7 +48,6 @@ def main(global_config, **settings):
46 48
     configurator.include('pyramid_jinja2')
47 49
     # Add SqlAlchemy DB
48 50
     configurator.include('.models')
49
-    configurator.add_subscriber(cors_headers, NewResponse)
50 51
     # set Hapic
51 52
     hapic.set_context(
52 53
         PyramidContext(

+ 77 - 0
tracim/lib/utils/cors.py View File

@@ -0,0 +1,77 @@
1
+# -*- coding: utf-8 -*-
2
+# INFO - G.M -17-05-2018 - CORS support
3
+# original code from https://gist.github.com/mmerickel/1afaf64154b335b596e4
4
+# see also
5
+# here : https://groups.google.com/forum/#!topic/pylons-discuss/2Sw4OkOnZcE
6
+from pyramid.events import NewResponse
7
+
8
+
9
+def add_cors_support(config):
10
+    # INFO - G.M - 17-05-2018 - CORS Preflight stuff (special requests)
11
+    config.add_directive(
12
+        'add_cors_preflight_handler',
13
+        add_cors_preflight_handler
14
+    )
15
+    config.add_route_predicate('cors_preflight', CorsPreflightPredicate)
16
+
17
+    # INFO - G.M - 17-05-2018 CORS Headers for all responses
18
+    config.add_subscriber(add_cors_to_response, NewResponse)
19
+
20
+
21
+class CorsPreflightPredicate(object):
22
+    def __init__(self, val, config):
23
+        self.val = val
24
+
25
+    def text(self):
26
+        return 'cors_preflight = %s' % bool(self.val)
27
+
28
+    phash = text
29
+
30
+    def __call__(self, context, request):
31
+        if not self.val:
32
+            return False
33
+        return (
34
+            request.method == 'OPTIONS' and
35
+            'Origin' in request.headers and
36
+            'Access-Control-Request-Method' in request.headers
37
+        )
38
+
39
+
40
+def add_cors_preflight_handler(config):
41
+    # INFO - G.M - 17-05-2018 - Add route for CORS preflight
42
+    # see https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
43
+    # for more info about preflight
44
+
45
+    config.add_route(
46
+        'cors-options-preflight', '/{catch_all:.*}',
47
+        cors_preflight=True,
48
+    )
49
+    config.add_view(
50
+        cors_options_view,
51
+        route_name='cors-options-preflight',
52
+    )
53
+
54
+
55
+def cors_options_view(context, request):
56
+    response = request.response
57
+    if 'Access-Control-Request-Headers' in request.headers:
58
+        response.headers['Access-Control-Allow-Methods'] = (
59
+            'OPTIONS,HEAD,GET,POST,PUT,DELETE'
60
+        )
61
+    response.headers['Access-Control-Allow-Headers'] = (
62
+        'Content-Type,Accept,Accept-Language,Authorization,X-Request-ID'
63
+    )
64
+    return response
65
+
66
+
67
+def add_cors_to_response(event):
68
+    # INFO - G.M - 17-05-2018 - Add some CORS headers to all requests
69
+    request = event.request
70
+    response = event.response
71
+    if 'Origin' in request.headers:
72
+        response.headers['Access-Control-Expose-Headers'] = (
73
+            'Content-Type,Date,Content-Length,Authorization,X-Request-ID'
74
+        )
75
+        # TODO - G.M - 17-05-2018 - Allow to configure this header in config
76
+        response.headers['Access-Control-Allow-Origin'] = '*'
77
+        response.headers['Access-Control-Allow-Credentials'] = 'true'

+ 0 - 5
tracim/lib/utils/pyramid_events.py View File

@@ -1,5 +0,0 @@
1
-
2
-
3
-def cors_headers(context):
4
-    # TODO - G.M - 17-05-2018 - Allow to configure this header in config
5
-    context.response.headers['Access-Control-Allow-Origin'] = '*'