From e0cf3d0e76e7985e8429172d7945deb0d7daae25 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Sun, 11 Aug 2019 20:44:35 -0700 Subject: [PATCH] zerver: Accept HEAD requests wherever GET requests are accepted. Signed-off-by: Anders Kaseorg --- zerver/lib/rest.py | 3 +++ zerver/logging_handlers.py | 4 ++-- zerver/tests/test_decorators.py | 2 +- zerver/views/auth.py | 10 ++++------ zerver/views/development/email_log.py | 4 ++-- zerver/views/realm.py | 4 ++-- zerver/webhooks/dropbox/view.py | 6 +++--- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/zerver/lib/rest.py b/zerver/lib/rest.py index 6a16b8fe64..536580b95d 100644 --- a/zerver/lib/rest.py +++ b/zerver/lib/rest.py @@ -68,6 +68,9 @@ def rest_dispatch(request: HttpRequest, **kwargs: Any) -> HttpResponse: supported_methods[arg] = kwargs[arg] del kwargs[arg] + if 'GET' in supported_methods: + supported_methods.setdefault('HEAD', supported_methods['GET']) + if request.method == 'OPTIONS': response = HttpResponse(status=204) # No content response['Allow'] = ', '.join(sorted(supported_methods.keys())) diff --git a/zerver/logging_handlers.py b/zerver/logging_handlers.py index 1bf6b78740..7ab7144313 100644 --- a/zerver/logging_handlers.py +++ b/zerver/logging_handlers.py @@ -61,8 +61,8 @@ def add_request_metadata(report: Dict[str, Any], request: HttpRequest) -> None: exception_filter = get_exception_reporter_filter(request) try: - report['data'] = request.GET if request.method == 'GET' else \ - exception_filter.get_post_parameters(request) + report['data'] = exception_filter.get_post_parameters(request) \ + if request.method == 'POST' else request.GET except Exception: # exception_filter.get_post_parameters will throw # RequestDataTooBig if there's a really big file uploaded diff --git a/zerver/tests/test_decorators.py b/zerver/tests/test_decorators.py index df70f7f053..bfe4711890 100644 --- a/zerver/tests/test_decorators.py +++ b/zerver/tests/test_decorators.py @@ -1709,7 +1709,7 @@ class RestAPITest(ZulipTestCase): self.login(self.example_email("hamlet")) result = self.client_options('/json/users') self.assertEqual(result.status_code, 204) - self.assertEqual(str(result['Allow']), 'GET, POST') + self.assertEqual(str(result['Allow']), 'GET, HEAD, POST') result = self.client_options('/json/streams/15') self.assertEqual(result.status_code, 204) diff --git a/zerver/views/auth.py b/zerver/views/auth.py index 4ea5ee24aa..38244ef527 100644 --- a/zerver/views/auth.py +++ b/zerver/views/auth.py @@ -11,7 +11,7 @@ from django.http import HttpRequest, HttpResponse, HttpResponseRedirect from django.template.response import SimpleTemplateResponse from django.shortcuts import redirect, render from django.views.decorators.csrf import csrf_exempt -from django.views.decorators.http import require_GET +from django.views.decorators.http import require_safe from django.utils.translation import ugettext as _ from django.utils.http import is_safe_url from django.core import signing @@ -555,9 +555,7 @@ def login_page(request: HttpRequest, **kwargs: Any) -> HttpResponse: # To support previewing the Zulip login pages, we have a special option # that disables the default behavior of redirecting logged-in users to the # logged-in app. - is_preview = False - if request.method == "GET" and request.GET and request.GET.get('preview'): - is_preview = True + is_preview = 'preview' in request.GET if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: if request.user and request.user.is_verified(): return HttpResponseRedirect(request.user.realm.uri) @@ -565,7 +563,7 @@ def login_page(request: HttpRequest, **kwargs: Any) -> HttpResponse: return HttpResponseRedirect(request.user.realm.uri) if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE: redirect_url = reverse('zerver.views.registration.realm_redirect') - if request.method == "GET" and request.GET: + if request.GET: redirect_url = "{}?{}".format(redirect_url, request.GET.urlencode()) return HttpResponseRedirect(redirect_url) @@ -790,7 +788,7 @@ def check_server_incompatibility(request: HttpRequest) -> bool: user_agent = parse_user_agent(request.META.get("HTTP_USER_AGENT", "Missing User-Agent")) return user_agent['name'] == "ZulipInvalid" -@require_GET +@require_safe @csrf_exempt def api_get_server_settings(request: HttpRequest) -> HttpResponse: # Log which client is making this request. diff --git a/zerver/views/development/email_log.py b/zerver/views/development/email_log.py index d72727ee77..95e33d0ea0 100755 --- a/zerver/views/development/email_log.py +++ b/zerver/views/development/email_log.py @@ -1,7 +1,7 @@ from django.conf import settings from django.http import HttpRequest, HttpResponse from django.shortcuts import render, redirect -from django.views.decorators.http import require_GET +from django.views.decorators.http import require_safe from zerver.models import ( get_realm, get_user_by_delivery_email, get_realm_stream, Realm, @@ -43,7 +43,7 @@ def clear_emails(request: HttpRequest) -> HttpResponse: pass return redirect(email_page) -@require_GET +@require_safe def generate_all_emails(request: HttpRequest) -> HttpResponse: if not settings.TEST_SUITE: # nocoverage # It's really convenient to automatically inline the email CSS diff --git a/zerver/views/realm.py b/zerver/views/realm.py index f4e91da352..ce2dfc5edd 100644 --- a/zerver/views/realm.py +++ b/zerver/views/realm.py @@ -3,7 +3,7 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render from django.utils.translation import ugettext as _ from django.core.exceptions import ValidationError -from django.views.decorators.http import require_GET +from django.views.decorators.http import require_safe from zerver.decorator import require_realm_admin, to_non_negative_int, to_not_negative_int_or_none from zerver.lib.actions import ( @@ -204,7 +204,7 @@ def deactivate_realm(request: HttpRequest, user: UserProfile) -> HttpResponse: do_deactivate_realm(realm, user) return json_success() -@require_GET +@require_safe def check_subdomain_available(request: HttpRequest, subdomain: str) -> HttpResponse: try: check_subdomain(subdomain) diff --git a/zerver/webhooks/dropbox/view.py b/zerver/webhooks/dropbox/view.py index 545feb7640..fc742299d7 100644 --- a/zerver/webhooks/dropbox/view.py +++ b/zerver/webhooks/dropbox/view.py @@ -7,10 +7,10 @@ from zerver.models import UserProfile @api_key_only_webhook_view('Dropbox', notify_bot_owner_on_invalid_json=False) @has_request_variables def api_dropbox_webhook(request: HttpRequest, user_profile: UserProfile) -> HttpResponse: - if request.method == 'GET': - return HttpResponse(request.GET['challenge']) - elif request.method == 'POST': + if request.method == 'POST': topic = 'Dropbox' check_send_webhook_message(request, user_profile, topic, "File has been updated on Dropbox!") return json_success() + else: + return HttpResponse(request.GET['challenge'])