添加中文url支持, 添加可以指定目录功能

This commit is contained in:
2026-02-12 14:53:33 +08:00
parent 5d676fb989
commit 77eca78d86
3 changed files with 55 additions and 3 deletions

9
Cargo.lock generated
View File

@ -5,3 +5,12 @@ version = 4
[[package]] [[package]]
name = "mini_web_server" name = "mini_web_server"
version = "0.1.0" version = "0.1.0"
dependencies = [
"urlencoding",
]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"

View File

@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
urlencoding = "2.1.3"

View File

@ -1,12 +1,45 @@
use std::env;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use std::io::{BufRead, BufReader, Write}; use std::io::{BufRead, BufReader, Write};
use std::net::{TcpListener, TcpStream}; use std::net::{TcpListener, TcpStream};
use std::process::exit;
use std::sync::OnceLock;
use urlencoding::decode;
use mini_web_server::ThreadPool; use mini_web_server::ThreadPool;
static GLOBAL_PATH: OnceLock<String> = OnceLock::new();
fn main() { fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); let args: Vec<String> = env::args().collect();
let addr = String::from("127.0.0.1:7878");
match args.len() {
1 => {
let path = String::from("./public");
GLOBAL_PATH.set(path).unwrap();
}
2 => {
let path = String::from(&args[1]);
GLOBAL_PATH.set(path).unwrap();
if Path::new(GLOBAL_PATH.get().unwrap()).try_exists().is_err() {
println!("path is invalid or not exist: {}", GLOBAL_PATH.get().unwrap());
exit(0);
}
}
_ => {
println!("usage: {} path/to/asset/", args[0]);
exit(0);
}
}
println!("set root path: {}", GLOBAL_PATH.get().unwrap());
let listener = TcpListener::bind(addr).unwrap();
println!("serverd on http://{}/", listener.local_addr().unwrap());
let pool = ThreadPool::new(10); let pool = ThreadPool::new(10);
@ -66,7 +99,6 @@ fn handle_connection(mut stream: TcpStream) {
} }
// 6. 安全地构建文件路径 // 6. 安全地构建文件路径
let base_dir = "./public";
let requested_path = path.trim_start_matches('/'); let requested_path = path.trim_start_matches('/');
if requested_path.contains("..") { if requested_path.contains("..") {
stream.write(b"HTTP/1.1 403 Forbidden\r\n\r\n").unwrap(); stream.write(b"HTTP/1.1 403 Forbidden\r\n\r\n").unwrap();
@ -92,9 +124,19 @@ fn handle_connection(mut stream: TcpStream) {
// }; // };
// v4 // v4
let base_path = Path::new(base_dir); let base_path = Path::new(GLOBAL_PATH.get().unwrap());
let requested_path = path.trim_start_matches('/'); // 去掉开头的 '/' let requested_path = path.trim_start_matches('/'); // 去掉开头的 '/'
let requested_path = match decode(requested_path) {
Ok(decoded) => decoded.into_owned(),
Err(_) => {
let _ = stream.write(b"HTTP/1.1 400 Bad Request\r\n\r\n");
let _ = stream.flush();
return;
}
};
// 禁止路径遍历 // 禁止路径遍历
if requested_path.contains("..") { if requested_path.contains("..") {
stream.write(b"HTTP/1.1 403 Forbidden\r\n\r\n").unwrap(); stream.write(b"HTTP/1.1 403 Forbidden\r\n\r\n").unwrap();