Пример #1
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)
Пример #2
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()
Пример #3
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)
Пример #4
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 = http.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)

    body_bytes = body.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_bytes), ))
    request.write(body_bytes)
    finish_request(request)
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)
Пример #6
0
 def render_GET(self, request: TwistedRequest) -> object:
     presenter = self.presenter
     depth = len(request.prepath) - 1
     styleURL = '../' * depth + styleRoot.relativeURL
     request.write(b'<!DOCTYPE html>\n')
     request.write(xhtml.html[
         xhtml.head[fixedHeadItems,
                    presenter.headItems(),
                    xhtml.title[f'Report: {self.fileName}']].present(
                        styleURL=styleURL),
         xhtml.body[xhtml.div(class_='body')[presenter.presentBody()]]].
                   flattenXML().encode())
     request.finish()
     return NOT_DONE_YET
def _return_json(json_obj: Any, request: Request):
    json_bytes = json.dumps(json_obj).encode("utf-8")

    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")
    request.setHeader(b"Access-Control-Allow-Origin", b"*")
    request.setHeader(b"Access-Control-Allow-Methods",
                      b"GET, POST, PUT, DELETE, OPTIONS")
    request.setHeader(
        b"Access-Control-Allow-Headers",
        b"Origin, X-Requested-With, Content-Type, Accept, Authorization",
    )
    request.write(json_bytes)
    try:
        request.finish()
    except RuntimeError as e:
        logger.info("Connection disconnected before response was written: %r",
                    e)
Пример #8
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()
Пример #9
0
def process_later(request: Request):
    print("process_later called")
    request.write(b"later")  # $ MISSING: responseBody=b"later"
    request.finish()
Пример #10
0
 def render(self, request: Request):  # $ requestHandler
     request.write(
         b"also now"
     )  # $ HttpResponse mimetype=text/html responseBody=b"also now"
     return b""  # $ HttpResponse mimetype=text/html responseBody=b""
Пример #11
0
    async def _async_render_POST(self, request: Request) -> None:
        try:
            try:
                # TODO: we should really validate that this gives us a dict, and
                #   not some other json value like str, list, int etc
                # json.loads doesn't allow bytes in Python 3.5
                body: JsonDict = json_decoder.decode(
                    request.content.read().decode("UTF-8"))
            except ValueError:
                request.setResponseCode(HTTPStatus.BAD_REQUEST)
                request.write(
                    dict_to_json_bytes({
                        "errcode": "M_BAD_JSON",
                        "error": "Malformed JSON"
                    }))
                request.finish()
                return

            missing = [k for k in ("threepid", "mxid") if k not in body]
            if len(missing) > 0:
                request.setResponseCode(HTTPStatus.BAD_REQUEST)
                msg = "Missing parameters: " + (",".join(missing))
                request.write(
                    dict_to_json_bytes({
                        "errcode": "M_MISSING_PARAMS",
                        "error": msg
                    }))
                request.finish()
                return

            threepid = body["threepid"]
            mxid = body["mxid"]

            if "medium" not in threepid or "address" not in threepid:
                request.setResponseCode(HTTPStatus.BAD_REQUEST)
                request.write(
                    dict_to_json_bytes({
                        "errcode":
                        "M_MISSING_PARAMS",
                        "error":
                        "Threepid lacks medium / address",
                    }))
                request.finish()
                return

            # We now check for authentication in two different ways, depending
            # on the contents of the request. If the user has supplied "sid"
            # (the Session ID returned by Sydent during the original binding)
            # and "client_secret" fields, they are trying to prove that they
            # were the original author of the bind. We then check that what
            # they supply matches and if it does, allow the unbind.
            #
            # However if these fields are not supplied, we instead check
            # whether the request originated from a homeserver, and if so the
            # same homeserver that originally created the bind. We do this by
            # checking the signature of the request. If it all matches up, we
            # allow the unbind.
            #
            # Only one method of authentication is required.
            if "sid" in body and "client_secret" in body:
                sid = body["sid"]
                client_secret = body["client_secret"]

                if not is_valid_client_secret(client_secret):
                    request.setResponseCode(HTTPStatus.BAD_REQUEST)
                    request.write(
                        dict_to_json_bytes({
                            "errcode":
                            "M_INVALID_PARAM",
                            "error":
                            "Invalid client_secret provided",
                        }))
                    request.finish()
                    return

                valSessionStore = ThreePidValSessionStore(self.sydent)

                try:
                    s = valSessionStore.getValidatedSession(sid, client_secret)
                except (IncorrectClientSecretException,
                        InvalidSessionIdException):
                    request.setResponseCode(HTTPStatus.UNAUTHORIZED)
                    request.write(
                        dict_to_json_bytes({
                            "errcode":
                            "M_NO_VALID_SESSION",
                            "error":
                            "No valid session was found matching that sid and client secret",
                        }))
                    request.finish()
                    return
                except SessionNotValidatedException:
                    request.setResponseCode(HTTPStatus.FORBIDDEN)
                    request.write(
                        dict_to_json_bytes({
                            "errcode":
                            "M_SESSION_NOT_VALIDATED",
                            "error":
                            "This validation session has not yet been completed",
                        }))
                    return

                if s.medium != threepid["medium"] or s.address != threepid[
                        "address"]:
                    request.setResponseCode(HTTPStatus.FORBIDDEN)
                    request.write(
                        dict_to_json_bytes({
                            "errcode":
                            "M_FORBIDDEN",
                            "error":
                            "Provided session information does not match medium/address combo",
                        }))
                    request.finish()
                    return
            else:
                try:
                    origin_server_name = (
                        await self.sydent.sig_verifier.authenticate_request(
                            request, body))
                except SignatureVerifyException as ex:
                    request.setResponseCode(HTTPStatus.UNAUTHORIZED)
                    request.write(
                        dict_to_json_bytes({
                            "errcode": "M_FORBIDDEN",
                            "error": str(ex)
                        }))
                    request.finish()
                    return
                except NoAuthenticationError as ex:
                    request.setResponseCode(HTTPStatus.UNAUTHORIZED)
                    request.write(
                        dict_to_json_bytes({
                            "errcode": "M_FORBIDDEN",
                            "error": str(ex)
                        }))
                    request.finish()
                    return
                except InvalidServerName as ex:
                    request.setResponseCode(HTTPStatus.BAD_REQUEST)
                    request.write(
                        dict_to_json_bytes({
                            "errcode": "M_INVALID_PARAM",
                            "error": str(ex)
                        }))
                    request.finish()
                    return
                except (DNSLookupError, ConnectError, ResponseFailed) as e:
                    msg = (f"Unable to contact the Matrix homeserver to "
                           f"authenticate request ({type(e).__name__})")
                    logger.warning(msg)
                    request.setResponseCode(HTTPStatus.INTERNAL_SERVER_ERROR)
                    request.write(
                        dict_to_json_bytes({
                            "errcode": "M_UNKNOWN",
                            "error": msg,
                        }))
                    request.finish()
                    return
                except Exception:
                    logger.exception(
                        "Exception whilst authenticating unbind request")
                    request.setResponseCode(HTTPStatus.INTERNAL_SERVER_ERROR)
                    request.write(
                        dict_to_json_bytes({
                            "errcode": "M_UNKNOWN",
                            "error": "Internal Server Error"
                        }))
                    request.finish()
                    return

                if not mxid.endswith(":" + origin_server_name):
                    request.setResponseCode(HTTPStatus.FORBIDDEN)
                    request.write(
                        dict_to_json_bytes({
                            "errcode":
                            "M_FORBIDDEN",
                            "error":
                            "Origin server name does not match mxid",
                        }))
                    request.finish()
                    return

            self.sydent.threepidBinder.removeBinding(threepid, mxid)

            request.write(dict_to_json_bytes({}))
            request.finish()
        except Exception as ex:
            logger.exception("Exception whilst handling unbind")
            request.setResponseCode(HTTPStatus.INTERNAL_SERVER_ERROR)
            request.write(
                dict_to_json_bytes({
                    "errcode": "M_UNKNOWN",
                    "error": str(ex)
                }))
            request.finish()
Пример #12
0
 def write(self, bytes):
     invoked.append(get_ident())
     return Request.write(self, bytes)