Implementation of HTTP 307 response for MSC3886 POST endpoint (#14018)

Co-authored-by: reivilibre <olivier@librepush.net>
Co-authored-by: Andrew Morgan <andrewm@element.io>
This commit is contained in:
Hugh Nimmo-Smith 2022-10-18 16:52:25 +01:00 committed by GitHub
parent 844ce47b9b
commit 4eaf3eb840
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 257 additions and 45 deletions

View file

@ -19,6 +19,7 @@ import logging
import types
import urllib
from http import HTTPStatus
from http.client import FOUND
from inspect import isawaitable
from typing import (
TYPE_CHECKING,
@ -339,7 +340,7 @@ class _AsyncResource(resource.Resource, metaclass=abc.ABCMeta):
return callback_return
_unrecognised_request_handler(request)
return _unrecognised_request_handler(request)
@abc.abstractmethod
def _send_response(
@ -598,7 +599,7 @@ class RootRedirect(resource.Resource):
class OptionsResource(resource.Resource):
"""Responds to OPTION requests for itself and all children."""
def render_OPTIONS(self, request: Request) -> bytes:
def render_OPTIONS(self, request: SynapseRequest) -> bytes:
request.setResponseCode(204)
request.setHeader(b"Content-Length", b"0")
@ -763,7 +764,7 @@ def respond_with_json(
def respond_with_json_bytes(
request: Request,
request: SynapseRequest,
code: int,
json_bytes: bytes,
send_cors: bool = False,
@ -859,7 +860,7 @@ def _write_bytes_to_request(request: Request, bytes_to_write: bytes) -> None:
_ByteProducer(request, bytes_generator)
def set_cors_headers(request: Request) -> None:
def set_cors_headers(request: SynapseRequest) -> None:
"""Set the CORS headers so that javascript running in a web browsers can
use this API
@ -870,10 +871,20 @@ def set_cors_headers(request: Request) -> None:
request.setHeader(
b"Access-Control-Allow-Methods", b"GET, HEAD, POST, PUT, DELETE, OPTIONS"
)
request.setHeader(
b"Access-Control-Allow-Headers",
b"X-Requested-With, Content-Type, Authorization, Date",
)
if request.experimental_cors_msc3886:
request.setHeader(
b"Access-Control-Allow-Headers",
b"X-Requested-With, Content-Type, Authorization, Date, If-Match, If-None-Match",
)
request.setHeader(
b"Access-Control-Expose-Headers",
b"ETag, Location, X-Max-Bytes",
)
else:
request.setHeader(
b"Access-Control-Allow-Headers",
b"X-Requested-With, Content-Type, Authorization, Date",
)
def set_corp_headers(request: Request) -> None:
@ -942,10 +953,25 @@ def set_clickjacking_protection_headers(request: Request) -> None:
request.setHeader(b"Content-Security-Policy", b"frame-ancestors 'none';")
def respond_with_redirect(request: Request, url: bytes) -> None:
"""Write a 302 response to the request, if it is still alive."""
def respond_with_redirect(
request: SynapseRequest, url: bytes, statusCode: int = FOUND, cors: bool = False
) -> None:
"""
Write a 302 (or other specified status code) response to the request, if it is still alive.
Args:
request: The http request to respond to.
url: The URL to redirect to.
statusCode: The HTTP status code to use for the redirect (defaults to 302).
cors: Whether to set CORS headers on the response.
"""
logger.debug("Redirect to %s", url.decode("utf-8"))
request.redirect(url)
if cors:
set_cors_headers(request)
request.setResponseCode(statusCode)
request.setHeader(b"location", url)
finish_request(request)