feat: add pingora-demo
This commit is contained in:
2908
__network/pingora-demo/Cargo.lock
generated
Normal file
2908
__network/pingora-demo/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
__network/pingora-demo/Cargo.toml
Normal file
14
__network/pingora-demo/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "pingora-demo"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
pingora-core = "0.2"
|
||||
pingora-proxy = "0.2"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
async-trait = "0.1"
|
||||
mime_guess = "2.0"
|
||||
headers = "0.3"
|
||||
|
||||
|
||||
6
__network/pingora-demo/README.md
Normal file
6
__network/pingora-demo/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
> Copied from: https://mp.weixin.qq.com/s/RHSy2EeK3XTRYXtOSCO0Ug
|
||||
> https://play.hatter.me/doc/showDocDetail.jssp?id=8495
|
||||
|
||||
|
||||
80
__network/pingora-demo/src/main.rs
Normal file
80
__network/pingora-demo/src/main.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use async_trait::async_trait;
|
||||
use headers::{ContentLength, ContentType};
|
||||
use pingora_core::server::Server;
|
||||
use pingora_proxy::{ProxyHttp, Session};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use mime_guess::from_path;
|
||||
|
||||
struct StaticFileServer {
|
||||
root_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl StaticFileServer {
|
||||
fn new(root: impl AsRef<Path>) -> Self {
|
||||
StaticFileServer {
|
||||
root_dir: root.as_ref().to_path_buf(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ProxyHttp for StaticFileServer {
|
||||
async fn response_filter(&self, session: &mut Session, response: &mut pingora_http::Response) {
|
||||
let path = session.req_header().uri.path();
|
||||
let file_path = self.root_dir.join(&path[1..]); // 去除前导/
|
||||
|
||||
if let Ok(metadata) = tokio::fs::metadata(&file_path).await {
|
||||
if metadata.is_file() {
|
||||
if let Ok(file) = tokio::fs::read(&file_path).await {
|
||||
// 设置正确的Content-Type
|
||||
let mime = from_path(&file_path).first_or_octet_stream();
|
||||
response.headers_mut().insert(
|
||||
headers::CONTENT_TYPE,
|
||||
ContentType::from(mime).to_string().parse().unwrap(),
|
||||
);
|
||||
|
||||
// 设置Content-Length
|
||||
response.headers_mut().insert(
|
||||
headers::CONTENT_LENGTH,
|
||||
ContentLength(metadata.len()).to_string().parse().unwrap(),
|
||||
);
|
||||
|
||||
// 设置缓存头(CDN关键配置)
|
||||
response.headers_mut().insert(
|
||||
"cache-control",
|
||||
"public, max-age=31536000".parse().unwrap(), // 1年缓存
|
||||
);
|
||||
|
||||
*response.body_mut() = file.into();
|
||||
response.set_status(200);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 文件不存在
|
||||
*response.status_mut() = 404;
|
||||
*response.body_mut() = b"Not Found".to_vec().into();
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// 1. 初始化服务器
|
||||
let mut server = Server::new(Some("Static File Server")).unwrap();
|
||||
server.bootstrap();
|
||||
|
||||
// 2. 创建文件服务(假设静态文件在./static目录)
|
||||
let static_service = StaticFileServer::new("./static");
|
||||
let mut service = pingora_proxy::http_proxy_service(&server.configuration, static_service);
|
||||
|
||||
// 3. 监听端口
|
||||
service.add_tcp("0.0.0.0:8080");
|
||||
|
||||
// 4. 启动服务
|
||||
server.add_service(service);
|
||||
println!("Static file server running on :8080");
|
||||
server.run_forever();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user