Gonna finally make a good website
This commit is contained in:
parent
2b02ffb79f
commit
aac5804d95
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
target
|
||||
.idea
|
||||
1377
Cargo.lock
generated
Normal file
1377
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "yyyi_ru"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
axum = "0.8.3"
|
||||
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
|
||||
tera="1.20.0"
|
||||
12
assets/HypertextPages/blog.html
Normal file
12
assets/HypertextPages/blog.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<title>Блог Гриши</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
21
assets/HypertextPages/index.html
Normal file
21
assets/HypertextPages/index.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<title>Гришина заглавная страничка</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-container">
|
||||
<div>
|
||||
<h2 class=""> Обо мне </h2>
|
||||
<p class="description-text">
|
||||
Я Андреев Григорий, от 21.06.2005.
|
||||
Живу в Москве, учусь прогать, люблю курить dwm и иногда пишу разного рода дичь.
|
||||
Самым интересным в своей жизни делюсь <a href="/blog">вот здесь</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
42
assets/css/common.css
Normal file
42
assets/css/common.css
Normal file
@ -0,0 +1,42 @@
|
||||
body, html {
|
||||
background-color: #151715;
|
||||
color: white;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.flex-justify-content-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: bold;
|
||||
font-size: 1.5em;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: aqua;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: deepskyblue;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #4c259a;
|
||||
}
|
||||
|
||||
a:visited:hover {
|
||||
color: #613d9c;
|
||||
}
|
||||
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod yyyi_ru;
|
||||
pub mod mtgott;
|
||||
6
src/main.rs
Normal file
6
src/main.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use yyyi_ru::yyyi_ru::MAIN;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
MAIN().await
|
||||
}
|
||||
4
src/mtgott/mod.rs
Normal file
4
src/mtgott/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub fn proclaim_glad_tidings() {
|
||||
println!("This project uses My Train Goes Off The Track!\n\
|
||||
But I ain't writing this shit second time")
|
||||
}
|
||||
132
src/yyyi_ru/mod.rs
Normal file
132
src/yyyi_ru/mod.rs
Normal file
@ -0,0 +1,132 @@
|
||||
use axum;
|
||||
use std::io;
|
||||
use std::fs;
|
||||
use std::collections::HashMap;
|
||||
use axum::http::HeaderValue;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use axum::http::header::CONTENT_TYPE;
|
||||
use tera;
|
||||
|
||||
use crate::mtgott::{proclaim_glad_tidings};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct StaticAsset {
|
||||
content_type: HeaderValue,
|
||||
content: Vec<u8>
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AssetsCache {
|
||||
page_index: StaticAsset,
|
||||
page_blog: StaticAsset,
|
||||
static_assets: HashMap<String, StaticAsset>
|
||||
}
|
||||
|
||||
struct ExtensionContentTypeCorr{
|
||||
extension: &'static str,
|
||||
content_type: HeaderValue,
|
||||
}
|
||||
|
||||
fn read_static_html_page(p: &Path) -> io::Result<StaticAsset> {
|
||||
Ok(StaticAsset {
|
||||
content_type: HeaderValue::from_str("text/html").unwrap(),
|
||||
content: fs::read(p)?
|
||||
})
|
||||
}
|
||||
|
||||
impl AssetsCache {
|
||||
fn load(p: &Path, need: &[ExtensionContentTypeCorr]) -> Result<AssetsCache, io::Error> {
|
||||
if !p.is_dir() {
|
||||
return Err(io::Error::from(io::ErrorKind::NotADirectory))
|
||||
}
|
||||
let mut st: HashMap<String, StaticAsset> = HashMap::new();
|
||||
let mut td: Vec<String> = vec![String::new()];
|
||||
while td.len() > 0 {
|
||||
let dshp_dir: String = td.pop().unwrap();
|
||||
let p_dir = p.join(dshp_dir.clone());
|
||||
for entry in fs::read_dir(p_dir)? {
|
||||
let entry = entry?;
|
||||
let dshp_child = if dshp_dir.len() > 0 {
|
||||
format!("{dshp_dir}/{}", entry.file_name().to_str().unwrap())
|
||||
} else {
|
||||
String::from(entry.file_name().to_str().unwrap())
|
||||
};
|
||||
let p_child = p.join(dshp_child.clone());
|
||||
if p_child.is_dir() {
|
||||
td.push(dshp_child);
|
||||
} else {
|
||||
if let Some(ext) = need.iter().find(|ext| {dshp_child.ends_with(ext.extension)}) {
|
||||
st.insert(dshp_child.clone(), StaticAsset {
|
||||
content_type: ext.content_type.clone(),
|
||||
content: fs::read(p.join(dshp_child))?
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(AssetsCache{
|
||||
page_index: read_static_html_page(&p.join("HypertextPages/index.html"))?,
|
||||
page_blog: read_static_html_page(&p.join("HypertextPages/blog.html"))?,
|
||||
static_assets: st
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async fn page_index(
|
||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>
|
||||
) -> impl axum::response::IntoResponse {
|
||||
(
|
||||
[(CONTENT_TYPE, assets.page_index.content_type.clone())],
|
||||
assets.page_index.content.clone()
|
||||
)
|
||||
}
|
||||
|
||||
async fn static_assets(
|
||||
axum::extract::Path(path): axum::extract::Path<String>,
|
||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
||||
) -> Result<([(axum::http::HeaderName, axum::http::HeaderValue); 1], Vec<u8>), axum::http::StatusCode> {
|
||||
if let Some(file) = assets.static_assets.get(&path) {
|
||||
return Ok((
|
||||
[(CONTENT_TYPE, file.content_type.clone())],
|
||||
file.content.clone()
|
||||
))
|
||||
}
|
||||
Err(axum::http::StatusCode::NOT_FOUND)
|
||||
}
|
||||
|
||||
|
||||
async fn page_blog(
|
||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>
|
||||
) -> impl axum::response::IntoResponse {
|
||||
axum::response::Html(String::from_utf8(assets.page_blog.content.clone()).unwrap())
|
||||
}
|
||||
|
||||
async fn fallback_page() -> axum::http::StatusCode {
|
||||
axum::http::StatusCode::NOT_FOUND
|
||||
}
|
||||
|
||||
pub async fn MAIN() {
|
||||
let manifest_dir = env!("CARGO_MANIFEST_DIR");
|
||||
println!("Cargo manifest dir: {manifest_dir}");
|
||||
let static_assets_types: &[ExtensionContentTypeCorr] = &[
|
||||
ExtensionContentTypeCorr{extension: "css", content_type: HeaderValue::from_str("text/css").unwrap()}
|
||||
];
|
||||
let assets = Arc::new(
|
||||
AssetsCache::load(
|
||||
&Path::new(manifest_dir).join("assets"),
|
||||
static_assets_types).unwrap());
|
||||
|
||||
// build our application with a single route
|
||||
let app = axum::Router::new()
|
||||
.without_v07_checks()
|
||||
.route("/", axum::routing::MethodRouter::new().get(page_index))
|
||||
.route("/assets/{*path}", axum::routing::get(static_assets))
|
||||
.route("/blog", axum::routing::get(page_blog))
|
||||
.fallback(fallback_page).with_state(assets);
|
||||
|
||||
// run our app with hyper, listening globally on port 3000
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user