zerver: Accept HEAD requests wherever GET requests are accepted.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This commit is contained in:
Anders Kaseorg
2019-08-11 20:44:35 -07:00
committed by Tim Abbott
parent ead13c11e5
commit e0cf3d0e76
7 changed files with 17 additions and 16 deletions

View File

@@ -68,6 +68,9 @@ def rest_dispatch(request: HttpRequest, **kwargs: Any) -> HttpResponse:
supported_methods[arg] = kwargs[arg] supported_methods[arg] = kwargs[arg]
del kwargs[arg] del kwargs[arg]
if 'GET' in supported_methods:
supported_methods.setdefault('HEAD', supported_methods['GET'])
if request.method == 'OPTIONS': if request.method == 'OPTIONS':
response = HttpResponse(status=204) # No content response = HttpResponse(status=204) # No content
response['Allow'] = ', '.join(sorted(supported_methods.keys())) response['Allow'] = ', '.join(sorted(supported_methods.keys()))

View File

@@ -61,8 +61,8 @@ def add_request_metadata(report: Dict[str, Any], request: HttpRequest) -> None:
exception_filter = get_exception_reporter_filter(request) exception_filter = get_exception_reporter_filter(request)
try: try:
report['data'] = request.GET if request.method == 'GET' else \ report['data'] = exception_filter.get_post_parameters(request) \
exception_filter.get_post_parameters(request) if request.method == 'POST' else request.GET
except Exception: except Exception:
# exception_filter.get_post_parameters will throw # exception_filter.get_post_parameters will throw
# RequestDataTooBig if there's a really big file uploaded # RequestDataTooBig if there's a really big file uploaded

View File

@@ -1709,7 +1709,7 @@ class RestAPITest(ZulipTestCase):
self.login(self.example_email("hamlet")) self.login(self.example_email("hamlet"))
result = self.client_options('/json/users') result = self.client_options('/json/users')
self.assertEqual(result.status_code, 204) 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') result = self.client_options('/json/streams/15')
self.assertEqual(result.status_code, 204) self.assertEqual(result.status_code, 204)

View File

@@ -11,7 +11,7 @@ from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from django.template.response import SimpleTemplateResponse from django.template.response import SimpleTemplateResponse
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.views.decorators.csrf import csrf_exempt 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.translation import ugettext as _
from django.utils.http import is_safe_url from django.utils.http import is_safe_url
from django.core import signing 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 # To support previewing the Zulip login pages, we have a special option
# that disables the default behavior of redirecting logged-in users to the # that disables the default behavior of redirecting logged-in users to the
# logged-in app. # logged-in app.
is_preview = False is_preview = 'preview' in request.GET
if request.method == "GET" and request.GET and request.GET.get('preview'):
is_preview = True
if settings.TWO_FACTOR_AUTHENTICATION_ENABLED: if settings.TWO_FACTOR_AUTHENTICATION_ENABLED:
if request.user and request.user.is_verified(): if request.user and request.user.is_verified():
return HttpResponseRedirect(request.user.realm.uri) return HttpResponseRedirect(request.user.realm.uri)
@@ -565,7 +563,7 @@ def login_page(request: HttpRequest, **kwargs: Any) -> HttpResponse:
return HttpResponseRedirect(request.user.realm.uri) return HttpResponseRedirect(request.user.realm.uri)
if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE: if is_subdomain_root_or_alias(request) and settings.ROOT_DOMAIN_LANDING_PAGE:
redirect_url = reverse('zerver.views.registration.realm_redirect') 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()) redirect_url = "{}?{}".format(redirect_url, request.GET.urlencode())
return HttpResponseRedirect(redirect_url) 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")) user_agent = parse_user_agent(request.META.get("HTTP_USER_AGENT", "Missing User-Agent"))
return user_agent['name'] == "ZulipInvalid" return user_agent['name'] == "ZulipInvalid"
@require_GET @require_safe
@csrf_exempt @csrf_exempt
def api_get_server_settings(request: HttpRequest) -> HttpResponse: def api_get_server_settings(request: HttpRequest) -> HttpResponse:
# Log which client is making this request. # Log which client is making this request.

View File

@@ -1,7 +1,7 @@
from django.conf import settings from django.conf import settings
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render, redirect 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 ( from zerver.models import (
get_realm, get_user_by_delivery_email, get_realm_stream, Realm, get_realm, get_user_by_delivery_email, get_realm_stream, Realm,
@@ -43,7 +43,7 @@ def clear_emails(request: HttpRequest) -> HttpResponse:
pass pass
return redirect(email_page) return redirect(email_page)
@require_GET @require_safe
def generate_all_emails(request: HttpRequest) -> HttpResponse: def generate_all_emails(request: HttpRequest) -> HttpResponse:
if not settings.TEST_SUITE: # nocoverage if not settings.TEST_SUITE: # nocoverage
# It's really convenient to automatically inline the email CSS # It's really convenient to automatically inline the email CSS

View File

@@ -3,7 +3,7 @@ from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.core.exceptions import ValidationError 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.decorator import require_realm_admin, to_non_negative_int, to_not_negative_int_or_none
from zerver.lib.actions import ( from zerver.lib.actions import (
@@ -204,7 +204,7 @@ def deactivate_realm(request: HttpRequest, user: UserProfile) -> HttpResponse:
do_deactivate_realm(realm, user) do_deactivate_realm(realm, user)
return json_success() return json_success()
@require_GET @require_safe
def check_subdomain_available(request: HttpRequest, subdomain: str) -> HttpResponse: def check_subdomain_available(request: HttpRequest, subdomain: str) -> HttpResponse:
try: try:
check_subdomain(subdomain) check_subdomain(subdomain)

View File

@@ -7,10 +7,10 @@ from zerver.models import UserProfile
@api_key_only_webhook_view('Dropbox', notify_bot_owner_on_invalid_json=False) @api_key_only_webhook_view('Dropbox', notify_bot_owner_on_invalid_json=False)
@has_request_variables @has_request_variables
def api_dropbox_webhook(request: HttpRequest, user_profile: UserProfile) -> HttpResponse: def api_dropbox_webhook(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
if request.method == 'GET': if request.method == 'POST':
return HttpResponse(request.GET['challenge'])
elif request.method == 'POST':
topic = 'Dropbox' topic = 'Dropbox'
check_send_webhook_message(request, user_profile, topic, check_send_webhook_message(request, user_profile, topic,
"File has been updated on Dropbox!") "File has been updated on Dropbox!")
return json_success() return json_success()
else:
return HttpResponse(request.GET['challenge'])