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
|
||||
.layer(
|
||||
InFlightCounterLayer::new("http.server.active_requests").on_request((
|
||||
|
@ -34,21 +34,26 @@ use std::{convert::Infallible, sync::Arc, time::Duration};
|
||||
|
||||
use axum::{
|
||||
body::{Bytes, HttpBody},
|
||||
extract::{FromRef, FromRequestParts},
|
||||
extract::{FromRef, FromRequestParts, OriginalUri, State},
|
||||
http::Method,
|
||||
response::{Html, IntoResponse},
|
||||
routing::{get, on, post, MethodFilter},
|
||||
Router,
|
||||
};
|
||||
use headers::HeaderName;
|
||||
use hyper::header::{
|
||||
use hyper::{
|
||||
header::{
|
||||
ACCEPT, ACCEPT_LANGUAGE, AUTHORIZATION, CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_TYPE,
|
||||
},
|
||||
StatusCode, Version,
|
||||
};
|
||||
use mas_axum_utils::FancyError;
|
||||
use mas_http::CorsLayerExt;
|
||||
use mas_keystore::{Encrypter, Keystore};
|
||||
use mas_policy::PolicyFactory;
|
||||
use mas_router::{Route, UrlBuilder};
|
||||
use mas_storage::{BoxClock, BoxRepository, BoxRng};
|
||||
use mas_templates::{ErrorContext, Templates};
|
||||
use mas_templates::{ErrorContext, NotFoundContext, Templates};
|
||||
use passwords::PasswordManager;
|
||||
use sqlx::PgPool;
|
||||
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
|
||||
|
||||
use chrono::Utc;
|
||||
use chrono::{DateTime, Utc};
|
||||
use http::{Method, Uri, Version};
|
||||
use mas_data_model::{
|
||||
AuthorizationGrant, BrowserSession, Client, CompatSsoLogin, CompatSsoLoginState,
|
||||
UpstreamOAuthLink, UpstreamOAuthProvider, User, UserEmail, UserEmailVerification,
|
||||
@ -1009,3 +1010,40 @@ impl ErrorContext {
|
||||
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::{
|
||||
AppContext, CompatSsoContext, ConsentContext, EmailAddContext, EmailVerificationContext,
|
||||
EmailVerificationPageContext, EmptyContext, ErrorContext, FormPostContext, IndexContext,
|
||||
LoginContext, LoginFormField, PolicyViolationContext, PostAuthContext,
|
||||
LoginContext, LoginFormField, NotFoundContext, PolicyViolationContext, PostAuthContext,
|
||||
PostAuthContextInner, ReauthContext, ReauthFormField, RegisterContext, RegisterFormField,
|
||||
TemplateContext, UpstreamExistingLinkContext, UpstreamRegister, UpstreamSuggestLink,
|
||||
WithCsrf, WithOptionalSession, WithSession,
|
||||
@ -222,6 +222,9 @@ pub enum TemplateError {
|
||||
}
|
||||
|
||||
register_templates! {
|
||||
/// Render the not found fallback page
|
||||
pub fn render_not_found(NotFoundContext) { "pages/404.html" }
|
||||
|
||||
/// Render the frontend app
|
||||
pub fn render_app(AppContext) { "app.html" }
|
||||
|
||||
@ -294,6 +297,7 @@ impl Templates {
|
||||
now: chrono::DateTime<chrono::Utc>,
|
||||
rng: &mut impl Rng,
|
||||
) -> anyhow::Result<()> {
|
||||
check::render_not_found(self, now, rng).await?;
|
||||
check::render_app(self, now, rng).await?;
|
||||
check::render_login(self, now, rng).await?;
|
||||
check::render_register(self, now, rng).await?;
|
||||
|
@ -13,6 +13,13 @@
|
||||
* 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";
|
||||
|
||||
@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