mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 13:33:24 +00:00
request: Move miscellaneous attributes to ZulipRequestNotes.
This includes the migration of fields that require trivial changes to be migrated to be stored with ZulipRequestNotes. Specifically _requestor_for_logs, _set_language, _query, error_format, placeholder_open_graph_description, saveed_response, which were all previously set on the HttpRequest object at some point. This migration allows them to be typed.
This commit is contained in:
@@ -84,10 +84,11 @@ def update_user_activity(
|
|||||||
if request.META["PATH_INFO"] == "/json/users/me/presence":
|
if request.META["PATH_INFO"] == "/json/users/me/presence":
|
||||||
return
|
return
|
||||||
|
|
||||||
|
request_notes = get_request_notes(request)
|
||||||
if query is not None:
|
if query is not None:
|
||||||
pass
|
pass
|
||||||
elif hasattr(request, "_query"):
|
elif request_notes.query is not None:
|
||||||
query = request._query
|
query = request_notes.query
|
||||||
else:
|
else:
|
||||||
query = request.META["PATH_INFO"]
|
query = request.META["PATH_INFO"]
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ def require_post(func: ViewFuncT) -> ViewFuncT:
|
|||||||
request.path,
|
request.path,
|
||||||
extra={"status_code": 405, "request": request},
|
extra={"status_code": 405, "request": request},
|
||||||
)
|
)
|
||||||
if request.error_format == "JSON":
|
if get_request_notes(request).error_format == "JSON":
|
||||||
return json_method_not_allowed(["POST"])
|
return json_method_not_allowed(["POST"])
|
||||||
else:
|
else:
|
||||||
return TemplateResponse(
|
return TemplateResponse(
|
||||||
@@ -442,7 +443,7 @@ def do_login(request: HttpRequest, user_profile: UserProfile) -> None:
|
|||||||
def log_view_func(view_func: ViewFuncT) -> ViewFuncT:
|
def log_view_func(view_func: ViewFuncT) -> ViewFuncT:
|
||||||
@wraps(view_func)
|
@wraps(view_func)
|
||||||
def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
|
def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
|
||||||
request._query = view_func.__name__
|
get_request_notes(request).query = view_func.__name__
|
||||||
return view_func(request, *args, **kwargs)
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
|
return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ from django.conf import settings
|
|||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
|
|
||||||
|
from zerver.lib.request import get_request_notes
|
||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def get_language_list() -> List[Dict[str, Any]]:
|
def get_language_list() -> List[Dict[str, Any]]:
|
||||||
@@ -62,6 +64,6 @@ def get_and_set_request_language(
|
|||||||
# something reasonable will happen in logged-in portico pages.
|
# something reasonable will happen in logged-in portico pages.
|
||||||
# We accomplish that by setting a flag on the request which signals
|
# We accomplish that by setting a flag on the request which signals
|
||||||
# to LocaleMiddleware to set the cookie on the response.
|
# to LocaleMiddleware to set the cookie on the response.
|
||||||
request._set_language = translation.get_language()
|
get_request_notes(request).set_language = translation.get_language()
|
||||||
|
|
||||||
return request_language
|
return request_language
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from zerver.decorator import (
|
|||||||
process_as_post,
|
process_as_post,
|
||||||
)
|
)
|
||||||
from zerver.lib.exceptions import MissingAuthenticationError
|
from zerver.lib.exceptions import MissingAuthenticationError
|
||||||
|
from zerver.lib.request import get_request_notes
|
||||||
from zerver.lib.response import json_method_not_allowed
|
from zerver.lib.response import json_method_not_allowed
|
||||||
from zerver.lib.types import ViewFuncT
|
from zerver.lib.types import ViewFuncT
|
||||||
|
|
||||||
@@ -66,11 +67,11 @@ def rest_dispatch(request: HttpRequest, **kwargs: Any) -> HttpResponse:
|
|||||||
etc, as that is where we route HTTP verbs to target functions.
|
etc, as that is where we route HTTP verbs to target functions.
|
||||||
"""
|
"""
|
||||||
supported_methods: Dict[str, Any] = {}
|
supported_methods: Dict[str, Any] = {}
|
||||||
|
request_notes = get_request_notes(request)
|
||||||
if hasattr(request, "saved_response"):
|
if request_notes.saved_response is not None:
|
||||||
# For completing long-polled Tornado requests, we skip the
|
# For completing long-polled Tornado requests, we skip the
|
||||||
# view function logic and just return the response.
|
# view function logic and just return the response.
|
||||||
return request.saved_response
|
return request_notes.saved_response
|
||||||
|
|
||||||
# duplicate kwargs so we can mutate the original as we go
|
# duplicate kwargs so we can mutate the original as we go
|
||||||
for arg in list(kwargs):
|
for arg in list(kwargs):
|
||||||
@@ -99,9 +100,9 @@ def rest_dispatch(request: HttpRequest, **kwargs: Any) -> HttpResponse:
|
|||||||
target_function = supported_methods[method_to_use]
|
target_function = supported_methods[method_to_use]
|
||||||
view_flags = set()
|
view_flags = set()
|
||||||
|
|
||||||
# Set request._query for update_activity_user(), which is called
|
# Set request_notes.query for update_activity_user(), which is called
|
||||||
# by some of the later wrappers.
|
# by some of the later wrappers.
|
||||||
request._query = target_function.__name__
|
request_notes.query = target_function.__name__
|
||||||
|
|
||||||
# We want to support authentication by both cookies (web client)
|
# We want to support authentication by both cookies (web client)
|
||||||
# and API keys (API clients). In the former case, we want to
|
# and API keys (API clients). In the former case, we want to
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ class LogRequests(MiddlewareMixin):
|
|||||||
if request_notes.log_data is not None:
|
if request_notes.log_data is not None:
|
||||||
# Sanity check to ensure this is being called from the
|
# Sanity check to ensure this is being called from the
|
||||||
# Tornado code path that returns responses asynchronously.
|
# Tornado code path that returns responses asynchronously.
|
||||||
assert getattr(request, "saved_response", False)
|
assert request_notes.saved_response is not None
|
||||||
|
|
||||||
# Avoid re-initializing request_notes.log_data if it's already there.
|
# Avoid re-initializing request_notes.log_data if it's already there.
|
||||||
return
|
return
|
||||||
@@ -363,7 +363,7 @@ class LogRequests(MiddlewareMixin):
|
|||||||
kwargs: Dict[str, Any],
|
kwargs: Dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
request_notes = get_request_notes(request)
|
request_notes = get_request_notes(request)
|
||||||
if hasattr(request, "saved_response"):
|
if request_notes.saved_response is not None:
|
||||||
# The below logging adjustments are unnecessary (because
|
# The below logging adjustments are unnecessary (because
|
||||||
# we've already imported everything) and incorrect
|
# we've already imported everything) and incorrect
|
||||||
# (because they'll overwrite data from pre-long-poll
|
# (because they'll overwrite data from pre-long-poll
|
||||||
@@ -458,7 +458,7 @@ class JsonErrorHandler(MiddlewareMixin):
|
|||||||
|
|
||||||
if isinstance(exception, JsonableError):
|
if isinstance(exception, JsonableError):
|
||||||
return json_response_from_error(exception)
|
return json_response_from_error(exception)
|
||||||
if request.error_format == "JSON":
|
if get_request_notes(request).error_format == "JSON":
|
||||||
capture_exception(exception)
|
capture_exception(exception)
|
||||||
json_error_logger = logging.getLogger("zerver.middleware.json_error_handler")
|
json_error_logger = logging.getLogger("zerver.middleware.json_error_handler")
|
||||||
json_error_logger.error(traceback.format_exc(), extra=dict(request=request))
|
json_error_logger.error(traceback.format_exc(), extra=dict(request=request))
|
||||||
@@ -474,9 +474,9 @@ class TagRequests(MiddlewareMixin):
|
|||||||
|
|
||||||
def process_request(self, request: HttpRequest) -> None:
|
def process_request(self, request: HttpRequest) -> None:
|
||||||
if request.path.startswith("/api/") or request.path.startswith("/json/"):
|
if request.path.startswith("/api/") or request.path.startswith("/json/"):
|
||||||
request.error_format = "JSON"
|
get_request_notes(request).error_format = "JSON"
|
||||||
else:
|
else:
|
||||||
request.error_format = "HTML"
|
get_request_notes(request).error_format = "HTML"
|
||||||
|
|
||||||
|
|
||||||
class CsrfFailureError(JsonableError):
|
class CsrfFailureError(JsonableError):
|
||||||
@@ -493,7 +493,7 @@ class CsrfFailureError(JsonableError):
|
|||||||
|
|
||||||
|
|
||||||
def csrf_failure(request: HttpRequest, reason: str = "") -> HttpResponse:
|
def csrf_failure(request: HttpRequest, reason: str = "") -> HttpResponse:
|
||||||
if request.error_format == "JSON":
|
if get_request_notes(request).error_format == "JSON":
|
||||||
return json_response_from_error(CsrfFailureError(reason))
|
return json_response_from_error(CsrfFailureError(reason))
|
||||||
else:
|
else:
|
||||||
return html_csrf_failure(request, reason)
|
return html_csrf_failure(request, reason)
|
||||||
@@ -516,9 +516,10 @@ class LocaleMiddleware(DjangoLocaleMiddleware):
|
|||||||
|
|
||||||
# An additional responsibility of our override of this middleware is to save the user's language
|
# An additional responsibility of our override of this middleware is to save the user's language
|
||||||
# preference in a cookie. That determination is made by code handling the request
|
# preference in a cookie. That determination is made by code handling the request
|
||||||
# and saved in the _set_language flag so that it can be used here.
|
# and saved in the set_language flag so that it can be used here.
|
||||||
if hasattr(request, "_set_language"):
|
set_language = get_request_notes(request).set_language
|
||||||
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, request._set_language)
|
if set_language is not None:
|
||||||
|
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, set_language)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@@ -611,8 +612,12 @@ class SetRemoteAddrFromRealIpHeader(MiddlewareMixin):
|
|||||||
|
|
||||||
def alter_content(request: HttpRequest, content: bytes) -> bytes:
|
def alter_content(request: HttpRequest, content: bytes) -> bytes:
|
||||||
first_paragraph_text = get_content_description(content, request)
|
first_paragraph_text = get_content_description(content, request)
|
||||||
|
placeholder_open_graph_description = get_request_notes(
|
||||||
|
request
|
||||||
|
).placeholder_open_graph_description
|
||||||
|
assert placeholder_open_graph_description is not None
|
||||||
return content.replace(
|
return content.replace(
|
||||||
request.placeholder_open_graph_description.encode("utf-8"),
|
placeholder_open_graph_description.encode("utf-8"),
|
||||||
first_paragraph_text.encode("utf-8"),
|
first_paragraph_text.encode("utf-8"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -622,7 +627,7 @@ class FinalizeOpenGraphDescription(MiddlewareMixin):
|
|||||||
self, request: HttpRequest, response: StreamingHttpResponse
|
self, request: HttpRequest, response: StreamingHttpResponse
|
||||||
) -> StreamingHttpResponse:
|
) -> StreamingHttpResponse:
|
||||||
|
|
||||||
if getattr(request, "placeholder_open_graph_description", None) is not None:
|
if get_request_notes(request).placeholder_open_graph_description is not None:
|
||||||
assert not response.streaming
|
assert not response.streaming
|
||||||
response.content = alter_content(request, response.content)
|
response.content = alter_content(request, response.content)
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
|||||||
# request/middleware system to run unmodified while avoiding
|
# request/middleware system to run unmodified while avoiding
|
||||||
# running expensive things like Zulip's authentication code a
|
# running expensive things like Zulip's authentication code a
|
||||||
# second time.
|
# second time.
|
||||||
request.saved_response = json_response(
|
request_notes.saved_response = json_response(
|
||||||
res_type=result_dict["result"], data=result_dict, status=self.get_status()
|
res_type=result_dict["result"], data=result_dict, status=self.get_status()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from django.views.generic import TemplateView
|
|||||||
from zerver.context_processors import zulip_default_context
|
from zerver.context_processors import zulip_default_context
|
||||||
from zerver.decorator import add_google_analytics_context
|
from zerver.decorator import add_google_analytics_context
|
||||||
from zerver.lib.integrations import CATEGORIES, INTEGRATIONS, HubotIntegration, WebhookIntegration
|
from zerver.lib.integrations import CATEGORIES, INTEGRATIONS, HubotIntegration, WebhookIntegration
|
||||||
from zerver.lib.request import REQ, has_request_variables
|
from zerver.lib.request import REQ, get_request_notes, has_request_variables
|
||||||
from zerver.lib.subdomains import get_subdomain
|
from zerver.lib.subdomains import get_subdomain
|
||||||
from zerver.lib.templates import render_markdown_path
|
from zerver.lib.templates import render_markdown_path
|
||||||
from zerver.models import Realm
|
from zerver.models import Realm
|
||||||
@@ -168,10 +168,11 @@ class MarkdownDirectoryView(ApiURLView):
|
|||||||
context["OPEN_GRAPH_TITLE"] = f"{article_title} ({title_base})"
|
context["OPEN_GRAPH_TITLE"] = f"{article_title} ({title_base})"
|
||||||
else:
|
else:
|
||||||
context["OPEN_GRAPH_TITLE"] = title_base
|
context["OPEN_GRAPH_TITLE"] = title_base
|
||||||
self.request.placeholder_open_graph_description = (
|
request_notes = get_request_notes(self.request)
|
||||||
|
request_notes.placeholder_open_graph_description = (
|
||||||
f"REPLACMENT_OPEN_GRAPH_DESCRIPTION_{int(2**24 * random.random())}"
|
f"REPLACMENT_OPEN_GRAPH_DESCRIPTION_{int(2**24 * random.random())}"
|
||||||
)
|
)
|
||||||
context["OPEN_GRAPH_DESCRIPTION"] = self.request.placeholder_open_graph_description
|
context["OPEN_GRAPH_DESCRIPTION"] = request_notes.placeholder_open_graph_description
|
||||||
|
|
||||||
context["sidebar_index"] = sidebar_index
|
context["sidebar_index"] = sidebar_index
|
||||||
# An "article" might require the api_uri_context to be rendered
|
# An "article" might require the api_uri_context to be rendered
|
||||||
|
|||||||
Reference in New Issue
Block a user