diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-11 15:19:16 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-11 15:19:16 (GMT) |
commit | 6b4cb5605a473114adee0990c69366a91f223039 (patch) | |
tree | 723a89a37d880ebf95f3bb531ae5f3ee4950396e | |
parent | a05942e9473696c65760050a0a23acfd43ea8155 (diff) |
Process OPTIONS and cross-site requests for localhost applications
-rw-r--r-- | sugar_network/node/router.py | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/sugar_network/node/router.py b/sugar_network/node/router.py index 888235c..ee1fa1c 100644 --- a/sugar_network/node/router.py +++ b/sugar_network/node/router.py @@ -44,20 +44,14 @@ class Router(object): def __call__(self, environ, start_response): request = _Request(environ) response = _Response() - result = None js_callback = None if 'callback' in request: js_callback = request.pop('callback') + result = None try: - request.principal = self._authenticate(request) - if request.path[:1] == ['static']: - static_path = join(static.PATH, *request.path[1:]) - enforce(isfile(static_path), 'No such file') - result = file(static_path) - else: - result = self._cp.call(request, response) + result = self._call(request, response) except ad.Redirect, error: response.status = '303 See Other' response['Location'] = error.location @@ -83,21 +77,17 @@ class Router(object): } response.content_type = 'application/json' - if hasattr(result, 'read'): - # pylint: disable-msg=E1103 - if hasattr(result, 'fileno'): - response.content_length = os.fstat(result.fileno()).st_size - elif hasattr(result, 'seek'): - result.seek(0, 2) - response.content_length = result.tell() - result.seek(0) - result = _stream_reader(result) result_streamed = isinstance(result, types.GeneratorType) - if not result_streamed and response.content_type == 'application/json': + if js_callback: + if result_streamed: + result = ''.join(result) + result_streamed = False + result = '%s(%s);' % (js_callback, json.dumps(result)) + response.content_length = len(result) + elif not result_streamed and \ + response.content_type == 'application/json': result = json.dumps(result) - if js_callback: - result = '%s(%s);' % (js_callback, result) response.content_length = len(result) _logger.debug('Called %s: response=%r result=%r streamed=%r', @@ -111,6 +101,45 @@ class Router(object): elif result is not None: yield result + def _call(self, request, response): + if 'HTTP_ORIGIN' in request.environ: + enforce(request.environ['HTTP_ORIGIN'] == 'null', ad.Forbidden, + 'Cross-site is allowed only for local applications') + response['Access-Control-Allow-Origin'] = \ + request.environ['HTTP_ORIGIN'] + + if request['method'] == "OPTIONS": + # TODO Process OPTIONS request per url? + if request.environ['HTTP_ORIGIN']: + response['Access-Control-Allow-Methods'] = \ + request.environ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] + response['Access-Control-Allow-Headers'] = \ + request.environ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] + else: + response['Allow'] = "GET, POST, PUT, DELETE" + response.content_length = 0 + return None + + request.principal = self._authenticate(request) + if request.path[:1] == ['static']: + static_path = join(static.PATH, *request.path[1:]) + enforce(isfile(static_path), 'No such file') + result = file(static_path) + else: + result = self._cp.call(request, response) + + if hasattr(result, 'read'): + # pylint: disable-msg=E1103 + if hasattr(result, 'fileno'): + response.content_length = os.fstat(result.fileno()).st_size + elif hasattr(result, 'seek'): + result.seek(0, 2) + response.content_length = result.tell() + result.seek(0) + result = _stream_reader(result) + + return result + def _authenticate(self, request): user = request.environ.get('HTTP_SUGAR_USER') if user is None: |