-
Notifications
You must be signed in to change notification settings - Fork 967
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1331 from carlfeberhard/CORS
Core, CORS: allow (non-preflighted) CORS requests by echoing back the…
- Loading branch information
Showing
6 changed files
with
235 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
""" | ||
Unit tests for ``galaxy.web.framework.webapp`` | ||
""" | ||
import os | ||
import imp | ||
import unittest | ||
|
||
import logging | ||
log = logging.getLogger( __name__ ) | ||
|
||
test_utils = imp.load_source( 'test_utils', | ||
os.path.join( os.path.dirname( __file__), '../../unittest_utils/utility.py' ) ) | ||
import galaxy_mock | ||
|
||
import re | ||
from galaxy.web.framework import webapp as Webapp | ||
import galaxy.config | ||
|
||
|
||
class StubGalaxyWebTransaction( Webapp.GalaxyWebTransaction ): | ||
def _ensure_valid_session( self, session_cookie, create=True ): | ||
pass | ||
|
||
|
||
class CORSParsingMockConfig( galaxy_mock.MockAppConfig ): | ||
# we can't use the actual Configuration for parsing*, so steal the parser for the mock instead | ||
# *It causes problems when it's change to tempfile.tempdir persists across tests | ||
_parse_allowed_origin_hostnames = galaxy.config.Configuration._parse_allowed_origin_hostnames.__func__ | ||
|
||
def __init__( self, **kwargs ): | ||
super( CORSParsingMockConfig, self ).__init__( **kwargs ) | ||
self.allowed_origin_hostnames = self._parse_allowed_origin_hostnames( kwargs ) | ||
|
||
|
||
class GalaxyWebTransaction_Headers_TestCase( test_utils.unittest.TestCase ): | ||
|
||
def _new_trans( self, allowed_origin_hostnames=None ): | ||
app = galaxy_mock.MockApp() | ||
app.config = CORSParsingMockConfig( | ||
allowed_origin_hostnames=allowed_origin_hostnames | ||
) | ||
webapp = galaxy_mock.MockWebapp() | ||
environ = galaxy_mock.buildMockEnviron() | ||
trans = StubGalaxyWebTransaction( environ, app, webapp ) | ||
return trans | ||
|
||
def assert_cors_header_equals( self, headers, should_be ): | ||
self.assertEqual( headers.get( 'access-control-allow-origin', None ), should_be ) | ||
|
||
def assert_cors_header_missing( self, headers ): | ||
self.assertFalse( 'access-control-allow-origin' in headers ) | ||
|
||
def test_parse_allowed_origin_hostnames( self ): | ||
"""Should return a list of (possibly) mixed strings and regexps""" | ||
config = CORSParsingMockConfig() | ||
|
||
# falsy listify value should return None | ||
self.assertEqual( config._parse_allowed_origin_hostnames({ | ||
"allowed_origin_hostnames" : "" | ||
}), None ) | ||
|
||
# should parse regex if using fwd slashes, string otherwise | ||
hostnames = config._parse_allowed_origin_hostnames({ | ||
"allowed_origin_hostnames" : "/host\d{2}/,geocities.com,miskatonic.edu" | ||
}) | ||
self.assertTrue( isinstance( hostnames[0], re._pattern_type ) ) | ||
self.assertTrue( isinstance( hostnames[1], str ) ) | ||
self.assertTrue( isinstance( hostnames[2], str ) ) | ||
|
||
def test_default_set_cors_headers( self ): | ||
"""No CORS headers should be set (or even checked) by default""" | ||
trans = self._new_trans( allowed_origin_hostnames=None ) | ||
self.assertTrue( isinstance( trans, Webapp.GalaxyWebTransaction ) ) | ||
|
||
trans.request.headers[ 'Origin' ] = 'http://lisaskelprecipes.pinterest.com?id=kelpcake' | ||
trans.set_cors_headers() | ||
self.assert_cors_header_missing( trans.response.headers ) | ||
|
||
def test_set_cors_headers( self ): | ||
"""Origin should be echo'd when it matches an allowed hostname""" | ||
# an asterisk is a special 'allow all' string | ||
trans = self._new_trans( allowed_origin_hostnames='*,beep.com' ) | ||
trans.request.headers[ 'Origin' ] = 'http://xxdarkhackerxx.disney.com' | ||
trans.set_cors_headers() | ||
self.assert_cors_header_equals( trans.response.headers, 'http://xxdarkhackerxx.disney.com' ) | ||
|
||
# subdomains should pass | ||
trans = self._new_trans( allowed_origin_hostnames='something.com,/^[\w\.]*beep\.com/' ) | ||
trans.request.headers[ 'Origin' ] = 'http://boop.beep.com' | ||
trans.set_cors_headers() | ||
self.assert_cors_header_equals( trans.response.headers, 'http://boop.beep.com' ) | ||
|
||
# ports should work | ||
trans = self._new_trans( allowed_origin_hostnames='somethingelse.com,/^[\w\.]*beep\.com/' ) | ||
trans.request.headers[ 'Origin' ] = 'http://boop.beep.com:8080' | ||
trans.set_cors_headers() | ||
self.assert_cors_header_equals( trans.response.headers, 'http://boop.beep.com:8080' ) | ||
|
||
# localhost should work | ||
trans = self._new_trans( allowed_origin_hostnames='/localhost/' ) | ||
trans.request.headers[ 'Origin' ] = 'http://localhost:8080' | ||
trans.set_cors_headers() | ||
self.assert_cors_header_equals( trans.response.headers, 'http://localhost:8080' ) | ||
|
||
# spoofing shouldn't be easy | ||
trans.response.headers = {} | ||
trans.request.headers[ 'Origin' ] = 'http://localhost.badstuff.tv' | ||
trans.set_cors_headers() | ||
self.assert_cors_header_missing( trans.response.headers ) | ||
|
||
# unicode should work | ||
trans = self._new_trans( allowed_origin_hostnames='/öbb\.at/' ) | ||
trans.request.headers[ 'Origin' ] = 'http://öbb.at' | ||
trans.set_cors_headers() | ||
self.assertEqual( | ||
trans.response.headers[ 'access-control-allow-origin' ], 'http://öbb.at' | ||
) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |