mirror of
https://github.com/RGBCube/Site
synced 2025-08-01 13:37:49 +00:00
Start rewriting for axum
This commit is contained in:
parent
a5ffcce3c8
commit
52783348df
10 changed files with 417 additions and 824 deletions
1022
Cargo.lock
generated
1022
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -9,8 +9,9 @@ repositoty = "https://github.com/RGBCube/rgbcube.github.io"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "4.4.1", features = [ "openssl" ] }
|
|
||||||
anyhow = "1.0.77"
|
anyhow = "1.0.77"
|
||||||
|
axum = "0.7.3"
|
||||||
|
axum-server = { version = "0.6.0", features = [ "tls-rustls" ] }
|
||||||
bytes = "1.5.0"
|
bytes = "1.5.0"
|
||||||
cargo_toml = "0.17.2"
|
cargo_toml = "0.17.2"
|
||||||
chrono = "0.4.31"
|
chrono = "0.4.31"
|
||||||
|
@ -18,11 +19,13 @@ clap = { version = "4.4.12", features = [ "derive" ] }
|
||||||
embed = { git = "https://github.com/RGBCube/embed-rs" }
|
embed = { git = "https://github.com/RGBCube/embed-rs" }
|
||||||
env_logger = "0.10.1"
|
env_logger = "0.10.1"
|
||||||
log = { version = "0.4.20", features = [ "serde" ] }
|
log = { version = "0.4.20", features = [ "serde" ] }
|
||||||
maud = { version = "0.25.0", features = [ "actix-web" ] }
|
maud = { git = "https://github.com/lambda-fairy/maud", features = [ "axum" ] }
|
||||||
mime_guess = "2.0.4"
|
mime_guess = "2.0.4"
|
||||||
minify-js = "0.6.0"
|
minify-js = "0.6.0"
|
||||||
openssl = "0.10.62"
|
|
||||||
pulldown-cmark = "0.9.3"
|
pulldown-cmark = "0.9.3"
|
||||||
|
tokio = { version = "1.35.1", features = [ "full" ] }
|
||||||
|
tower = "0.4.13"
|
||||||
|
tower-http = { version = "0.5.0", features = [ "trace" ] }
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
proc-macro2 = { git = "https://github.com/RGBCube/proc-macro2" }
|
proc-macro2 = { git = "https://github.com/RGBCube/proc-macro2" }
|
||||||
|
|
|
@ -72,12 +72,7 @@
|
||||||
inherit cargoArtifacts;
|
inherit cargoArtifacts;
|
||||||
});
|
});
|
||||||
in {
|
in {
|
||||||
devShells.${system}.default = crane.devShell {
|
devShells.${system}.default = crane.devShell {};
|
||||||
packages = with nixpkgs.legacyPackages.${system}; [
|
|
||||||
openssl
|
|
||||||
pkg-config
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
checks.${system} = {
|
checks.${system} = {
|
||||||
inherit site;
|
inherit site;
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
|
use axum::Router;
|
||||||
|
|
||||||
mod internal_server_error;
|
mod internal_server_error;
|
||||||
mod not_found;
|
mod not_found;
|
||||||
|
|
||||||
use actix_web::{
|
|
||||||
http::StatusCode,
|
|
||||||
middleware::ErrorHandlers,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn handler<B: 'static>() -> ErrorHandlers<B> {
|
pub fn handler<B: 'static>() -> ErrorHandlers<B> {
|
||||||
ErrorHandlers::new()
|
Router::new().fallback(not_found::handler).handler(
|
||||||
.handler(StatusCode::NOT_FOUND, not_found::handler)
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
.handler(
|
internal_server_error::handler,
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
)
|
||||||
internal_server_error::handler,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,29 @@
|
||||||
use std::array;
|
use std::array;
|
||||||
|
|
||||||
use actix_web::{
|
use maud::{
|
||||||
dev::ServiceResponse,
|
html,
|
||||||
middleware::ErrorHandlerResponse,
|
Markup,
|
||||||
};
|
};
|
||||||
use maud::html;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asset,
|
asset,
|
||||||
page::cube,
|
page::cube,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn handler<B: 'static>(
|
pub fn handler() -> Markup {
|
||||||
response: ServiceResponse<B>,
|
cube::create(
|
||||||
) -> actix_web::Result<ErrorHandlerResponse<B>> {
|
Some("404"),
|
||||||
let (request, response) = response.into_parts();
|
asset::Css::Shared("cube-grid.css"),
|
||||||
|
array::from_fn(|_| {
|
||||||
let response = response.set_body(
|
html! {
|
||||||
cube::create(
|
.frame {
|
||||||
Some("404"),
|
a href="/" { "404" }
|
||||||
asset::Css::Shared("cube-grid.css"),
|
}
|
||||||
array::from_fn(|_| {
|
.square .black {}
|
||||||
(html! {
|
.square .magenta {}
|
||||||
.frame {
|
.square .magenta {}
|
||||||
a href="/" { "404" }
|
.square .black {}
|
||||||
}
|
}
|
||||||
.square .black {}
|
}),
|
||||||
.square .magenta {}
|
)
|
||||||
.square .magenta {}
|
|
||||||
.square .black {}
|
|
||||||
})
|
|
||||||
.clone()
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.into_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(ErrorHandlerResponse::Response(
|
|
||||||
ServiceResponse::new(request, response)
|
|
||||||
.map_into_boxed_body()
|
|
||||||
.map_into_right_body(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
62
src/main.rs
62
src/main.rs
|
@ -1,4 +1,4 @@
|
||||||
#![feature(iterator_try_collect, lazy_cell, let_chains)]
|
#![feature(lazy_cell, let_chains)]
|
||||||
|
|
||||||
mod asset;
|
mod asset;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
@ -7,21 +7,16 @@ mod minify;
|
||||||
mod page;
|
mod page;
|
||||||
mod routes;
|
mod routes;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::{
|
||||||
|
net::SocketAddr,
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
use actix_web::{
|
|
||||||
main as async_main,
|
|
||||||
middleware,
|
|
||||||
App,
|
|
||||||
HttpServer,
|
|
||||||
};
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use axum::Router;
|
||||||
|
use axum_server::tls_rustls::RustlsConfig;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use openssl::ssl::{
|
use tower_http::trace::TraceLayer;
|
||||||
SslAcceptor,
|
|
||||||
SslFiletype,
|
|
||||||
SslMethod,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version, about)]
|
#[command(author, version, about)]
|
||||||
|
@ -41,7 +36,7 @@ struct Cli {
|
||||||
key: Option<PathBuf>,
|
key: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
|
|
||||||
|
@ -51,35 +46,26 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.format_timestamp(None)
|
.format_timestamp(None)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let server = HttpServer::new(|| {
|
let app = Router::new()
|
||||||
App::new()
|
.merge(routes::router())
|
||||||
.wrap(middleware::Logger::default())
|
.merge(errors::router())
|
||||||
.wrap(errors::handler())
|
.layer(TraceLayer::new_for_http())
|
||||||
.service(routes::handler())
|
.into_make_service();
|
||||||
});
|
|
||||||
|
|
||||||
let server = if let Some(certificate_path) = args.certificate
|
let address = SocketAddr::from(([0, 0, 0, 0], args.port));
|
||||||
|
|
||||||
|
if let Some(certificate_path) = args.certificate
|
||||||
&& let Some(key_path) = args.key
|
&& let Some(key_path) = args.key
|
||||||
{
|
{
|
||||||
let mut builder = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
|
let config = RustlsConfig::from_pem_file(certificate_path, key_path)
|
||||||
|
.await
|
||||||
|
.with_context(|| "Failed to create TLS configuration from PEM files")?;
|
||||||
|
|
||||||
builder
|
axum_server::bind_rustls(address, config).serve(app).await
|
||||||
.set_private_key_file(key_path, SslFiletype::PEM)
|
|
||||||
.unwrap();
|
|
||||||
builder
|
|
||||||
.set_certificate_chain_file(certificate_path)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
server.bind_openssl(("0.0.0.0", args.port), builder)
|
|
||||||
} else {
|
} else {
|
||||||
server.bind(("0.0.0.0", args.port))
|
axum_server::bind(address).serve(app).await
|
||||||
};
|
}
|
||||||
|
.with_context(|| "Failed to run server")?;
|
||||||
server
|
|
||||||
.with_context(|| format!("Failed to bind to 0.0.0.0:{}", args.port))?
|
|
||||||
.run()
|
|
||||||
.await
|
|
||||||
.with_context(|| "Failed to run HttpServer")?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use actix_web::get;
|
|
||||||
use maud::Markup;
|
use maud::Markup;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -9,11 +8,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[get("/about")]
|
pub async fn handler() -> Markup {
|
||||||
pub async fn handler() -> actix_web::Result<Markup> {
|
text::create(
|
||||||
Ok(text::create(
|
|
||||||
Some("About"),
|
Some("About"),
|
||||||
Page::About,
|
Page::About,
|
||||||
markdown::parse(embed::string!("about.md").as_ref()),
|
markdown::parse(embed::string!("about.md").as_ref()),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
path::Path,
|
path,
|
||||||
sync::LazyLock,
|
sync::LazyLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
use actix_web::{
|
use axum::{
|
||||||
get,
|
body::Body,
|
||||||
web,
|
extract::Path,
|
||||||
HttpResponse,
|
http::{
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
Response,
|
||||||
|
StatusCode,
|
||||||
|
},
|
||||||
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
|
@ -19,7 +24,7 @@ static ASSETS: LazyLock<HashMap<String, Bytes>> = LazyLock::new(|| {
|
||||||
let mut assets = HashMap::new();
|
let mut assets = HashMap::new();
|
||||||
|
|
||||||
for file in embed::dir!("..").flatten() {
|
for file in embed::dir!("..").flatten() {
|
||||||
let path = Path::new(file.path().as_ref())
|
let path = path::Path::new(file.path().as_ref())
|
||||||
.file_name()
|
.file_name()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_str()
|
.to_str()
|
||||||
|
@ -46,19 +51,19 @@ static ASSETS: LazyLock<HashMap<String, Bytes>> = LazyLock::new(|| {
|
||||||
assets
|
assets
|
||||||
});
|
});
|
||||||
|
|
||||||
#[get("/assets/{path}")]
|
pub async fn handler(Path(path): Path<String>) -> Response<Body> {
|
||||||
pub async fn handler(path: web::Path<String>) -> HttpResponse {
|
|
||||||
let path = path.into_inner();
|
|
||||||
|
|
||||||
if let Some(body) = ASSETS.get(&path) {
|
if let Some(body) = ASSETS.get(&path) {
|
||||||
HttpResponse::Ok()
|
(
|
||||||
.content_type(
|
[(
|
||||||
|
CONTENT_TYPE,
|
||||||
mime_guess::from_path(&path)
|
mime_guess::from_path(&path)
|
||||||
.first_or_octet_stream()
|
.first_or_octet_stream()
|
||||||
.essence_str(),
|
.essence_str(),
|
||||||
)
|
)],
|
||||||
.body(Bytes::clone(body))
|
Bytes::clone(body),
|
||||||
|
)
|
||||||
|
.into_response()
|
||||||
} else {
|
} else {
|
||||||
HttpResponse::NotFound().into()
|
StatusCode::NOT_FOUND.into_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use actix_web::get;
|
|
||||||
use maud::{
|
use maud::{
|
||||||
html,
|
html,
|
||||||
Markup,
|
Markup,
|
||||||
|
@ -9,9 +8,8 @@ use crate::{
|
||||||
page::cube,
|
page::cube,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[get("/")]
|
pub async fn handler() -> Markup {
|
||||||
pub async fn handler() -> actix_web::Result<Markup> {
|
cube::create(
|
||||||
Ok(cube::create(
|
|
||||||
None,
|
None,
|
||||||
asset::css::owned!("index.css"),
|
asset::css::owned!("index.css"),
|
||||||
[
|
[
|
||||||
|
@ -46,5 +44,5 @@ pub async fn handler() -> actix_web::Result<Markup> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
|
use axum::{
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
|
||||||
mod about;
|
mod about;
|
||||||
mod assets;
|
mod assets;
|
||||||
mod index;
|
mod index;
|
||||||
|
|
||||||
use actix_web::{
|
pub fn router() -> Router {
|
||||||
web,
|
Router::new()
|
||||||
Scope,
|
.route("/", get(index::handler))
|
||||||
};
|
.route("/about", get(about::handler))
|
||||||
|
.route("/assets/*path", get(assets::handler))
|
||||||
pub fn handler() -> Scope {
|
|
||||||
web::scope("")
|
|
||||||
.service(index::handler)
|
|
||||||
.service(about::handler)
|
|
||||||
.service(assets::handler)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue