use askama::Template;
use axum::{
Router,
middleware::map_response,
response::{Html, Response},
routing::get,
};
use ocre::{
Ctx, Error, ErrorPage, Result, render,
security::{ContentSecurityPolicy, DATA, HTTPS, NONE, PermissionsPolicy, SELF, UNSAFE_INLINE},
};
use worker::{Context, Env, HttpRequest, event};
#[event(start)]
fn start() {}
#[event(fetch)]
async fn fetch(req: HttpRequest, env: Env, _ctx: Context) -> worker::Result<worker::web_sys::Response> {
ocre::serve(routes(), req, env).await
}
fn routes() -> Router<Ctx> {
Router::new()
.route("/", get(home))
.route("/up", get(up))
.fallback(not_found)
.layer(map_response(error_page))
.layer(content_security_policy())
.layer(permissions_policy())
}
fn content_security_policy() -> ContentSecurityPolicy {
ContentSecurityPolicy::new()
.default_src(&[SELF])
.script_src(&[SELF, "https://unpkg.com"])
.style_src(&[SELF, UNSAFE_INLINE, "https://unpkg.com"])
.img_src(&[SELF, DATA, HTTPS])
.font_src(&[SELF, DATA])
.object_src(&[NONE])
.base_uri(&[SELF])
.frame_ancestors(&[SELF])
}
fn permissions_policy() -> PermissionsPolicy {
PermissionsPolicy::new().deny(&["camera", "microphone", "geolocation", "payment", "usb"])
}
#[derive(Template)]
#[template(path = "home.html")]
struct HomeView;
async fn home() -> Result<Html<String>> {
render(&HomeView)
}
async fn up() -> &'static str {
"OK"
}
async fn not_found() -> Error {
Error::NotFound
}
#[derive(Template)]
#[template(path = "error.html")]
struct ErrorView<'a> {
error: &'a ErrorPage,
}
async fn error_page(response: Response) -> Response {
ocre::error_page(response, |error| render(&ErrorView { error }))
}