async fn handle_error(ctx: &Context, err: BrokerError) -> Response {
    let reference = err.log(Some(&ctx.app.rng)).await;

    if ctx.want_json {
        let mut res = json_response(&json!({
            "error": err.oauth_error_code(),
            "error_description": &format!("{}", err),
            "reference": reference,
        }));
        *res.status_mut() = err.http_status_code();
        return res;
    }

    // Check if we can redirect to the RP. We must have return parameters, and the RP must not have
    // opted out from receiving errors in the redirect response.
    let can_redirect = matches!(
        ctx.return_params,
        Some(ReturnParams {
            response_errors: true,
            ..
        })
    );

    let catalog = ctx.catalog();
    match (err, can_redirect) {
        // Redirects with description.
        (err @ BrokerError::Input(_), true)
        | (err @ BrokerError::Provider(_), true)
        | (err @ BrokerError::ProviderInput(_), true) => return_to_relier(
            ctx,
            &[
                ("error", err.oauth_error_code()),
                ("error_description", &format!("{}", err)),
            ],
        ),
        // Friendly error pages for what we can't redirect.
        (err @ BrokerError::Input(_), false) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("error", &format!("{}", err)),
                ("intro", catalog.gettext("The request is invalid, and could not be completed.")),
                ("reason", catalog.gettext("Technical description")),
                ("explanation", catalog.gettext("This indicates an issue with the site you're trying to login to. Contact the site administrator to get the issue resolved.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        (err @ BrokerError::Provider(_), false) | (err @ BrokerError::ProviderInput(_), false) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("error", &format!("{}", err)),
                (
                    "intro",
                    catalog.gettext("Failed to connect with your email domain."),
                ),
                ("reason", catalog.gettext("Technical description")),
                (
                    "explanation",
                    catalog.gettext(
                        "Contact the administrator of your email domain to get the issue resolved.",
                    ),
                ),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        // Friendly error pages for what we will never redirect.
        (err @ BrokerError::Internal(_), _) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("ref", &reference.expect("internal error must have a reference")),
                ("intro", catalog.gettext("Something went wrong, and we cannot complete your request at this time.")),
                ("explanation", catalog.gettext("An internal error occurred, which has been logged with the below reference number.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        (err @ BrokerError::RateLimited, _) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("intro", catalog.gettext("Too many login attempts.")),
                ("explanation", catalog.gettext("We've received too many requests in a short amount of time. Please try again later.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        (err @ BrokerError::SessionExpired, _) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("intro", catalog.gettext("The session has expired.")),
                ("explanation", catalog.gettext("Your login attempt may have taken too long, or you tried to follow an old link. Please try again.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        // Internal status that should never bubble this far
        (BrokerError::ProviderCancelled, _) => unreachable!(),
    }
}
/// Handle a `BrokerError` and create a response.
///
/// Our service calls this on error. We handle all these errors, and always
/// return a response.
///
/// When we handle an error, we want to:
///
///  - Log internal errors and errors related to communcation with providers.
///  - Not log input errors, such as missing parameters.
///
///  - Hide the details of internal errors from the user.
///  - Show a description for input and provider errors.
///
///  - Return the error to the relier via redirect, as per the OAuth2 spec.
///  - Always show something to the user, even if we cannot redirect.
///
/// The large match-statement below handles all these scenario's properly, and
/// sets proper response codes for each category.
Handle a `BrokerError` and create a response.
Our service calls this on error. We handle all these errors, and always
return a response.

When we handle an error, we want to.

Log internal errors and errors related to communcation with providers.
Not log input errors, such as missing parameters.

Hide the details of internal errors from the user.
Show a description for input and provider errors.

Return the error to the relier via redirect, as per the OAuth2 spec.
Always show something to the user, even if we cannot redirect.

The large match-statement below handles all these scenario's properly, and
sets proper response codes for each category.
Handle a ` BrokerError ` and create a response . Our service calls this on error . We handle all these errors and always return a response . When we handle an error we want to . Log internal errors and errors related to communcation with providers . Not log input errors such as missing parameters . Hide the details of internal errors from the user . Show a description for input and provider errors . Return the error to the relier via redirect as per the OAuth2 spec . Always show something to the user even if we cannot redirect . The large match - statement below handles all these scenario ' s properly and sets proper response codes for each category .
async fn handle_error(ctx: &Context, err: BrokerError) -> Response {
    let reference = err.log(Some(&ctx.app.rng)).await;
    if ctx.want_json {
        let mut res = json_response(&json!({
            "error": err.oauth_error_code(),
            "error_description": &format!("{}", err),
            "reference": reference,
        }));
        *res.status_mut() = err.http_status_code();
        return res;
    }
    // Check if we can redirect to the RP. We must have return parameters, and the RP must not have
    // opted out from receiving errors in the redirect response.
    let can_redirect = matches!(
        ctx.return_params,
        Some(ReturnParams {
            response_errors: true,
            ..
        })
    );
    let catalog = ctx.catalog();
    match (err, can_redirect) {
        // Redirects with description.
        (err @ BrokerError::Input(_), true)
        | (err @ BrokerError::Provider(_), true)
        | (err @ BrokerError::ProviderInput(_), true) => return_to_relier(
            ctx,
            &[
                ("error", err.oauth_error_code()),
                ("error_description", &format!("{}", err)),
            ],
        ),
        // Friendly error pages for what we can't redirect.
        (err @ BrokerError::Input(_), false) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("error", &format!("{}", err)),
                ("intro", catalog.gettext("The request is invalid, and could not be completed.")),
                ("reason", catalog.gettext("Technical description")),
                ("explanation", catalog.gettext("This indicates an issue with the site you're trying to login to. Contact the site administrator to get the issue resolved.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        (err @ BrokerError::Provider(_), false) | (err @ BrokerError::ProviderInput(_), false) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("error", &format!("{}", err)),
                (
                    "intro",
                    catalog.gettext("Failed to connect with your email domain."),
                ),
                ("reason", catalog.gettext("Technical description")),
                (
                    "explanation",
                    catalog.gettext(
                        "Contact the administrator of your email domain to get the issue resolved.",
                    ),
                ),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        // Friendly error pages for what we will never redirect.
        (err @ BrokerError::Internal(_), _) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("ref", &reference.expect("internal error must have a reference")),
                ("intro", catalog.gettext("Something went wrong, and we cannot complete your request at this time.")),
                ("explanation", catalog.gettext("An internal error occurred, which has been logged with the below reference number.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        (err @ BrokerError::RateLimited, _) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("intro", catalog.gettext("Too many login attempts.")),
                ("explanation", catalog.gettext("We've received too many requests in a short amount of time. Please try again later.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        (err @ BrokerError::SessionExpired, _) => {
            let mut res = html_response(ctx.app.templates.error.render(&[
                ("intro", catalog.gettext("The session has expired.")),
                ("explanation", catalog.gettext("Your login attempt may have taken too long, or you tried to follow an old link. Please try again.")),
            ]));
            *res.status_mut() = err.http_status_code();
            res
        }
        // Internal status that should never bubble this far
        (BrokerError::ProviderCancelled, _) => unreachable!(),
    }
}
async fn handle_error ( ctx : & Context , err : BrokerError ) -> Response { let reference = err . log ( Some ( & ctx . app . rng ) ) . await ; if ctx . want_json { let mut res = json_response ( & json ! ( { " " err oauth_error_code ( ) " " format ( " " err ) " " reference } ) ) ; * res . status_mut ( ) = err . http_status_code ( ) ; return res ; } // Check if we can redirect to the RP. We must have return parameters, and the RP must not have // opted out from receiving errors in the redirect response. let can_redirect = matches ! ( ctx return_params Some ( ReturnParams { response_errors true } ) ) ; let catalog = ctx . catalog ( ) ; match ( err , can_redirect ) { // Redirects with description. ( err @ BrokerError :: Input ( _ ) , true ) | ( err @ BrokerError :: Provider ( _ ) , true ) | ( err @ BrokerError :: ProviderInput ( _ ) , true ) => return_to_relier ( ctx , & [ ( " " , err . oauth_error_code ( ) ) , ( " " , & format ! ( " " err ) ) , ] , ) , // Friendly error pages for what we can't redirect. ( err @ BrokerError :: Input ( _ ) , false ) => { let mut res = html_response ( ctx . app . templates . error . render ( & [ ( " " , & format ! ( " " err ) ) , ( " " , catalog . gettext ( " " ) ) , ( " " , catalog . gettext ( " " ) ) , ( " " , catalog . gettext ( " " ) ) , ] ) ) ; * res . status_mut ( ) = err . http_status_code ( ) ; res } ( err @ BrokerError :: Provider ( _ ) , false ) | ( err @ BrokerError :: ProviderInput ( _ ) , false ) => { let mut res = html_response ( ctx . app . templates . error . render ( & [ ( " " , & format ! ( " " err ) ) , ( " " , catalog . gettext ( " " ) , ) , ( " " , catalog . gettext ( " " ) ) , ( " " , catalog . gettext ( " " , ) , ) , ] ) ) ; * res . status_mut ( ) = err . http_status_code ( ) ; res } // Friendly error pages for what we will never redirect. ( err @ BrokerError :: Internal ( _ ) , _ ) => { let mut res = html_response ( ctx . app . templates . error . render ( & [ ( " " , & reference . expect ( " " ) ) , ( " " , catalog . gettext ( " " ) ) , ( " " , catalog . gettext ( " " ) ) , ] ) ) ; * res . status_mut ( ) = err . http_status_code ( ) ; res } ( err @ BrokerError :: RateLimited , _ ) => { let mut res = html_response ( ctx . app . templates . error . render ( & [ ( " " , catalog . gettext ( " " ) ) , ( " " , catalog . gettext ( " " ) ) , ] ) ) ; * res . status_mut ( ) = err . http_status_code ( ) ; res } ( err @ BrokerError :: SessionExpired , _ ) => { let mut res = html_response ( ctx . app . templates . error . render ( & [ ( " " , catalog . gettext ( " " ) ) , ( " " , catalog . gettext ( " " ) ) , ] ) ) ; * res . status_mut ( ) = err . http_status_code ( ) ; res } // Internal status that should never bubble this far ( BrokerError :: ProviderCancelled , _ ) => unreachable ! ( ) , } }
Handle a `BrokerError` and create a response.
Handle a ` BrokerError ` and create a response .
ctx
&Context
err
BrokerError
ctx
&Context
err
BrokerError