更新了https功能,将原有的服务从http迁移到了https中

This commit is contained in:
2025-09-30 17:26:56 +08:00
parent 7fa1ae6301
commit 7143064a09
4 changed files with 143 additions and 31 deletions

View File

@@ -1,7 +1,10 @@
use std::pin::Pin;
use actix_web::middleware::from_fn;
use actix_web::{App, HttpResponse, HttpServer, Responder, delete, get, post, web};
use include_dir::{Dir, include_dir};
use log::{debug, error, info, warn};
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
use reqwest::Client;
use sqlx::postgres::PgPool;
mod auth;
@@ -18,6 +21,23 @@ use crate::models::{Claims, TokenResponse};
static STATIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/static");
static TEMPLATES_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates");
// 加载TLS证书和私钥
fn create_ssl_acceptor() -> Result<SslAcceptorBuilder, Box<dyn std::error::Error>> {
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
// 从环境变量获取证书和私钥路径
let key_path =
std::env::var("SSL_KEY_PATH").unwrap_or_else(|_| "path/to/private.key".to_string());
let cert_path =
std::env::var("SSL_CERT_PATH").unwrap_or_else(|_| "path/to/certificate.crt".to_string());
builder.set_private_key_file(&key_path, SslFiletype::PEM)?;
builder.set_certificate_chain_file(&cert_path)?;
// 返回构建器而不是构建后的接受器
Ok(builder)
}
#[post("/api/login")]
async fn login(
pool: web::Data<PgPool>,
@@ -610,18 +630,19 @@ async fn main() -> std::io::Result<()> {
eprintln!("警告:加载.env文件失败使用系统环境变量: {}", e);
}
// 2. 打印当前 RUST_LOG 的值(关键:验证配置是否生效)
// 打印当前 RUST_LOG 的值
let rust_log = std::env::var("RUST_LOG").unwrap_or_else(|_| "未设置".to_string());
eprintln!("当前 RUST_LOG 级别:{}", rust_log); // 这行用 eprintln!,不受日志级别影响
eprintln!("当前 RUST_LOG 级别:{}", rust_log);
env_logger::init(); // 添加这一行
env_logger::init();
info!("logger init successful");
// 初始化数据库连接池
let pool = match create_pool().await {
Ok(pool) => pool,
Err(e) => {
eprintln!("Failed to create database pool: {}", e);
eprintln!("Please check your database connection configuration in .env file");
error!("Failed to create database pool: {}", e);
error!("Please check your database connection configuration in .env file");
std::process::exit(1);
}
};
@@ -629,45 +650,99 @@ async fn main() -> std::io::Result<()> {
// 初始化HTTP客户端
let http_client = Client::new();
println!("Attempting to start server...");
// 尝试多个端口
let ports = vec![8080, 3000, 8000, 8888];
let mut server = None;
info!("Attempting to start server...");
for port in ports {
// 尝试多个端口
let ports = vec![443, 8443, 8080, 3000, 8000, 8888];
let mut server: Option<
Pin<Box<dyn std::future::Future<Output = std::io::Result<()>> + Unpin>>,
> = None;
let mut bound_port = 0; // 记录绑定的端口
// 使用&ports创建引用迭代器而不是获取所有权
for port in &ports {
let addr = format!("0.0.0.0:{}", port);
println!("Trying to bind to {}", addr);
info!("Trying to bind to {}", addr);
// 为每个服务器创建克隆的连接池和HTTP客户端
let pool_clone = pool.clone();
let http_client_clone = http_client.clone();
match HttpServer::new(move || {
create_server_config(pool_clone.clone(), http_client_clone.clone())
})
.bind(&addr)
{
Ok(s) => {
println!("Successfully bound to {}", addr);
server = Some(s);
break;
}
Err(e) => {
eprintln!("Failed to bind to {}: {}", addr, e);
if e.kind() == std::io::ErrorKind::PermissionDenied {
eprintln!(" -> Permission denied. Try running with sudo or use a port > 1024");
// 根据端口选择是否使用SSL
if *port == 443 || *port == 8443 {
// 对于443和8443端口使用HTTPS
// 为每个端口创建新的SSL构建器
let ssl_builder = match create_ssl_acceptor() {
Ok(builder) => builder,
Err(e) => {
eprintln!("Failed to create SSL acceptor: {}", e);
continue;
}
};
match HttpServer::new(move || {
create_server_config(pool_clone.clone(), http_client_clone.clone())
})
.bind_openssl(&addr, ssl_builder) // 直接传递构建器
{
Ok(s) => {
info!("Successfully bound to {} with HTTPS", addr);
// 将服务器运行Future转换为正确的类型
let server_future = s.run();
// 使用Box::pin将Pin<Box<Server>>转换为Pin<Box<dyn Future<Output = Result<(), std::io::Error>> + Unpin>>
server = Some(Box::pin(server_future));
bound_port = *port; // 记录绑定的端口
break;
}
Err(e) => {
eprintln!("Failed to bind to {} with HTTPS: {}", addr, e);
if e.kind() == std::io::ErrorKind::PermissionDenied {
eprintln!(" -> Permission denied. Try running with sudo or use a port > 1024");
}
continue;
}
}
} else {
// 对于其他端口使用HTTP
match HttpServer::new(move || {
create_server_config(pool_clone.clone(), http_client_clone.clone())
})
.bind(&addr)
{
Ok(s) => {
info!("Successfully bound to {} with HTTP", addr);
// 将服务器运行Future转换为正确的类型
let server_future = s.run();
// 使用Box::pin将Pin<Box<Server>>转换为Pin<Box<dyn Future<Output = Result<(), std::io::Error>> + Unpin>>
server = Some(Box::pin(server_future));
bound_port = *port; // 记录绑定的端口
break;
}
Err(e) => {
error!("Failed to bind to {} with HTTP: {}", addr, e);
if e.kind() == std::io::ErrorKind::PermissionDenied {
error!(
" -> Permission denied. Try running with sudo or use a port > 1024"
);
}
continue;
}
continue;
}
}
}
match server {
Some(s) => {
println!("Server started successfully");
s.run().await
// 使用记录的端口判断是否为HTTPS
if bound_port == 443 || bound_port == 8443 {
info!("Server started successfully with HTTPS");
} else {
info!("Server started successfully with HTTP");
}
s.await
}
None => {
eprintln!("Failed to bind to any port. Please check your system configuration.");
error!("Failed to bind to any port. Please check your system configuration.");
std::process::exit(1);
}
}