class TestCorsMiddlewareProcessRequest(TestCase):

    def setUp(self):
        self.middleware = CorsMiddleware()

    def test_process_request(self):
        request = Mock(path='/')
        request.method = 'OPTIONS'
        request.META = {'HTTP_ACCESS_CONTROL_REQUEST_METHOD': 'value'}
        with settings_override(CORS_URLS_REGEX='^.*$'):
            response = self.middleware.process_request(request)
        self.assertIsInstance(response, HttpResponse)

    def test_process_request_empty_header(self):
        request = Mock(path='/')
        request.method = 'OPTIONS'
        request.META = {'HTTP_ACCESS_CONTROL_REQUEST_METHOD': ''}
        with settings_override(CORS_URLS_REGEX='^.*$'):
            response = self.middleware.process_request(request)
        self.assertIsInstance(response, HttpResponse)

    def test_process_request_no_header(self):
        request = Mock(path='/')
        request.method = 'OPTIONS'
        request.META = {}
        response = self.middleware.process_request(request)
        self.assertIsNone(response)

    def test_process_request_not_options(self):
        request = Mock(path='/')
        request.method = 'GET'
        request.META = {'HTTP_ACCESS_CONTROL_REQUEST_METHOD': 'value'}
        response = self.middleware.process_request(request)
        self.assertIsNone(response)
 def setUp(self):
     self.middleware = CorsMiddleware()
class TestCorsMiddlewareProcessResponse(TestCase):

    def setUp(self):
        self.middleware = CorsMiddleware()

    def assertAccessControlAllowOriginEquals(self, response, header):
        self.assertIn(ACCESS_CONTROL_ALLOW_ORIGIN, response, "Response %r does "
            "NOT have %r header" % (response, ACCESS_CONTROL_ALLOW_ORIGIN))
        self.assertEqual(response[ACCESS_CONTROL_ALLOW_ORIGIN], header)

    def test_process_response_no_origin(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request = Mock(path='/', META={})
        processed = self.middleware.process_response(request, response)
        self.assertNotIn(ACCESS_CONTROL_ALLOW_ORIGIN, processed)

    def test_process_response_not_in_whitelist(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = False
        settings.CORS_ORIGIN_WHITELIST = ['example.com']
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request = Mock(path='/', META={'HTTP_ORIGIN': 'http://foobar.it'})
        processed = self.middleware.process_response(request, response)
        self.assertNotIn(ACCESS_CONTROL_ALLOW_ORIGIN, processed)

    def test_process_response_in_whitelist(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = False
        settings.CORS_ORIGIN_WHITELIST = ['example.com', 'foobar.it']
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request = Mock(path='/', META={'HTTP_ORIGIN': 'http://foobar.it'})
        processed = self.middleware.process_response(request, response)
        self.assertAccessControlAllowOriginEquals(processed, 'http://foobar.it')

    def test_process_response_expose_headers(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = True
        settings.CORS_EXPOSE_HEADERS = ['accept', 'origin', 'content-type']
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request = Mock(path='/', META={'HTTP_ORIGIN': 'http://example.com'})
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed[ACCESS_CONTROL_EXPOSE_HEADERS],
            'accept, origin, content-type')

    def test_process_response_dont_expose_headers(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = True
        settings.CORS_EXPOSE_HEADERS = []
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request = Mock(path='/', META={'HTTP_ORIGIN': 'http://example.com'})
        processed = self.middleware.process_response(request, response)
        self.assertNotIn(ACCESS_CONTROL_EXPOSE_HEADERS, processed)

    def test_process_response_allow_credentials(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = True
        settings.CORS_ALLOW_CREDENTIALS = True
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request = Mock(path='/', META={'HTTP_ORIGIN': 'http://example.com'})
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed[ACCESS_CONTROL_ALLOW_CREDENTIALS], 'true')

    def test_process_response_dont_allow_credentials(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = True
        settings.CORS_ALLOW_CREDENTIALS = False
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request = Mock(path='/', META={'HTTP_ORIGIN': 'http://example.com'})
        processed = self.middleware.process_response(request, response)
        self.assertNotIn(ACCESS_CONTROL_ALLOW_CREDENTIALS, processed)

    def test_process_response_options_method(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = True
        settings.CORS_ALLOW_HEADERS = ['content-type', 'origin']
        settings.CORS_ALLOW_METHODS = ['GET', 'OPTIONS']
        settings.CORS_PREFLIGHT_MAX_AGE = 1002
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request_headers = {'HTTP_ORIGIN': 'http://example.com'}
        request = Mock(path='/', META=request_headers, method='OPTIONS')
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed[ACCESS_CONTROL_ALLOW_HEADERS],
            'content-type, origin')
        self.assertEqual(processed[ACCESS_CONTROL_ALLOW_METHODS], 'GET, OPTIONS')
        self.assertEqual(processed[ACCESS_CONTROL_MAX_AGE], '1002')

    def test_process_response_options_method_no_max_age(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = True
        settings.CORS_ALLOW_HEADERS = ['content-type', 'origin']
        settings.CORS_ALLOW_METHODS = ['GET', 'OPTIONS']
        settings.CORS_PREFLIGHT_MAX_AGE = 0
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request_headers = {'HTTP_ORIGIN': 'http://example.com'}
        request = Mock(path='/', META=request_headers, method='OPTIONS')
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed[ACCESS_CONTROL_ALLOW_HEADERS],
            'content-type, origin')
        self.assertEqual(processed[ACCESS_CONTROL_ALLOW_METHODS], 'GET, OPTIONS')
        self.assertNotIn(ACCESS_CONTROL_MAX_AGE, processed)

    def test_process_response_whitelist_with_port(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_ALLOW_ALL = False
        settings.CORS_ALLOW_METHODS = ['OPTIONS']
        settings.CORS_ORIGIN_WHITELIST = ('localhost:9000',)
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request_headers = {'HTTP_ORIGIN': 'http://localhost:9000'}
        request = Mock(path='/', META=request_headers, method='OPTIONS')
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed.get(ACCESS_CONTROL_ALLOW_CREDENTIALS, None), 'true')

    def test_process_response_adds_origin_when_domain_found_in_origin_regex_whitelist(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_REGEX_WHITELIST = ('^http?://(\w+\.)?google\.com$', )
        settings.CORS_ALLOW_CREDENTIALS = True
        settings.CORS_ORIGIN_ALLOW_ALL = False
        settings.CORS_ALLOW_METHODS = ['OPTIONS']
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request_headers = {'HTTP_ORIGIN': 'http://foo.google.com'}
        request = Mock(path='/', META=request_headers, method='OPTIONS')
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed.get(ACCESS_CONTROL_ALLOW_ORIGIN, None), 'http://foo.google.com')

    def test_process_response_will_not_add_origin_when_domain_not_found_in_origin_regex_whitelist(self, settings):
        settings.CORS_MODEL = None
        settings.CORS_ORIGIN_REGEX_WHITELIST = ('^http?://(\w+\.)?yahoo\.com$', )
        settings.CORS_ALLOW_CREDENTIALS = True
        settings.CORS_ORIGIN_ALLOW_ALL = False
        settings.CORS_ALLOW_METHODS = ['OPTIONS']
        settings.CORS_URLS_REGEX = '^.*$'
        response = HttpResponse()
        request_headers = {'HTTP_ORIGIN': 'http://foo.google.com'}
        request = Mock(path='/', META=request_headers, method='OPTIONS')
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed.get(ACCESS_CONTROL_ALLOW_ORIGIN, None), None)

    def test_process_response_when_custom_model_enabled(self, settings):
        from corsprofiles.models import CorsModel
        CorsModel.objects.create(cors='foo.google.com')
        settings.CORS_ORIGIN_REGEX_WHITELIST = ()
        settings.CORS_ALLOW_CREDENTIALS = False
        settings.CORS_ORIGIN_ALLOW_ALL = False
        settings.CORS_ALLOW_METHODS = settings.default_methods
        settings.CORS_URLS_REGEX = '^.*$'
        settings.CORS_MODEL = 'corsprofiles.CorsModel'
        response = HttpResponse()
        request = Mock(path='/', META={'HTTP_ORIGIN': 'http://foo.google.com'})
        processed = self.middleware.process_response(request, response)
        self.assertEqual(processed.get(ACCESS_CONTROL_ALLOW_ORIGIN, None), 'http://foo.google.com')