You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-31 09:24:31 +03:00
Add a 404 HTMl fallback
This commit is contained in:
@ -235,6 +235,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
router = router.fallback(mas_handlers::fallback);
|
||||||
|
|
||||||
router
|
router
|
||||||
.layer(
|
.layer(
|
||||||
InFlightCounterLayer::new("http.server.active_requests").on_request((
|
InFlightCounterLayer::new("http.server.active_requests").on_request((
|
||||||
|
@ -34,21 +34,26 @@ use std::{convert::Infallible, sync::Arc, time::Duration};
|
|||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::{Bytes, HttpBody},
|
body::{Bytes, HttpBody},
|
||||||
extract::{FromRef, FromRequestParts},
|
extract::{FromRef, FromRequestParts, OriginalUri, State},
|
||||||
|
http::Method,
|
||||||
response::{Html, IntoResponse},
|
response::{Html, IntoResponse},
|
||||||
routing::{get, on, post, MethodFilter},
|
routing::{get, on, post, MethodFilter},
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use headers::HeaderName;
|
use headers::HeaderName;
|
||||||
use hyper::header::{
|
use hyper::{
|
||||||
ACCEPT, ACCEPT_LANGUAGE, AUTHORIZATION, CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_TYPE,
|
header::{
|
||||||
|
ACCEPT, ACCEPT_LANGUAGE, AUTHORIZATION, CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_TYPE,
|
||||||
|
},
|
||||||
|
StatusCode, Version,
|
||||||
};
|
};
|
||||||
|
use mas_axum_utils::FancyError;
|
||||||
use mas_http::CorsLayerExt;
|
use mas_http::CorsLayerExt;
|
||||||
use mas_keystore::{Encrypter, Keystore};
|
use mas_keystore::{Encrypter, Keystore};
|
||||||
use mas_policy::PolicyFactory;
|
use mas_policy::PolicyFactory;
|
||||||
use mas_router::{Route, UrlBuilder};
|
use mas_router::{Route, UrlBuilder};
|
||||||
use mas_storage::{BoxClock, BoxRepository, BoxRng};
|
use mas_storage::{BoxClock, BoxRepository, BoxRng};
|
||||||
use mas_templates::{ErrorContext, Templates};
|
use mas_templates::{ErrorContext, NotFoundContext, Templates};
|
||||||
use passwords::PasswordManager;
|
use passwords::PasswordManager;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use tower::util::AndThenLayer;
|
use tower::util::AndThenLayer;
|
||||||
@ -368,3 +373,22 @@ where
|
|||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The fallback handler for all routes that don't match anything else.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if the template rendering fails.
|
||||||
|
pub async fn fallback(
|
||||||
|
State(templates): State<Templates>,
|
||||||
|
OriginalUri(uri): OriginalUri,
|
||||||
|
method: Method,
|
||||||
|
version: Version,
|
||||||
|
) -> Result<impl IntoResponse, FancyError> {
|
||||||
|
let ctx = NotFoundContext::new(&method, version, &uri);
|
||||||
|
// XXX: this should look at the Accept header and return JSON if requested
|
||||||
|
|
||||||
|
let res = templates.render_not_found(&ctx).await?;
|
||||||
|
|
||||||
|
Ok((StatusCode::NOT_FOUND, Html(res)))
|
||||||
|
}
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
//! Contexts used in templates
|
//! Contexts used in templates
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::{DateTime, Utc};
|
||||||
|
use http::{Method, Uri, Version};
|
||||||
use mas_data_model::{
|
use mas_data_model::{
|
||||||
AuthorizationGrant, BrowserSession, Client, CompatSsoLogin, CompatSsoLoginState,
|
AuthorizationGrant, BrowserSession, Client, CompatSsoLogin, CompatSsoLoginState,
|
||||||
UpstreamOAuthLink, UpstreamOAuthProvider, User, UserEmail, UserEmailVerification,
|
UpstreamOAuthLink, UpstreamOAuthProvider, User, UserEmail, UserEmailVerification,
|
||||||
@ -1009,3 +1010,40 @@ impl ErrorContext {
|
|||||||
self.details.as_deref()
|
self.details.as_deref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Context used by the not found (`404.html`) template
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct NotFoundContext {
|
||||||
|
method: String,
|
||||||
|
version: String,
|
||||||
|
uri: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NotFoundContext {
|
||||||
|
/// Constructs a context for the not found page
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(method: &Method, version: Version, uri: &Uri) -> Self {
|
||||||
|
Self {
|
||||||
|
method: method.to_string(),
|
||||||
|
version: format!("{version:?}"),
|
||||||
|
uri: uri.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TemplateContext for NotFoundContext {
|
||||||
|
fn sample(_now: DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
vec![
|
||||||
|
Self::new(&Method::GET, Version::HTTP_11, &"/".parse().unwrap()),
|
||||||
|
Self::new(&Method::POST, Version::HTTP_2, &"/foo/bar".parse().unwrap()),
|
||||||
|
Self::new(
|
||||||
|
&Method::PUT,
|
||||||
|
Version::HTTP_10,
|
||||||
|
&"/foo?bar=baz".parse().unwrap(),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -49,7 +49,7 @@ pub use self::{
|
|||||||
context::{
|
context::{
|
||||||
AppContext, CompatSsoContext, ConsentContext, EmailAddContext, EmailVerificationContext,
|
AppContext, CompatSsoContext, ConsentContext, EmailAddContext, EmailVerificationContext,
|
||||||
EmailVerificationPageContext, EmptyContext, ErrorContext, FormPostContext, IndexContext,
|
EmailVerificationPageContext, EmptyContext, ErrorContext, FormPostContext, IndexContext,
|
||||||
LoginContext, LoginFormField, PolicyViolationContext, PostAuthContext,
|
LoginContext, LoginFormField, NotFoundContext, PolicyViolationContext, PostAuthContext,
|
||||||
PostAuthContextInner, ReauthContext, ReauthFormField, RegisterContext, RegisterFormField,
|
PostAuthContextInner, ReauthContext, ReauthFormField, RegisterContext, RegisterFormField,
|
||||||
TemplateContext, UpstreamExistingLinkContext, UpstreamRegister, UpstreamSuggestLink,
|
TemplateContext, UpstreamExistingLinkContext, UpstreamRegister, UpstreamSuggestLink,
|
||||||
WithCsrf, WithOptionalSession, WithSession,
|
WithCsrf, WithOptionalSession, WithSession,
|
||||||
@ -222,6 +222,9 @@ pub enum TemplateError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
register_templates! {
|
register_templates! {
|
||||||
|
/// Render the not found fallback page
|
||||||
|
pub fn render_not_found(NotFoundContext) { "pages/404.html" }
|
||||||
|
|
||||||
/// Render the frontend app
|
/// Render the frontend app
|
||||||
pub fn render_app(AppContext) { "app.html" }
|
pub fn render_app(AppContext) { "app.html" }
|
||||||
|
|
||||||
@ -294,6 +297,7 @@ impl Templates {
|
|||||||
now: chrono::DateTime<chrono::Utc>,
|
now: chrono::DateTime<chrono::Utc>,
|
||||||
rng: &mut impl Rng,
|
rng: &mut impl Rng,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
check::render_not_found(self, now, rng).await?;
|
||||||
check::render_app(self, now, rng).await?;
|
check::render_app(self, now, rng).await?;
|
||||||
check::render_login(self, now, rng).await?;
|
check::render_login(self, now, rng).await?;
|
||||||
check::render_register(self, now, rng).await?;
|
check::render_register(self, now, rng).await?;
|
||||||
|
@ -13,6 +13,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@import "@fontsource/inter/400.css";
|
||||||
|
@import "@fontsource/inter/500.css";
|
||||||
|
@import "@fontsource/inter/600.css";
|
||||||
|
@import "@fontsource/inter/700.css";
|
||||||
|
@import "@vector-im/compound-design-tokens/assets/web/css/compound-design-tokens.css";
|
||||||
|
@import "@vector-im/compound-web/dist/style.css";
|
||||||
|
|
||||||
@config "../tailwind.templates.config.cjs";
|
@config "../tailwind.templates.config.cjs";
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
|
35
templates/pages/404.html
Normal file
35
templates/pages/404.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{#
|
||||||
|
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
#}
|
||||||
|
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section class="flex-1 flex items-center justify-center">
|
||||||
|
<div class="w-64 flex flex-col gap-2">
|
||||||
|
<h1 class="text-xl font-semibold">Page not found</h1>
|
||||||
|
<p>The page you were looking for doesn't exist or has been moved</p>
|
||||||
|
<a class="text-links hover:text-links/70" href="/">Go back to the homepage</a>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<code>
|
||||||
|
<pre class="whitespace-pre-wrap break-all">{{ method }} {{ uri }} {{ version }}
|
||||||
|
|
||||||
|
{{ version }} 404 Not Found</pre>
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
Reference in New Issue
Block a user