a lot of shit
This commit is contained in:
parent
002767b85a
commit
c3f365e1f6
16 changed files with 1247 additions and 2 deletions
1025
Cargo.lock
generated
1025
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -4,3 +4,12 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
axum = "0.8.7"
|
||||
chrono = "0.4"
|
||||
http = "1.3.1"
|
||||
mime_guess = "2.0"
|
||||
rust-embed = "8.9.0"
|
||||
term_size = "0.1"
|
||||
tokio = { version = "*", features = ["full"] }
|
||||
tower-http = "0.6.6"
|
||||
tower-service = "0.3.3"
|
||||
|
|
|
|||
0
README.md
Normal file
0
README.md
Normal file
30
TECHDOC.md
Normal file
30
TECHDOC.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Техдок проекта
|
||||
|
||||
## Идея
|
||||
- Что делает проект:
|
||||
должен выполнять front и back задач
|
||||
- Зачем нужен:
|
||||
чтобы выпендрится
|
||||
|
||||
## Технологии
|
||||
- Язык:
|
||||
rust
|
||||
- Фреймворки:
|
||||
- Библиотеки:
|
||||
tokio
|
||||
|
||||
## Структура проекта
|
||||
- Основные файлы:
|
||||
- Модули:
|
||||
|
||||
## TODO
|
||||
- Задача 1:
|
||||
- Задача 2:
|
||||
|
||||
## Проблемы и решения
|
||||
- Проблема 1:
|
||||
- Решение:
|
||||
|
||||
## Заметки
|
||||
- Идеи для улучшений:
|
||||
- Вопросы:
|
||||
0
assets/content/about.md
Normal file
0
assets/content/about.md
Normal file
BIN
assets/media/uzi.gif
Normal file
BIN
assets/media/uzi.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 522 KiB |
14
assets/pages/about.html
Normal file
14
assets/pages/about.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>About</title>
|
||||
<base href="{{BASE_URL}}">
|
||||
</head>
|
||||
<body>
|
||||
<h1>About Page</h1>
|
||||
<p>This is the about page.</p>
|
||||
<a href="/">index</a>
|
||||
</body>
|
||||
</html>
|
||||
14
assets/pages/index.html
Normal file
14
assets/pages/index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<base href="{{BASE_URL}}">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello world!</h1>
|
||||
<img src="media/uzi.gif"/>
|
||||
<a href="about/">about</a>
|
||||
</body>
|
||||
</html>
|
||||
0
assets/scripts/hello.js
Normal file
0
assets/scripts/hello.js
Normal file
0
assets/styles/main.css
Normal file
0
assets/styles/main.css
Normal file
5
src/assets.rs
Normal file
5
src/assets.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
use rust_embed::Embed;
|
||||
|
||||
#[derive(Embed, Debug)]
|
||||
#[folder = "assets"]
|
||||
pub struct Assets;
|
||||
1
src/debug/mod.rs
Normal file
1
src/debug/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod static_content;
|
||||
12
src/debug/static_content.rs
Normal file
12
src/debug/static_content.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
use crate::assets::Assets;
|
||||
// Добавляем импорт для функции logger
|
||||
use crate::logger::logger as log;
|
||||
|
||||
pub fn print_static_content() {
|
||||
|
||||
// Собираем список файлов и логируем каждый как DEBUG (3)
|
||||
let total_files: Vec<_> = Assets::iter().collect();
|
||||
for file in total_files {
|
||||
log(3, file.as_ref(), false);
|
||||
}
|
||||
}
|
||||
33
src/logger.rs
Normal file
33
src/logger.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use chrono::Local;
|
||||
use term_size;
|
||||
|
||||
const RESET: &str = "\x1b[0m";
|
||||
const WHITE: &str = "\x1b[1;37m";
|
||||
const YELLOW: &str = "\x1b[1;33m";
|
||||
const RED: &str = "\x1b[1;31m";
|
||||
const BLUE: &str = "\x1b[1;34m";
|
||||
const GREEN: &str = "\x1b[1;32m";
|
||||
const TEXT_COLOR_NORMAL: &str = "\x1b[22;37m";
|
||||
const TEXT_COLOR_BOLD: &str = "\x1b[1;37m";
|
||||
|
||||
pub fn logger(level: i32, string: &str, bold: bool) {
|
||||
let (level_str, color) = match level {
|
||||
0 => ("INFO", GREEN),
|
||||
1 => ("WARN", YELLOW),
|
||||
2 => ("ERROR", RED),
|
||||
3 => ("DEBUG", BLUE),
|
||||
_ => ("UNKNOWN", WHITE),
|
||||
};
|
||||
|
||||
let text_color = if bold { TEXT_COLOR_BOLD } else { TEXT_COLOR_NORMAL };
|
||||
|
||||
let time = Local::now().format("%H:%M:%S").to_string();
|
||||
let width = term_size::dimensions().map(|(w, _)| w).unwrap_or(80);
|
||||
let inner_width = width - 2; // Account for 1 space padding on each side
|
||||
|
||||
let prefix = format!("[{}]", level_str);
|
||||
let visible_len = prefix.len() + 1 + string.len(); // [TYPE] space message
|
||||
let spaces = inner_width.saturating_sub(visible_len + time.len());
|
||||
|
||||
print!(" {}{}{}{}{}{}{}{}{}\n", color, prefix, " ", text_color, string, RESET, " ".repeat(spaces), color, time);
|
||||
}
|
||||
22
src/main.rs
22
src/main.rs
|
|
@ -1,3 +1,21 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
mod logger;
|
||||
use crate::logger::logger as log;
|
||||
mod debug;
|
||||
mod assets;
|
||||
mod routing;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// build our application with auto-routing
|
||||
let app = routing::create_router();
|
||||
|
||||
debug::static_content::print_static_content();
|
||||
|
||||
// run our app with hyper, listening globally on port 3000
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
log(0, "Server started successfully on port 3000", true);
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
|
||||
log(0, "gkweb started", true)
|
||||
|
||||
}
|
||||
|
|
|
|||
84
src/routing.rs
Normal file
84
src/routing.rs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
use axum::{response::Response, routing::get, Router, extract::Path};
|
||||
use crate::assets::Assets;
|
||||
use mime_guess::from_path;
|
||||
use http::{StatusCode, header};
|
||||
use std::env;
|
||||
|
||||
fn get_base_url() -> String {
|
||||
env::var("BASE_URL").unwrap_or_else(|_| "/".to_string())
|
||||
}
|
||||
|
||||
fn internal_error() -> Response {
|
||||
Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body("500 Internal Server Error".into())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn serve_static_file(path: &str) -> Option<Response> {
|
||||
if let Some(file) = Assets::get(path) {
|
||||
let mime_type = from_path(path).first_or_octet_stream();
|
||||
Some(Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(header::CONTENT_TYPE, mime_type.as_ref())
|
||||
.body(file.data.into())
|
||||
.unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn serve_html_page(page_path: &str) -> Option<Response> {
|
||||
if let Some(file) = Assets::get(page_path) {
|
||||
let content = match String::from_utf8(file.data.into_owned()) {
|
||||
Ok(c) => c,
|
||||
Err(_) => return Some(internal_error()),
|
||||
};
|
||||
let base_url = get_base_url();
|
||||
let new_content = content.replace("{{BASE_URL}}", &base_url);
|
||||
let mime_type = from_path(page_path).first_or_octet_stream();
|
||||
Some(Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(header::CONTENT_TYPE, mime_type.as_ref())
|
||||
.body(new_content.into())
|
||||
.unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// создаёт роуты для axum
|
||||
pub fn create_router() -> Router {
|
||||
Router::new()
|
||||
.route("/", get(index_handler))
|
||||
.route("/{*path}", get(static_file_handler)) // <-- Заменяем other_handler
|
||||
}
|
||||
// особый хэндлер для index.html
|
||||
async fn index_handler() -> Response {
|
||||
if let Some(response) = serve_html_page("pages/index.html") {
|
||||
response
|
||||
} else {
|
||||
Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body("404 Not Found".into())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
async fn static_file_handler(Path(raw_path): Path<String>) -> Response {
|
||||
let path = raw_path.trim_end_matches('/').to_string();
|
||||
|
||||
if let Some(response) = serve_static_file(&path) {
|
||||
return response;
|
||||
}
|
||||
|
||||
let page_path = format!("pages/{}.html", path);
|
||||
if let Some(response) = serve_html_page(&page_path) {
|
||||
return response;
|
||||
}
|
||||
|
||||
Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body("404 Not Found".into())
|
||||
.unwrap()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue