Esempio n. 1
0
    def renderDirectory(self, request: TwistedRequest, zipFile: ZipFile,
                        node: 'ZipTreeNode') -> object:
        """Serve a directory from a ZIP file.
        """

        # URLs for directory entries should end with a slash.
        if not request.path.endswith(b'/'):
            path = (request.postpath or request.prepath)[-1]
            return redirectTo(path + b'/', request)

        # Serve index.html at directory URL.
        entries = node.children
        index = entries.get('index.html')
        if isinstance(index, ZipInfo):
            return self.renderFile(request, zipFile, index)

        # If a ZIP contains a single file or single top-level directory,
        # redirect to that.
        if len(request.postpath) == 1:
            if len(entries) == 1:
                (name, entry), = entries.items()
                path = name.encode()
                if isinstance(entry, ZipTreeNode):
                    path += b'/'
                return redirectTo(path, request)

        request.setResponseCode(500)
        request.setHeader(b'Content-Type', b'text/plain; charset=UTF-8')
        return b'ZIP directory listing not yet implemented\n'
Esempio n. 2
0
    def render_GET(self, request: Request) -> str:
        send_cors(request)

        args = get_args(request, ("token", "sid", "client_secret"))
        resp = self.do_validate_request(request)
        if "success" in resp and resp["success"]:
            msg = "Verification successful! Please return to your Matrix client to continue."
            if "next_link" in args:
                next_link = args["next_link"]
                request.setResponseCode(302)
                request.setHeader("Location", next_link)
        else:
            request.setResponseCode(400)
            msg = (
                "Verification failed: you may need to request another verification text"
            )

        brand = self.sydent.brand_from_request(request)

        # self.sydent.config.http.verify_response_template is deprecated
        if self.sydent.config.http.verify_response_template is None:
            templateFile = self.sydent.get_branded_template(
                brand,
                "verify_response_template.html",
            )
        else:
            templateFile = self.sydent.config.http.verify_response_template

        request.setHeader("Content-Type", "text/html")
        return open(templateFile).read() % {"message": msg}
Esempio n. 3
0
    async def _async_render_GET(self, request: Request) -> None:
        set_cors_headers(request)
        request.setHeader(
            b"Content-Security-Policy",
            b"sandbox;"
            b" default-src 'none';"
            b" script-src 'none';"
            b" plugin-types application/pdf;"
            b" style-src 'unsafe-inline';"
            b" media-src 'self';"
            b" object-src 'self';",
        )
        request.setHeader(
            b"Referrer-Policy",
            b"no-referrer",
        )
        server_name, media_id, name = parse_media_id(request)
        if server_name == self.server_name:
            await self.media_repo.get_local_media(request, media_id, name)
        else:
            allow_remote = parse_boolean(request, "allow_remote", default=True)
            if not allow_remote:
                logger.info(
                    "Rejecting request for remote media %s/%s due to allow_remote",
                    server_name,
                    media_id,
                )
                respond_404(request)
                return

            await self.media_repo.get_remote_media(request, server_name,
                                                   media_id, name)
Esempio n. 4
0
    def render_GET(self, request: Request) -> bytes:
        args = get_args(request, ("nextLink", ), required=False)

        resp = None
        try:
            resp = self.do_validate_request(request)
        except Exception:
            pass
        if resp and "success" in resp and resp["success"]:
            msg = "Verification successful! Please return to your Matrix client to continue."
            if "nextLink" in args:
                next_link = args["nextLink"]
                if not next_link.startswith("file:///"):
                    request.setResponseCode(302)
                    request.setHeader("Location", next_link)
        else:
            msg = "Verification failed: you may need to request another verification email"

        brand = self.sydent.brand_from_request(request)

        # self.sydent.config.http.verify_response_template is deprecated
        if self.sydent.config.http.verify_response_template is None:
            templateFile = self.sydent.get_branded_template(
                brand,
                "verify_response_template.html",
            )
        else:
            templateFile = self.sydent.config.http.verify_response_template

        request.setHeader("Content-Type", "text/html")
        res = open(templateFile).read() % {"message": msg}

        return res.encode("UTF-8")
Esempio n. 5
0
    def render_OPTIONS(self, request: Request) -> bytes:
        request.setResponseCode(204)
        request.setHeader(b"Content-Length", b"0")

        set_cors_headers(request)

        return b""
Esempio n. 6
0
    def inner(self: Res, request: Request) -> bytes:
        """
        Runs a web handler function with the given request and parameters, then
        converts its result into JSON and returns it. If an error happens, also sets
        the HTTP response code.

        :param self: The current object.
        :param request: The request to process.

        :return: The JSON payload to send as a response to the request.
        """
        try:
            request.setHeader("Content-Type", "application/json")
            return dict_to_json_bytes(f(self, request))
        except MatrixRestError as e:
            request.setResponseCode(e.httpStatus)
            return dict_to_json_bytes({"errcode": e.errcode, "error": e.error})
        except Exception:
            logger.exception("Exception processing request")
            request.setHeader("Content-Type", "application/json")
            request.setResponseCode(500)
            return dict_to_json_bytes({
                "errcode": "M_UNKNOWN",
                "error": "Internal Server Error",
            })
Esempio n. 7
0
 def render(self, request: TwistedRequest) -> bytes:
     body = super().render(request)
     request.setHeader(
         b'WWW-Authenticate',
         b'Basic realm="%s"' % self.realm.encode('ascii')
         )
     return body
Esempio n. 8
0
def respond_with_html_bytes(request: Request, code: int, html_bytes: bytes) -> None:
    """
    Sends HTML (encoded as UTF-8 bytes) as the response to the given request.

    Note that this adds clickjacking protection headers and finishes the request.

    Args:
        request: The http request to respond to.
        code: The HTTP response code.
        html_bytes: The HTML bytes to use as the response body.
    """
    # could alternatively use request.notifyFinish() and flip a flag when
    # the Deferred fires, but since the flag is RIGHT THERE it seems like
    # a waste.
    if request._disconnected:
        logger.warning(
            "Not sending response to request %s, already disconnected.", request
        )
        return None

    request.setResponseCode(code)
    request.setHeader(b"Content-Type", b"text/html; charset=utf-8")
    request.setHeader(b"Content-Length", b"%d" % (len(html_bytes),))

    # Ensure this content cannot be embedded.
    set_clickjacking_protection_headers(request)

    request.write(html_bytes)
    finish_request(request)
Esempio n. 9
0
def return_html_error(
    f: failure.Failure,
    request: Request,
    error_template: Union[str, jinja2.Template],
) -> None:
    """Sends an HTML error page corresponding to the given failure.

    Handles RedirectException and other CodeMessageExceptions (such as SynapseError)

    Args:
        f: the error to report
        request: the failing request
        error_template: the HTML template. Can be either a string (with `{code}`,
            `{msg}` placeholders), or a jinja2 template
    """
    if f.check(CodeMessageException):
        # mypy doesn't understand that f.check asserts the type.
        cme: CodeMessageException = f.value  # type: ignore
        code = cme.code
        msg = cme.msg

        if isinstance(cme, RedirectException):
            logger.info("%s redirect to %s", request, cme.location)
            request.setHeader(b"location", cme.location)
            request.cookies.extend(cme.cookies)
        elif isinstance(cme, SynapseError):
            logger.info("%s SynapseError: %s - %s", request, code, msg)
        else:
            logger.error(
                "Failed handle request %r",
                request,
                exc_info=(f.type, f.value, f.getTracebackObject()),  # type: ignore[arg-type]
            )
    elif f.check(CancelledError):
        code = HTTP_STATUS_REQUEST_CANCELLED
        msg = "Request cancelled"

        if not request._disconnected:
            logger.error(
                "Got cancellation before client disconnection when handling request %r",
                request,
                exc_info=(f.type, f.value, f.getTracebackObject()),  # type: ignore[arg-type]
            )
    else:
        code = HTTPStatus.INTERNAL_SERVER_ERROR
        msg = "Internal server error"

        logger.error(
            "Failed handle request %r",
            request,
            exc_info=(f.type, f.value, f.getTracebackObject()),  # type: ignore[arg-type]
        )

    if isinstance(error_template, str):
        body = error_template.format(code=code, msg=html.escape(msg))
    else:
        body = error_template.render(code=code, msg=msg)

    respond_with_html(request, code, body)
Esempio n. 10
0
    def render_GET(self, request: Request) -> bytes:
        if not self._serve_server_wellknown:
            request.setResponseCode(404)
            request.setHeader(b"Content-Type", b"text/plain")
            return b"404. Is anything ever truly *well* known?\n"

        request.setHeader(b"Content-Type", b"application/json")
        return self._response
Esempio n. 11
0
 def putDone(
         cls,
         result: None,  # pylint: disable=unused-argument
         request: TwistedRequest) -> None:
     request.setResponseCode(201)
     request.setHeader(b'Content-Type', b'text/plain; charset=UTF-8')
     request.write(b'Artifact stored\n')
     request.finish()
Esempio n. 12
0
def set_corp_headers(request: Request) -> None:
    """Set the CORP headers so that javascript running in a web browsers can
    embed the resource returned from this request when their client requires
    the `Cross-Origin-Embedder-Policy: require-corp` header.

    Args:
        request: The http request to add the CORP header to.
    """
    request.setHeader(b"Cross-Origin-Resource-Policy", b"cross-origin")
Esempio n. 13
0
    def render_GET(self, request: server.Request):  # noqa: N802
        """Render the database status in plain text."""
        if not self.is_client_permitted(request):
            request.setResponseCode(403)
            return b'Access denied'

        result_txt = DatabaseStatusRequest().generate_status()
        request.setHeader(b'Content-Type', b'text/plain; charset=utf-8')
        return result_txt.encode('utf-8')
Esempio n. 14
0
 def putFailed(cls, fail: Failure, request: TwistedRequest) -> None:
     ex = fail.value
     if isinstance(ex, ValueError):
         request.setResponseCode(415)
         request.setHeader(b'Content-Type', b'text/plain; charset=UTF-8')
         request.write((f'{ex}\n').encode())
         request.finish()
     else:
         request.processingFailed(fail)
Esempio n. 15
0
    def render_GET(self, request: Request) -> bytes:
        set_cors_headers(request)
        r = self._well_known_builder.get_well_known()
        if not r:
            request.setResponseCode(404)
            request.setHeader(b"Content-Type", b"text/plain")
            return b".well-known not available"

        logger.debug("returning: %s", r)
        request.setHeader(b"Content-Type", b"application/json")
        return json_encoder.encode(r).encode("utf-8")
def _return_html_error(code: int, msg: str, request: Request):
    """Sends an HTML error page"""
    body = HTML_ERROR_TEMPLATE.format(code=code,
                                      msg=html.escape(msg)).encode("utf-8")
    request.setResponseCode(code)
    request.setHeader(b"Content-Type", b"text/html; charset=utf-8")
    request.setHeader(b"Content-Length", b"%i" % (len(body), ))
    request.write(body)
    try:
        request.finish()
    except RuntimeError as e:
        logger.info("Connection disconnected before response was written: %r",
                    e)
Esempio n. 17
0
def set_clickjacking_protection_headers(request: Request) -> None:
    """
    Set headers to guard against clickjacking of embedded content.

    This sets the X-Frame-Options and Content-Security-Policy headers which instructs
    browsers to not allow the HTML of the response to be embedded onto another
    page.

    Args:
        request: The http request to add the headers to.
    """
    request.setHeader(b"X-Frame-Options", b"DENY")
    request.setHeader(b"Content-Security-Policy", b"frame-ancestors 'none';")
Esempio n. 18
0
def respond_with_json(
    request: Request,
    code: int,
    json_object: Any,
    send_cors: bool = False,
    pretty_print: bool = False,
    canonical_json: bool = True,
):
    """Sends encoded JSON in response to the given request.

    Args:
        request: The http request to respond to.
        code: The HTTP response code.
        json_object: The object to serialize to JSON.
        send_cors: Whether to send Cross-Origin Resource Sharing headers
            https://fetch.spec.whatwg.org/#http-cors-protocol
        pretty_print: Whether to include indentation and line-breaks in the
            resulting JSON bytes.
        canonical_json: Whether to use the canonicaljson algorithm when encoding
            the JSON bytes.

    Returns:
        twisted.web.server.NOT_DONE_YET if the request is still active.
    """
    # could alternatively use request.notifyFinish() and flip a flag when
    # the Deferred fires, but since the flag is RIGHT THERE it seems like
    # a waste.
    if request._disconnected:
        logger.warning(
            "Not sending response to request %s, already disconnected.",
            request)
        return None

    if pretty_print:
        encoder = iterencode_pretty_printed_json
    else:
        if canonical_json or synapse.events.USE_FROZEN_DICTS:
            encoder = iterencode_canonical_json
        else:
            encoder = _encode_json_bytes

    request.setResponseCode(code)
    request.setHeader(b"Content-Type", b"application/json")
    request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate")

    if send_cors:
        set_cors_headers(request)

    _ByteProducer(request, encoder(json_object))
    return NOT_DONE_YET
Esempio n. 19
0
    def serveZipEntry(cls, inp: IO[bytes], info: ZipInfo,
                      request: TwistedRequest) -> 'FileProducer':
        """Serves a deflate-compressed ZIP file entry as a gzip file."""

        request.setHeader(b'Content-Encoding', b'gzip')

        # Seek to start of deflate stream.
        offset = info.header_offset
        inp.seek(offset + 26)
        nameLen, extraLen = cls._variableHeaderLengths.unpack(inp.read(4))
        inp.seek(offset + 30 + nameLen + extraLen)

        size = info.compress_size
        footer = cls._gzipFooter.pack(info.CRC, info.file_size)
        return cls._serve(cls.gzipBlockGen(inp, size, footer), request)
Esempio n. 20
0
def return_html_error(
    f: failure.Failure,
    request: Request,
    error_template: Union[str, jinja2.Template],
) -> None:
    """Sends an HTML error page corresponding to the given failure.

    Handles RedirectException and other CodeMessageExceptions (such as SynapseError)

    Args:
        f: the error to report
        request: the failing request
        error_template: the HTML template. Can be either a string (with `{code}`,
            `{msg}` placeholders), or a jinja2 template
    """
    if f.check(CodeMessageException):
        cme = f.value
        code = cme.code
        msg = cme.msg

        if isinstance(cme, RedirectException):
            logger.info("%s redirect to %s", request, cme.location)
            request.setHeader(b"location", cme.location)
            request.cookies.extend(cme.cookies)
        elif isinstance(cme, SynapseError):
            logger.info("%s SynapseError: %s - %s", request, code, msg)
        else:
            logger.error(
                "Failed handle request %r",
                request,
                exc_info=(f.type, f.value, f.getTracebackObject()),
            )
    else:
        code = HTTPStatus.INTERNAL_SERVER_ERROR
        msg = "Internal server error"

        logger.error(
            "Failed handle request %r",
            request,
            exc_info=(f.type, f.value, f.getTracebackObject()),
        )

    if isinstance(error_template, str):
        body = error_template.format(code=code, msg=html.escape(msg))
    else:
        body = error_template.render(code=code, msg=msg)

    respond_with_html(request, code, body)
Esempio n. 21
0
    def render_GET(self, request: Request):  # $ requestHandler
        request.addCookie(
            "key",
            "value")  # $ CookieWrite CookieName="key" CookieValue="value"
        request.addCookie(
            k="key",
            v="value")  # $ CookieWrite CookieName="key" CookieValue="value"
        val = "key2=value"
        request.cookies.append(val)  # $ CookieWrite CookieRawHeader=val

        request.responseHeaders.addRawHeader("key", "value")
        request.setHeader(
            "Set-Cookie", "key3=value3"
        )  # $ MISSING: CookieWrite CookieRawHeader="key3=value3"

        return b""  # $ HttpResponse mimetype=text/html responseBody=b""
Esempio n. 22
0
    async def on_GET(self, request: Request, medium: str) -> None:
        if medium != "email":
            raise SynapseError(
                400, "This medium is currently not supported for registration")
        if self.config.email.threepid_behaviour_email == ThreepidBehaviour.OFF:
            if self.config.email.local_threepid_handling_disabled_due_to_email_config:
                logger.warning(
                    "User registration via email has been disabled due to lack of email config"
                )
            raise SynapseError(
                400, "Email-based registration is disabled on this server")

        sid = parse_string(request, "sid", required=True)
        client_secret = parse_string(request, "client_secret", required=True)
        assert_valid_client_secret(client_secret)
        token = parse_string(request, "token", required=True)

        # Attempt to validate a 3PID session
        try:
            # Mark the session as valid
            next_link = await self.store.validate_threepid_session(
                sid, client_secret, token, self.clock.time_msec())

            # Perform a 302 redirect if next_link is set
            if next_link:
                if next_link.startswith("file:///"):
                    logger.warning(
                        "Not redirecting to next_link as it is a local file: address"
                    )
                else:
                    request.setResponseCode(302)
                    request.setHeader("Location", next_link)
                    finish_request(request)
                    return None

            # Otherwise show the success template
            html = self.config.email.email_registration_template_success_html_content
            status_code = 200
        except ThreepidValidationError as e:
            status_code = e.code

            # Show a failure page with a reason
            template_vars = {"failure_reason": e.msg}
            html = self._failure_email_template.render(**template_vars)

        respond_with_html(request, status_code, html)
Esempio n. 23
0
    async def on_GET(self, request: Request) -> None:
        if self.config.email.threepid_behaviour_email == ThreepidBehaviour.OFF:
            if self.config.email.local_threepid_handling_disabled_due_to_email_config:
                logger.warning(
                    "Adding emails have been disabled due to lack of an email config"
                )
            raise SynapseError(
                400, "Adding an email to your account is disabled on this server"
            )
        elif self.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
            raise SynapseError(
                400,
                "This homeserver is not validating threepids. Use an identity server "
                "instead.",
            )

        sid = parse_string(request, "sid", required=True)
        token = parse_string(request, "token", required=True)
        client_secret = parse_string(request, "client_secret", required=True)
        assert_valid_client_secret(client_secret)

        # Attempt to validate a 3PID session
        try:
            # Mark the session as valid
            next_link = await self.store.validate_threepid_session(
                sid, client_secret, token, self.clock.time_msec()
            )

            # Perform a 302 redirect if next_link is set
            if next_link:
                request.setResponseCode(302)
                request.setHeader("Location", next_link)
                finish_request(request)
                return None

            # Otherwise show the success template
            html = self.config.email.email_add_threepid_template_success_html_content
            status_code = 200
        except ThreepidValidationError as e:
            status_code = e.code

            # Show a failure page with a reason
            template_vars = {"failure_reason": e.msg}
            html = self._failure_email_template.render(**template_vars)

        respond_with_html(request, status_code, html)
Esempio n. 24
0
    async def _async_render_POST(self, request: Request) -> Tuple[int, bytes]:
        sid = parse_string(request, "sid", required=True)
        token = parse_string(request, "token", required=True)
        client_secret = parse_string(request, "client_secret", required=True)

        # Attempt to validate a 3PID session
        try:
            # Mark the session as valid
            next_link = await self.store.validate_threepid_session(
                sid, client_secret, token, self.clock.time_msec()
            )

            # Perform a 302 redirect if next_link is set
            if next_link:
                if next_link.startswith("file:///"):
                    logger.warning(
                        "Not redirecting to next_link as it is a local file: address"
                    )
                else:
                    next_link_bytes = next_link.encode("utf-8")
                    request.setHeader("Location", next_link_bytes)
                    return (
                        302,
                        (
                            b'You are being redirected to <a src="%s">%s</a>.'
                            % (next_link_bytes, next_link_bytes)
                        ),
                    )

            # Otherwise show the success template
            html_bytes = self._email_password_reset_template_success_html.encode(
                "utf-8"
            )
            status_code = 200
        except ThreepidValidationError as e:
            status_code = e.code

            # Show a failure page with a reason
            template_vars = {"failure_reason": e.msg}
            html_bytes = self._failure_email_template.render(**template_vars).encode(
                "utf-8"
            )

        return status_code, html_bytes
Esempio n. 25
0
    def renderFile(self, request: TwistedRequest, zipFile: ZipFile,
                   info: ZipInfo) -> object:
        """Serve a file entry from a ZIP file.
        """

        # Determine content type.
        contentType, encoding = guess_type(info.filename, strict=False)
        if encoding is not None:
            # We want contents to be served as-is, not automatically
            # decoded by the browser.
            contentType = 'application/' + encoding
        if contentType is None:
            contentType = 'application/octet-stream'
        request.setHeader(b'Content-Type', contentType.encode())
        request.setHeader(b'Content-Disposition', b'inline')

        # Serve data in compressed form if user agent accepts it.
        if info.compress_type == ZIP_DEFLATED:
            accept = AcceptedEncodings.parse(
                request.getHeader('accept-encoding'))
            decompress = 4.0 * accept['gzip'] < accept['identity']
            if not decompress:
                request.setHeader('Content-Encoding', 'gzip')
        else:
            decompress = True
        if decompress:
            FileProducer.servePlain(zipFile.open(info), request)
        else:
            FileProducer.serveZipEntry(self.zipPath.open(), info, request)
        return NOT_DONE_YET
Esempio n. 26
0
def respond_with_json_bytes(
    request: Request, code: int, json_bytes: bytes, send_cors: bool = False,
):
    """Sends encoded JSON in response to the given request.

    Args:
        request: The http request to respond to.
        code: The HTTP response code.
        json_bytes: The json bytes to use as the response body.
        send_cors: Whether to send Cross-Origin Resource Sharing headers
            https://fetch.spec.whatwg.org/#http-cors-protocol

    Returns:
        twisted.web.server.NOT_DONE_YET if the request is still active.
    """

    request.setResponseCode(code)
    request.setHeader(b"Content-Type", b"application/json")
    request.setHeader(b"Content-Length", b"%d" % (len(json_bytes),))
    request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate")

    if send_cors:
        set_cors_headers(request)

    # note that this is zero-copy (the bytesio shares a copy-on-write buffer with
    # the original `bytes`).
    bytes_io = BytesIO(json_bytes)

    producer = NoRangeStaticProducer(request, bytes_io)
    producer.start()
    return NOT_DONE_YET
Esempio n. 27
0
def respond_with_json_bytes(
    request: Request,
    code: int,
    json_bytes: bytes,
    send_cors: bool = False,
) -> Optional[int]:
    """Sends encoded JSON in response to the given request.

    Args:
        request: The http request to respond to.
        code: The HTTP response code.
        json_bytes: The json bytes to use as the response body.
        send_cors: Whether to send Cross-Origin Resource Sharing headers
            https://fetch.spec.whatwg.org/#http-cors-protocol

    Returns:
        twisted.web.server.NOT_DONE_YET if the request is still active.
    """
    if request._disconnected:
        logger.warning(
            "Not sending response to request %s, already disconnected.", request
        )
        return None

    request.setResponseCode(code)
    request.setHeader(b"Content-Type", b"application/json")
    request.setHeader(b"Content-Length", b"%d" % (len(json_bytes),))
    request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate")

    if send_cors:
        set_cors_headers(request)

    _write_bytes_to_request(request, json_bytes)
    return NOT_DONE_YET
Esempio n. 28
0
 async def render(f: AsyncRenderer[Res], self: Res,
                  request: Request) -> None:
     request.setHeader("Content-Type", "application/json")
     try:
         result = await f(self, request)
         request.write(dict_to_json_bytes(result))
     except MatrixRestError as e:
         request.setResponseCode(e.httpStatus)
         request.write(
             dict_to_json_bytes({
                 "errcode": e.errcode,
                 "error": e.error
             }))
     except Exception:
         logger.exception("Request processing failed")
         request.setResponseCode(500)
         request.write(
             dict_to_json_bytes({
                 "errcode": "M_UNKNOWN",
                 "error": "Internal Server Error"
             }))
     request.finish()
Esempio n. 29
0
    def render_PUT(self, request: TwistedRequest) -> object:
        path = self.path

        if path.isfile():
            request.setResponseCode(409)
            request.setHeader(b'Content-Type', b'text/plain; charset=UTF-8')
            return b'Artifacts cannot be overwritten\n'

        # Note: Twisted buffers the entire upload into 'request.content'
        #       prior to calling our render method.
        #       There doesn't seem to be a clean way to handle streaming
        #       uploads in Twisted; we'd have to set site.requestFactory
        #       to a request implementation that overrides gotLength() or
        #       handleContentChunk(), both of which are documented as
        #       "not intended for users".

        # Do the actual store in a separate thread, so we don't have to worry
        # about slow operations hogging the reactor thread.
        deferToThread(self._storeArtifact, request.content, path) \
            .addCallback(self.putDone, request) \
            .addErrback(self.putFailed, request)
        return NOT_DONE_YET
Esempio n. 30
0
def set_cors_headers(request: Request):
    """Set the CORS headers so that javascript running in a web browsers can
    use this API

    Args:
        request: The http request to add CORS to.
    """
    request.setHeader(b"Access-Control-Allow-Origin", b"*")
    request.setHeader(b"Access-Control-Allow-Methods",
                      b"GET, HEAD, POST, PUT, DELETE, OPTIONS")
    request.setHeader(
        b"Access-Control-Allow-Headers",
        b"Origin, X-Requested-With, Content-Type, Accept, Authorization, Date",
    )