def test_error_handlers(rf): """ Test that SHOOP_FRONT_INSTALL_ERROR_HANDLERS installs error handlers without overwriting possible custom ones. """ with override_settings( DEBUG=False, SHOOP_FRONT_INSTALL_ERROR_HANDLERS=True, MIDDLEWARE_CLASSES=[] ): with replace_urls([ url("^aaargh/", errorful_view) ], {"handler404": four_oh_four}): resolver = get_resolver(None) urlconf = resolver.urlconf_module install_error_handlers() assert callable(urlconf.handler500) # We get a new 500 handler assert urlconf.handler404 == four_oh_four # Our custom 404 handler didn't get overwritten handler = BaseHandler() handler.load_middleware() # Test 500 response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 # Uh oh! assert isinstance(response, TemplateResponse) # Looks good! assert response.template_name.startswith("shoop") # Woop! # Test 404 response = handler.get_response(rf.get("/another_castle/")) assert response.status_code == 200 # Our custom 404 handler made it a 200! assert b"flesh wound" in response.content
class MessageSenderWorker(QueueProcessingWorker): def __init__(self): # type: () -> None super().__init__() self.redis_client = get_redis_client() self.handler = BaseHandler() self.handler.load_middleware() def consume(self, event): # type: (Mapping[str, Any]) -> None server_meta = event['server_meta'] environ = { 'REQUEST_METHOD': 'SOCKET', 'SCRIPT_NAME': '', 'PATH_INFO': '/json/messages', 'SERVER_NAME': '127.0.0.1', 'SERVER_PORT': 9993, 'SERVER_PROTOCOL': 'ZULIP_SOCKET/1.0', 'wsgi.version': (1, 0), 'wsgi.input': StringIO(), 'wsgi.errors': sys.stderr, 'wsgi.multithread': False, 'wsgi.multiprocess': True, 'wsgi.run_once': False, 'zulip.emulated_method': 'POST' } if 'socket_user_agent' in event['request']: environ['HTTP_USER_AGENT'] = event['request']['socket_user_agent'] del event['request']['socket_user_agent'] # We're mostly using a WSGIRequest for convenience environ.update(server_meta['request_environ']) request = WSGIRequest(environ) # Note: If we ever support non-POST methods, we'll need to change this. request._post = event['request'] request.csrf_processing_done = True user_profile = get_user_profile_by_id(server_meta['user_id']) request._cached_user = user_profile resp = self.handler.get_response(request) server_meta['time_request_finished'] = time.time() server_meta['worker_log_data'] = request._log_data resp_content = resp.content.decode('utf-8') response_data = ujson.loads(resp_content) if response_data['result'] == 'error': check_and_send_restart_signal() result = {'response': response_data, 'req_id': event['req_id'], 'server_meta': server_meta} redis_key = req_redis_key(event['req_id']) self.redis_client.hmset(redis_key, {'status': 'complete', 'response': resp_content}) queue_json_publish(server_meta['return_queue'], result, respond_send_message)
class CommonMiddlewareAppendSlashWithoutRedirect(CommonMiddleware): """ This class converts HttpSmartRedirectResponse to the common response of Django view, without redirect. """ response_redirect_class = HttpSmartRedirectResponse def __init__(self, *args, **kwargs): # create django request resolver self.handler = BaseHandler() # prevent recursive includes old = settings.MIDDLEWARE name = self.__module__ + '.' + self.__class__.__name__ settings.MIDDLEWARE = [i for i in settings.MIDDLEWARE if i != name] self.handler.load_middleware() settings.MIDDLEWARE = old super(CommonMiddlewareAppendSlashWithoutRedirect, self).__init__(*args, **kwargs) def process_response(self, request, response): response = super(CommonMiddlewareAppendSlashWithoutRedirect, self).process_response(request, response) if isinstance(response, HttpSmartRedirectResponse): if not request.path.endswith('/'): request.path = request.path + '/' # we don't need query string in path_info because it's in request.GET already request.path_info = request.path response = self.handler.get_response(request) return response
class MessageSenderWorker(QueueProcessingWorker): def __init__(self): # type: () -> None super().__init__() self.redis_client = get_redis_client() self.handler = BaseHandler() self.handler.load_middleware() def consume(self, event): # type: (Mapping[str, Any]) -> None server_meta = event['server_meta'] environ = { 'REQUEST_METHOD': 'SOCKET', 'SCRIPT_NAME': '', 'PATH_INFO': '/json/messages', 'SERVER_NAME': '127.0.0.1', 'SERVER_PORT': 9993, 'SERVER_PROTOCOL': 'ZULIP_SOCKET/1.0', 'wsgi.version': (1, 0), 'wsgi.input': StringIO(), 'wsgi.errors': sys.stderr, 'wsgi.multithread': False, 'wsgi.multiprocess': True, 'wsgi.run_once': False, 'zulip.emulated_method': 'POST' } if 'socket_user_agent' in event['request']: environ['HTTP_USER_AGENT'] = event['request']['socket_user_agent'] del event['request']['socket_user_agent'] # We're mostly using a WSGIRequest for convenience environ.update(server_meta['request_environ']) request = WSGIRequest(environ) # Note: If we ever support non-POST methods, we'll need to change this. request._post = event['request'] request.csrf_processing_done = True user_profile = get_user_profile_by_id(server_meta['user_id']) request._cached_user = user_profile resp = self.handler.get_response(request) server_meta['time_request_finished'] = time.time() server_meta['worker_log_data'] = request._log_data resp_content = resp.content.decode('utf-8') response_data = ujson.loads(resp_content) if response_data['result'] == 'error': check_and_send_restart_signal() result = {'response': response_data, 'req_id': event['req_id'], 'server_meta': server_meta} redis_key = req_redis_key(event['req_id']) self.redis_client.hmset(redis_key, {'status': 'complete', 'response': resp_content}) queue_json_publish(server_meta['return_queue'], result, respond_send_message)
def test_plugins_middleware_requestor_in_plugin_when_no_app_and_user_in_req_is_none( rf, settings): settings.MIDDLEWARE = [ "saleor.core.middleware.plugins", ] settings.PLUGINS = ["saleor.plugins.tests.sample_plugins.ActivePlugin"] request = rf.request() request.user = None request.app = None handler = BaseHandler() handler.load_middleware() handler.get_response(request) plugin = request.plugins.all_plugins.pop() assert not plugin.requestor
def test_plugins_middleware_loads_requestor_in_plugin(rf, customer_user, settings): settings.MIDDLEWARE = [ "saleor.core.middleware.plugins", ] settings.PLUGINS = ["saleor.plugins.tests.sample_plugins.ActivePlugin"] request = rf.request() request.user = customer_user request.app = None handler = BaseHandler() handler.load_middleware() handler.get_response(request) plugin = request.plugins.all_plugins.pop() assert isinstance(plugin.requestor, type(customer_user)) assert plugin.requestor.id == customer_user.id
def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): handler = BaseHandler() handler.load_middleware() wsgi_request = self.prepared_request_to_wsgi_request(request) http_response = handler.get_response(wsgi_request) requests_response = self.http_response_to_response(http_response, request) return requests_response
def build_dummy_request(newsitem): """ Construct a HttpRequest object that is, as far as possible, representative of ones that would receive this page as a response. Used for previewing / moderation and any other place where we want to display a view of this page in the admin interface without going through the regular page routing logic. """ url = newsitem.full_url if url: url_info = urlparse(url) hostname = url_info.hostname path = url_info.path port = url_info.port or 80 else: # Cannot determine a URL to this page - cobble one together based on # whatever we find in ALLOWED_HOSTS try: hostname = settings.ALLOWED_HOSTS[0] except IndexError: hostname = 'localhost' path = '/' port = 80 request = WSGIRequest({ 'REQUEST_METHOD': 'GET', 'PATH_INFO': path, 'SERVER_NAME': hostname, 'SERVER_PORT': port, 'HTTP_HOST': hostname, 'wsgi.input': StringIO(), }) # Apply middleware to the request - see http://www.mellowmorning.com/2011/04/18/mock-django-request-for-testing/ handler = BaseHandler() handler.load_middleware() # call each middleware in turn and throw away any responses that they might return if hasattr(handler, '_request_middleware'): for middleware_method in handler._request_middleware: middleware_method(request) else: handler.get_response(request) return request
def test_error_handlers(rf): """ Test that SHUUP_FRONT_INSTALL_ERROR_HANDLERS installs error handlers without overwriting possible custom ones. """ with override_settings( DEBUG=False, SHUUP_FRONT_INSTALL_ERROR_HANDLERS=True, MIDDLEWARE_CLASSES=[], TEMPLATES= [ # Overriden to be sure about the contents of our 500.jinja { "BACKEND": "django_jinja.backend.Jinja2", "DIRS": [ os.path.realpath( os.path.join(os.path.dirname(__file__), "templates")) ], "OPTIONS": { "match_extension": ".jinja", "newstyle_gettext": True, }, "NAME": "jinja2", } ]): with replace_urls([url("^aaargh/", errorful_view)], {"handler404": four_oh_four}): resolver = get_resolver(None) urlconf = resolver.urlconf_module install_error_handlers() assert callable(urlconf.handler500) # We get a new 500 handler assert urlconf.handler404 == four_oh_four # Our custom 404 handler didn't get overwritten handler = BaseHandler() handler.load_middleware() # Test 500 response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 # Uh oh! assert "intergalactic testing 500" in force_text(response.content) # Test 404 response = handler.get_response(rf.get("/another_castle/")) assert response.status_code == 200 # Our custom 404 handler made it a 200! assert b"flesh wound" in response.content
class MessageSenderWorker(QueueProcessingWorker): def __init__(self): # type: () -> None super(MessageSenderWorker, self).__init__() self.redis_client = get_redis_client() self.handler = BaseHandler() self.handler.load_middleware() def consume(self, event): # type: (Mapping[str, Any]) -> None server_meta = event['server_meta'] environ = { 'REQUEST_METHOD': 'SOCKET', 'SCRIPT_NAME': '', 'PATH_INFO': '/json/messages', 'SERVER_NAME': 'localhost', 'SERVER_PORT': 9993, 'SERVER_PROTOCOL': 'ZULIP_SOCKET/1.0', 'wsgi.version': (1, 0), 'wsgi.input': StringIO(), 'wsgi.errors': sys.stderr, 'wsgi.multithread': False, 'wsgi.multiprocess': True, 'wsgi.run_once': False, 'zulip.emulated_method': 'POST' } # We're mostly using a WSGIRequest for convenience environ.update(server_meta['request_environ']) request = WSGIRequest(environ) request._request = event['request'] request.csrf_processing_done = True user_profile = get_user_profile_by_id(server_meta['user_id']) request._cached_user = user_profile resp = self.handler.get_response(request) server_meta['time_request_finished'] = time.time() server_meta['worker_log_data'] = request._log_data resp_content = resp.content.decode('utf-8') result = { 'response': ujson.loads(resp_content), 'req_id': event['req_id'], 'server_meta': server_meta } redis_key = req_redis_key(event['req_id']) self.redis_client.hmset(redis_key, { 'status': 'complete', 'response': resp_content }) queue_json_publish(server_meta['return_queue'], result, lambda e: None)
def test_error_handlers(rf): """ Test that SHUUP_FRONT_INSTALL_ERROR_HANDLERS installs error handlers without overwriting possible custom ones. """ with override_settings( DEBUG=False, SHUUP_FRONT_INSTALL_ERROR_HANDLERS=True, MIDDLEWARE_CLASSES=[], TEMPLATES=[ # Overriden to be sure about the contents of our 500.jinja { "BACKEND": "django_jinja.backend.Jinja2", "DIRS": [ os.path.realpath(os.path.join(os.path.dirname(__file__), "templates")) ], "OPTIONS": { "match_extension": ".jinja", "newstyle_gettext": True, }, "NAME": "jinja2", } ] ): with replace_urls([ url("^aaargh/", errorful_view) ], {"handler404": four_oh_four}): resolver = get_resolver(None) urlconf = resolver.urlconf_module install_error_handlers() assert callable(urlconf.handler500) # We get a new 500 handler assert urlconf.handler404 == four_oh_four # Our custom 404 handler didn't get overwritten handler = BaseHandler() handler.load_middleware() # Test 500 response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 # Uh oh! assert "intergalactic testing 500" in force_text(response.content) # Test 404 response = handler.get_response(rf.get("/another_castle/")) assert response.status_code == 200 # Our custom 404 handler made it a 200! assert b"flesh wound" in response.content
def test_jwt_refresh_token_middleware(rf, customer_user, settings): refresh_token = create_refresh_token(customer_user) settings.MIDDLEWARE = [ "saleor.core.middleware.jwt_refresh_token_middleware", ] request = rf.request() request.refresh_token = refresh_token handler = BaseHandler() handler.load_middleware() response = handler.get_response(request) cookie = response.cookies.get(JWT_REFRESH_TOKEN_COOKIE_NAME) assert cookie.value == refresh_token
def test_jwt_refresh_token_middleware_samesite_debug_mode(rf, customer_user, settings): refresh_token = create_refresh_token(customer_user) settings.MIDDLEWARE = [ "saleor.core.middleware.jwt_refresh_token_middleware", ] settings.DEBUG = True request = rf.request() request.refresh_token = refresh_token handler = BaseHandler() handler.load_middleware() response = handler.get_response(request) cookie = response.cookies.get(JWT_REFRESH_TOKEN_COOKIE_NAME) assert cookie["samesite"] == "Lax"
def initialize_context() -> HttpRequest: """Prepare a request object for webhook subscription. It creates a dummy request object and initialize middleware on it. It is required to process a request in the same way as API logic does. return: HttpRequest """ handler = BaseHandler() context = RequestFactory().request(SERVER_NAME=SimpleLazyObject(get_host)) handler.load_middleware() response = handler.get_response(context) if not response.status_code == 200: raise Exception("Unable to initialize context for webhook.") return context
class UrlConsumer(object): """ Dispatches channel HTTP requests into django's URL system. """ def __init__(self): self.handler = BaseHandler() self.handler.load_middleware() def __call__(self, channel, **kwargs): request = HttpRequest.channel_decode(kwargs) try: response = self.handler.get_response(request) except HttpResponse.ResponseLater: return Channel(request.response_channel).send(**response.channel_encode())
class UrlConsumer(object): """ Dispatches channel HTTP requests into django's URL system. """ def __init__(self): self.handler = BaseHandler() self.handler.load_middleware() def __call__(self, message): request = HttpRequest.channel_decode(message.content) try: response = self.handler.get_response(request) except HttpResponse.ResponseLater: return message.reply_channel.send(response.channel_encode())
class UrlConsumer(object): """ Dispatches channel HTTP requests into django's URL system. """ def __init__(self): self.handler = BaseHandler() self.handler.load_middleware() def __call__(self, channel, **kwargs): request = HttpRequest.channel_decode(kwargs) try: response = self.handler.get_response(request) except HttpResponse.ResponseLater: return Channel(request.response_channel).send(**response.channel_encode())
class MessageSenderWorker(QueueProcessingWorker): def __init__(self): # type: () -> None super(MessageSenderWorker, self).__init__() self.redis_client = get_redis_client() self.handler = BaseHandler() self.handler.load_middleware() def consume(self, event): # type: (Mapping[str, Any]) -> None server_meta = event['server_meta'] environ = {'REQUEST_METHOD': 'SOCKET', 'SCRIPT_NAME': '', 'PATH_INFO': '/json/messages', 'SERVER_NAME': 'localhost', 'SERVER_PORT': 9993, 'SERVER_PROTOCOL': 'ZULIP_SOCKET/1.0', 'wsgi.version': (1, 0), 'wsgi.input': StringIO(), 'wsgi.errors': sys.stderr, 'wsgi.multithread': False, 'wsgi.multiprocess': True, 'wsgi.run_once': False, 'zulip.emulated_method': 'POST'} # We're mostly using a WSGIRequest for convenience environ.update(server_meta['request_environ']) request = WSGIRequest(environ) request._request = event['request'] request.csrf_processing_done = True user_profile = get_user_profile_by_id(server_meta['user_id']) request._cached_user = user_profile resp = self.handler.get_response(request) server_meta['time_request_finished'] = time.time() server_meta['worker_log_data'] = request._log_data resp_content = resp.content.decode('utf-8') result = {'response': ujson.loads(resp_content), 'req_id': event['req_id'], 'server_meta': server_meta} redis_key = req_redis_key(event['req_id']) self.redis_client.hmset(redis_key, {'status': 'complete', 'response': resp_content}); queue_json_publish(server_meta['return_queue'], result, lambda e: None)
class CommonMiddlewareAppendSlashWithoutRedirect(CommonMiddleware): """ This class converts HttpSmartRedirectResponse to the common response of Django view, without redirect. This is necessary to match status_codes for urls like /url?q=1 and /url/?q=1. If you don't use it, you will have 302 code always on pages without slash. """ response_redirect_class = HttpSmartRedirectResponse def __init__(self, *args, **kwargs): # create django request resolver self.handler = BaseHandler() # prevent recursive includes old = settings.MIDDLEWARE name = self.__module__ + '.' + self.__class__.__name__ settings.MIDDLEWARE = [i for i in settings.MIDDLEWARE if i != name] self.handler.load_middleware() settings.MIDDLEWARE = old super(CommonMiddlewareAppendSlashWithoutRedirect, self).__init__(*args, **kwargs) def get_full_path_with_slash(self, request): """ Return the full path of the request with a trailing slash appended without Exception in Debug mode """ new_path = request.get_full_path(force_append_slash=True) # Prevent construction of scheme relative urls. new_path = escape_leading_slashes(new_path) return new_path def process_response(self, request, response): response = super(CommonMiddlewareAppendSlashWithoutRedirect, self).process_response(request, response) request.editor_keymap = settings.EDITOR_KEYMAP if isinstance(response, HttpSmartRedirectResponse): if not request.path.endswith('/'): # remove prefix SCRIPT_NAME path = request.path[len(settings.FORCE_SCRIPT_NAME):] if settings.FORCE_SCRIPT_NAME \ else request.path request.path = path + '/' # we don't need query string in path_info because it's in request.GET already request.path_info = request.path response = self.handler.get_response(request) return response
class Middleware404View(Buildable404View): def __init__(self, **kwargs): self.handler = BaseHandler() self.handler.load_middleware() super().__init__(**kwargs) def get(self, request): return self.handler.get_response(request) def get_content(self): response = self.get(self.request) if hasattr(response, 'render'): return response.render().content if hasattr(response, 'content'): return response.content raise AttributeError( "'%s' object has no attribute 'render' or 'content'" % response)
class MessageSenderWorker(QueueProcessingWorker): def __init__(self): super(MessageSenderWorker, self).__init__() self.redis_client = get_redis_client() self.handler = BaseHandler() self.handler.load_middleware() def consume(self, event): server_meta = event["server_meta"] environ = { "REQUEST_METHOD": "SOCKET", "SCRIPT_NAME": "", "PATH_INFO": "/json/messages", "SERVER_NAME": "localhost", "SERVER_PORT": 9993, "SERVER_PROTOCOL": "ZULIP_SOCKET/1.0", "wsgi.version": (1, 0), "wsgi.input": StringIO(), "wsgi.errors": sys.stderr, "wsgi.multithread": False, "wsgi.multiprocess": True, "wsgi.run_once": False, "zulip.emulated_method": "POST", } # We're mostly using a WSGIRequest for convenience environ.update(server_meta["request_environ"]) request = WSGIRequest(environ) request._request = event["request"] request.csrf_processing_done = True user_profile = get_user_profile_by_id(server_meta["user_id"]) request._cached_user = user_profile resp = self.handler.get_response(request) server_meta["time_request_finished"] = time.time() server_meta["worker_log_data"] = request._log_data resp_content = resp.content result = {"response": ujson.loads(resp_content), "req_id": event["req_id"], "server_meta": server_meta} redis_key = req_redis_key(event["req_id"]) self.redis_client.hmset(redis_key, {"status": "complete", "response": resp_content}) queue_json_publish(server_meta["return_queue"], result, lambda e: None)
def get_response(self, request): # Set up middleware if needed. We couldn't do this earlier, because # settings weren't available. if self._request_middleware is None: self.initLock.acquire() try: try: # Check that middleware is still uninitialised. if self._request_middleware is None: self.load_middleware() except: # Unload whatever middleware we got self._request_middleware = None raise finally: self.initLock.release() return BaseHandler.get_response(self, request)
def get_response(self, request): # Set up middleware if needed. We couldn't do this earlier, because # settings weren't available. if self._request_middleware is None: self.initLock.acquire() try: try: # Check that middleware is still uninitialised. if self._request_middleware is None: self.load_middleware() except: # Unload whatever middleware we got self._request_middleware = None raise finally: self.initLock.release() return BaseHandler.get_response(self, request)
def test_jwt_refresh_token_middleware_token_without_expire(rf, customer_user, settings): settings.JWT_EXPIRE = True payload = jwt_user_payload( customer_user, JWT_REFRESH_TYPE, settings.JWT_TTL_REFRESH, ) del payload["exp"] refresh_token = jwt_encode(payload) settings.MIDDLEWARE = [ "saleor.core.middleware.jwt_refresh_token_middleware", ] request = rf.request() request.refresh_token = refresh_token handler = BaseHandler() handler.load_middleware() response = handler.get_response(request) cookie = response.cookies.get(JWT_REFRESH_TOKEN_COOKIE_NAME) assert cookie.value == refresh_token
def consume_request(self, request, start_callback=None, success_callback=None, fail_callback=None): start_callback() if start_callback else None handler = BaseHandler() handler.load_middleware() response = handler.get_response(request) if is_success(response.status_code): success_callback() if success_callback else None else: fail_callback() if fail_callback else None self.responses[request] = response return True
def process_request(self, request): """Replicates a lot of code from BaseHandler#get_response.""" # Setup URL resolver urlconf = settings.ROOT_URLCONF urlresolvers.set_urlconf(urlconf) resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) callback, callback_args, \ callback_kwargs = resolver.resolve(request.path_info) if getattr(callback, 'bypass_middleware', False): # bypass_middleware decorator was used; zero out all # middleware and return the response. handler = BaseHandler() handler._request_middleware = [] handler._view_middleware = [] handler._template_response_middleware = [] handler._response_middleware = [] handler._exception_middleware = [] response = handler.get_response(request) return response
def test_front_error_handlers(rf): """ Test that `SHUUP_ERROR_PAGE_HANDLERS_SPEC` installs error handlers that are overwriting custom ones. """ with override_settings( DEBUG=False, SHUUP_ERROR_PAGE_HANDLERS_SPEC=[ "shuup.front.error_handlers.FrontPageErrorHandler" ], MIDDLEWARE_CLASSES=[], # For Django < 2 MIDDLEWARE=[], TEMPLATES= [ # Overriden to be sure about the contents of our 500.jinja { "BACKEND": "django_jinja.backend.Jinja2", "DIRS": [ os.path.realpath( os.path.join(os.path.dirname(__file__), "templates")) ], "OPTIONS": { "match_extension": ".jinja", "newstyle_gettext": True, }, "NAME": "jinja2", } ]): with replace_urls([ url("^aaargh/", errorful_view), url("^notfound/", notfound_view), url("^dash/", DashboardView.as_view()), url("^index/", IndexView.as_view()), ], { "handler404": four_oh_four, "handler500": handler500 }): resolver = get_resolver(None) urlconf = resolver.urlconf_module handler = BaseHandler() handler.load_middleware() # test without installing the handler assert urlconf.handler404 == four_oh_four assert urlconf.handler500 == handler500 # Test 500 response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 assert b"The best error" in response.content # Test 404 response = handler.get_response(rf.get("/another_castle/")) assert response.status_code == 404 assert b"flesh wound" in response.content # inject our custom error handlers install_error_handlers() assert urlconf.handler404 != four_oh_four assert urlconf.handler500 != handler500 assert "miss something? 404" in force_text( urlconf.handler404(rf.get("/notfound/")).content) assert "intergalactic testing 500" in force_text( urlconf.handler500(rf.get("/aaargh/")).content) # Front must handle all possible apps error_handler = FrontPageErrorHandler() response = handler.get_response(rf.get("/aaargh/")) assert "intergalactic testing 500" in force_text(response.content) # simulate a view to check whether the handler can handle an # error of a non-front view, a front view and a admin view for path in ("/aaargh/", "/index/", "/dash/"): request = rf.get(path) assert error_handler.can_handle_error(request, 500) assert error_handler.can_handle_error(request, 400) assert error_handler.can_handle_error(request, 403) assert error_handler.can_handle_error(request, 404) # check the error handlers return the correct status and text for status, content in [ (500, "intergalactic testing 500"), (400, "about 400"), (403, "get out 403"), (404, "miss something? 404"), ]: response = error_handler.handle_error(request, status) assert response.status_code == status assert content in force_text(response.content) from django.conf import settings # front can't handle static and media paths for path in (settings.STATIC_URL + "mystaticfile", settings.MEDIA_URL + "mymediafile"): request = rf.get(path) assert error_handler.can_handle_error(request, 500) is False assert error_handler.can_handle_error(request, 400) is False assert error_handler.can_handle_error(request, 403) is False assert error_handler.can_handle_error(request, 404) is False
def test_install_error_handlers(rf): # no error handler set with override_settings(DEBUG=False, SHUUP_ERROR_PAGE_HANDLERS_SPEC=[], MIDDLEWARE_CLASSES=[], MIDDLEWARE=[]): def intact_view(request, *args, **kwargs): return HttpResponse("OK") # set handlers in root urlconf with replace_urls( [ url("^/", intact_view), ], { "handler400": intact_view, "handler403": intact_view, "handler404": intact_view, "handler500": intact_view }): # install error handlers - as soon as no spec was set, # the handlers must return the same as the default handlers install_error_handlers() resolver = get_resolver(None) urlconf = resolver.urlconf_module assert urlconf.handler500 != intact_view assert urlconf.handler400 != intact_view assert urlconf.handler403 != intact_view assert urlconf.handler404 != intact_view request = rf.get("/") assert urlconf.handler400(request).content == intact_view( request).content assert urlconf.handler403(request).content == intact_view( request).content assert urlconf.handler404(request).content == intact_view( request).content assert urlconf.handler500(request).content == intact_view( request).content # force clear again import shuup.core.error_handling as error_handling error_handling._URLCONF_ERROR_HANDLERS.clear() # NO handler set in root urlconf with replace_urls([ url("^aaargh/", errorful_view), url("^notfound/", notfound_view), ], {}): # install error handlers - as soon as no spec was set, # neither handlers set in urlconf, must return blank http responses with errors install_error_handlers() resolver = get_resolver(None) urlconf = resolver.urlconf_module request = rf.get("/") assert urlconf.handler400(request).status_code == 400 assert urlconf.handler403(request).status_code == 403 assert urlconf.handler404(request).status_code == 404 assert urlconf.handler500(request).status_code == 500 handler = BaseHandler() handler.load_middleware() response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 response = handler.get_response(rf.get("/notfound/")) assert response.status_code == 404
def test_admin_error_handlers(rf): """ Test that SHUUP_ERROR_PAGE_HANDLERS_SPEC installs error handlers that are overwriting custom ones. """ with override_settings( DEBUG=False, SHUUP_ERROR_PAGE_HANDLERS_SPEC=[ "shuup.admin.error_handlers.AdminPageErrorHandler" ], MIDDLEWARE_CLASSES=[], # For Django 2 MIDDLEWARE=[], TEMPLATES= [ # Overriden to be sure about the contents of our 500.jinja { "BACKEND": "django_jinja.backend.Jinja2", "DIRS": [ os.path.realpath( os.path.join(os.path.dirname(__file__), "templates")) ], "OPTIONS": { "match_extension": ".jinja", "newstyle_gettext": True, }, "NAME": "jinja2", } ]): with replace_urls([ url("^aaargh/", errorful_view), url("^index/", IndexView.as_view()), url("^dash/", DashboardView.as_view()), ], { "handler404": four_oh_four, "handler500": handler500 }): resolver = get_resolver(None) urlconf = resolver.urlconf_module handler = BaseHandler() handler.load_middleware() # test without installing the handler assert urlconf.handler404 == four_oh_four assert urlconf.handler500 == handler500 # Test 500 response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 assert b"The best error" in response.content # Test 404 response = handler.get_response(rf.get("/another_castle/")) assert response.status_code == 404 assert b"flesh wound" in response.content # inject our custom error handlers install_error_handlers() # here the urlconfs will be the default handlers # because admin can't handle such requests # but the functions of the handlers are pointing to our factory view assert urlconf.handler404 != four_oh_four assert urlconf.handler500 != handler500 assert "flesh wound" in force_text( urlconf.handler404(rf.get("/notfound/")).content) assert "The best error" in force_text( urlconf.handler500(rf.get("/aaargh/")).content) # Admin must handle only admin app errors error_handler = AdminPageErrorHandler() # simulate a view to check whether the handler can handle an error of a non-front view # Admin handler will check for the resolver_match and admin app only response = handler.get_response(rf.get("/aaargh/")) assert b"The best error" in response.content # can't handle non admin views neither media or static files from django.conf import settings for path in ("/aaargh/", "/index/", settings.STATIC_URL + "mystaticfile", settings.MEDIA_URL + "mymediafile"): request = rf.get(path) assert error_handler.can_handle_error(request, 500) is False assert error_handler.can_handle_error(request, 400) is False assert error_handler.can_handle_error(request, 403) is False assert error_handler.can_handle_error(request, 404) is False # simulate a view to check whether the handler can handle an error of an admin view request = rf.get("/dash/") assert error_handler.can_handle_error(request, 500) is False assert error_handler.can_handle_error(request, 400) is False assert error_handler.can_handle_error(request, 403) is False assert error_handler.can_handle_error(request, 404) is False # check the error handlers return the correct status and text for status, content in [ (500, "admin 500"), (400, "admin 400"), (403, "admin 403"), (404, "admin 404"), ]: response = error_handler.handle_error(request, status) assert response.status_code == status assert content in force_text(response.content)
def test_front_error_handlers(rf): """ Test that SHUUP_ERROR_PAGE_HANDLERS_SPEC installs error handlers overwriting custom ones """ with override_settings( DEBUG=False, SHUUP_ERROR_PAGE_HANDLERS_SPEC=["shuup.front.error_handlers.FrontPageErrorHandler"], MIDDLEWARE_CLASSES=[], TEMPLATES=[ # Overriden to be sure about the contents of our 500.jinja { "BACKEND": "django_jinja.backend.Jinja2", "DIRS": [ os.path.realpath(os.path.join(os.path.dirname(__file__), "templates")) ], "OPTIONS": { "match_extension": ".jinja", "newstyle_gettext": True, }, "NAME": "jinja2", } ] ): with replace_urls([ url("^aaargh/", errorful_view), url("^notfound/", notfound_view), url("^dash/", DashboardView.as_view()), url("^index/", IndexView.as_view()), ], {"handler404": four_oh_four, "handler500": handler500}): resolver = get_resolver(None) urlconf = resolver.urlconf_module handler = BaseHandler() handler.load_middleware() # test without installing the handler assert urlconf.handler404 == four_oh_four assert urlconf.handler500 == handler500 # Test 500 response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 assert b"The best error" in response.content # Test 404 response = handler.get_response(rf.get("/another_castle/")) assert response.status_code == 404 assert b"flesh wound" in response.content # inject our custom error handlers install_error_handlers() assert urlconf.handler404 != four_oh_four assert urlconf.handler500 != handler500 assert "miss something? 404" in force_text(urlconf.handler404(rf.get("/notfound/")).content) assert "intergalactic testing 500" in force_text(urlconf.handler500(rf.get("/aaargh/")).content) # Front must handle all possible apps error_handler = FrontPageErrorHandler() response = handler.get_response(rf.get("/aaargh/")) assert "intergalactic testing 500" in force_text(response.content) # simulate a view to check whether the handler can handle an # error of a non-front view, a front view and a admin view for path in ("/aaargh/", "/index/", "/dash/"): request = rf.get(path) assert error_handler.can_handle_error(request, 500) assert error_handler.can_handle_error(request, 400) assert error_handler.can_handle_error(request, 403) assert error_handler.can_handle_error(request, 404) # check the error handlers return the correct status and text for status, content in [ (500, "intergalactic testing 500"), (400, "about 400"), (403, "get out 403"), (404, "miss something? 404"), ]: response = error_handler.handle_error(request, status) assert response.status_code == status assert content in force_text(response.content) from django.conf import settings # front can't handle static and media paths for path in (settings.STATIC_URL + "mystaticfile", settings.MEDIA_URL + "mymediafile"): request = rf.get(path) assert error_handler.can_handle_error(request, 500) is False assert error_handler.can_handle_error(request, 400) is False assert error_handler.can_handle_error(request, 403) is False assert error_handler.can_handle_error(request, 404) is False
def test_install_error_handlers(rf): # no error handler set with override_settings(DEBUG=False, SHUUP_ERROR_PAGE_HANDLERS_SPEC=[], MIDDLEWARE_CLASSES=[]): def intact_view(request, *args, **kwargs): return HttpResponse("OK") # set handlers in root urlconf with replace_urls([url("^/", intact_view),], { "handler400": intact_view, "handler403": intact_view, "handler404": intact_view, "handler500": intact_view }): # install error handlers - as soon as no spec was set, # the handlers must return the same as the default handlers install_error_handlers() resolver = get_resolver(None) urlconf = resolver.urlconf_module assert urlconf.handler500 != intact_view assert urlconf.handler400 != intact_view assert urlconf.handler403 != intact_view assert urlconf.handler404 != intact_view request = rf.get("/") assert urlconf.handler400(request).content == intact_view(request).content assert urlconf.handler403(request).content == intact_view(request).content assert urlconf.handler404(request).content == intact_view(request).content assert urlconf.handler500(request).content == intact_view(request).content # force clear again import shuup.core.error_handling as error_handling error_handling._URLCONF_ERROR_HANDLERS.clear() # NO handler set in root urlconf with replace_urls([ url("^aaargh/", errorful_view), url("^notfound/", notfound_view), ], {}): # install error handlers - as soon as no spec was set, # neither handlers set in urlconf, must return blank http responses with errors install_error_handlers() resolver = get_resolver(None) urlconf = resolver.urlconf_module request = rf.get("/") assert urlconf.handler400(request).status_code == 400 assert urlconf.handler403(request).status_code == 403 assert urlconf.handler404(request).status_code == 404 assert urlconf.handler500(request).status_code == 500 handler = BaseHandler() handler.load_middleware() response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 response = handler.get_response(rf.get("/notfound/")) assert response.status_code == 404
def test_admin_error_handlers(rf): """ Test that SHUUP_ERROR_PAGE_HANDLERS_SPEC installs error handlers overwriting custom ones """ with override_settings( DEBUG=False, SHUUP_ERROR_PAGE_HANDLERS_SPEC=["shuup.admin.error_handlers.AdminPageErrorHandler"], MIDDLEWARE_CLASSES=[], TEMPLATES=[ # Overriden to be sure about the contents of our 500.jinja { "BACKEND": "django_jinja.backend.Jinja2", "DIRS": [ os.path.realpath(os.path.join(os.path.dirname(__file__), "templates")) ], "OPTIONS": { "match_extension": ".jinja", "newstyle_gettext": True, }, "NAME": "jinja2", } ] ): with replace_urls([ url("^aaargh/", errorful_view), url("^index/", IndexView.as_view()), url("^dash/", DashboardView.as_view()), ], {"handler404": four_oh_four, "handler500": handler500}): resolver = get_resolver(None) urlconf = resolver.urlconf_module handler = BaseHandler() handler.load_middleware() # test without installing the handler assert urlconf.handler404 == four_oh_four assert urlconf.handler500 == handler500 # Test 500 response = handler.get_response(rf.get("/aaargh/")) assert response.status_code == 500 assert b"The best error" in response.content # Test 404 response = handler.get_response(rf.get("/another_castle/")) assert response.status_code == 404 assert b"flesh wound" in response.content # inject our custom error handlers install_error_handlers() # here the urlconfs will be the default handlers # because admin can't handle such requests # but the functions of the handlers are pointing to our factory view assert urlconf.handler404 != four_oh_four assert urlconf.handler500 != handler500 assert "flesh wound" in force_text(urlconf.handler404(rf.get("/notfound/")).content) assert "The best error" in force_text(urlconf.handler500(rf.get("/aaargh/")).content) # Admin must handle only admin app errors error_handler = AdminPageErrorHandler() # simulate a view to check whether the handler can handle an error of a non-front view # Admin handler will check for the resolver_match and admin app only response = handler.get_response(rf.get("/aaargh/")) assert b"The best error" in response.content # can't handle non admin views neither media or static files from django.conf import settings for path in ("/aaargh/", "/index/", settings.STATIC_URL + "mystaticfile", settings.MEDIA_URL + "mymediafile"): request = rf.get(path) assert error_handler.can_handle_error(request, 500) is False assert error_handler.can_handle_error(request, 400) is False assert error_handler.can_handle_error(request, 403) is False assert error_handler.can_handle_error(request, 404) is False # simulate a view to check whether the handler can handle an error of an admin view request = rf.get("/dash/") assert error_handler.can_handle_error(request, 500) is False assert error_handler.can_handle_error(request, 400) is False assert error_handler.can_handle_error(request, 403) is False assert error_handler.can_handle_error(request, 404) is False # check the error handlers return the correct status and text for status, content in [ (500, "admin 500"), (400, "admin 400"), (403, "admin 403"), (404, "admin 404"), ]: response = error_handler.handle_error(request, status) assert response.status_code == status assert content in force_text(response.content)
class WagtailBakeryView(BuildableDetailView): """ An abstract class that can be inherited to create a buildable view that can be added to BAKERY_VIEWS setting. """ def __init__(self, *args, **kwargs): self.handler = BaseHandler() self.handler.load_middleware() super(WagtailBakeryView, self).__init__(*args, **kwargs) def get(self, request): response = self.handler.get_response(request) return response def get_content(self, obj): response = self.get(self.request) if isinstance(response, HttpResponseRedirect): return self.get_redirect_content(response, obj) if hasattr(response, 'render'): return response.render().content if hasattr(response, 'content'): return response.content raise AttributeError( "'%s' object has no attribute 'render' or 'content'" % response) def get_redirect_content(self, response, obj): context = { 'page': obj, 'self': obj, 'redirect_url': response.url, } content = render( self.request, 'wagtailbakery/redirect.html', context).content return response.make_bytes(content) def get_build_path(self, obj): url = self.get_url(obj) if url.startswith('http'): # Multisite has absolute urls url_parsed = urlparse(url) path = url_parsed.path hostname = url_parsed.hostname if getattr(settings, 'BAKERY_MULTISITE', False): build_path = os.path.join( settings.BUILD_DIR, hostname, path[1:]) else: build_path = os.path.join(settings.BUILD_DIR, path[1:]) else: # Single site has relative urls build_path = os.path.join(settings.BUILD_DIR, url[1:]) # Make sure the (deeply) directories are created os.path.exists(build_path) or os.makedirs(build_path) # Always append index.html at the end of the path return os.path.join(build_path, 'index.html') def get_url(self, obj): """Return Wagtail page url instead of Django's get_absolute_url.""" return obj.url def get_path(self, obj): """Return Wagtail path to page.""" return obj.path def build_object(self, obj): """ Build wagtail page and set SERVER_NAME to retrieve corresponding site object. """ site = obj.get_site() logger.debug("Building %s" % obj) self.request = RequestFactory( SERVER_NAME=site.hostname).get(self.get_url(obj)) self.set_kwargs(obj) path = self.get_build_path(obj) self.build_file(path, self.get_content(obj)) def build_queryset(self): for item in self.get_queryset().all(): url = self.get_url(item) if url is not None: self.build_object(item) class Meta: abstract = True
class WagtailBakeryView(BuildableDetailView): """ An abstract class that can be inherited to create a buildable view that can be added to BAKERY_VIEWS setting. """ def __init__(self, *args, **kwargs): self.handler = BaseHandler() self.handler.load_middleware() self.site = self.get_site() super(WagtailBakeryView, self).__init__(*args, **kwargs) def get(self, request): response = self.handler.get_response(request) return response def get_site(self): """Return the site were to build the static pages from. By default this is the site marked as default with `is_default_site` set to `true`. In case of a multisite setup this site object will be ignored. Example: def get_site(self): return Site.objects.get(hostname='website.com') """ return Site.objects.get(is_default_site=True) def get_build_path(self, obj): url = self.get_url(obj) if url.startswith('http'): url_parsed = urlparse(url) path = url_parsed.path hostname = url_parsed.hostname build_path = os.path.join(settings.BUILD_DIR, hostname, path[1:]) else: build_path = os.path.join(settings.BUILD_DIR, url[1:]) # Make sure the (deeply) directories are created os.path.exists(build_path) or os.makedirs(build_path) # Always append index.html at the end of the path return os.path.join(build_path, 'index.html') def get_url(self, obj): """Return Wagtail page url instead of Django's get_absolute_url.""" return obj.url def get_path(self, obj): """Return Wagtail path to page.""" return obj.path def build_queryset(self): for item in self.get_queryset().all(): if self.get_url(item) is not None: self.build_object(item) class Meta: abstract = True