更新了https功能,将原有的服务从http迁移到了https中
This commit is contained in:
5
.env
5
.env
@@ -3,4 +3,7 @@ DATABASE_URL=postgres://milkydata:44n6FdB8CdDAk5rk@154.37.213.24:5432/milkydata
|
||||
WECHAT_APPID="wx5b00eb90621802f7"
|
||||
WECHAT_SECRET="494efc513faa310bfba588bda2849bfd"
|
||||
JWT_SECRET="your_super_secret_key"
|
||||
RUST_LOG=info
|
||||
SSL_KEY_PATH=/etc/ssl/private/private.key
|
||||
SSL_CERT_PATH=/etc/ssl/certs/full_chain.pem
|
||||
RUST_LOG=info
|
||||
APP_VERSION="0.1.9"
|
||||
33
Cargo.lock
generated
33
Cargo.lock
generated
@@ -51,6 +51,7 @@ dependencies = [
|
||||
"actix-codec",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
"actix-utils",
|
||||
"base64",
|
||||
"bitflags",
|
||||
@@ -143,6 +144,25 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-tls"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac453898d866cdbecdbc2334fe1738c747b4eba14a677261f2b768ba05329389"
|
||||
dependencies = [
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"futures-core",
|
||||
"impl-more",
|
||||
"openssl",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-openssl",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-utils"
|
||||
version = "3.0.1"
|
||||
@@ -166,6 +186,7 @@ dependencies = [
|
||||
"actix-rt",
|
||||
"actix-server",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
"actix-utils",
|
||||
"actix-web-codegen",
|
||||
"bytes",
|
||||
@@ -2053,6 +2074,7 @@ dependencies = [
|
||||
"include_dir",
|
||||
"jsonwebtoken",
|
||||
"log",
|
||||
"openssl",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -2709,6 +2731,17 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-openssl"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59df6849caa43bb7567f9a36f863c447d95a11d5903c9cc334ba32576a27eadd"
|
||||
dependencies = [
|
||||
"openssl",
|
||||
"openssl-sys",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.2"
|
||||
|
||||
@@ -5,7 +5,7 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
actix-files = "0.6.8"
|
||||
actix-web = "4.11.0"
|
||||
actix-web = {version = "4.11.0", features=["openssl"]}
|
||||
chrono = {version = "0.4.41", features=["serde"]}
|
||||
dotenvy = "0.15.7"
|
||||
env_logger = "0.11.8"
|
||||
@@ -13,6 +13,7 @@ error = "0.1.9"
|
||||
include_dir = "0.7.4"
|
||||
jsonwebtoken = "9.3.1"
|
||||
log = "0.4.28"
|
||||
openssl = "0.10.73"
|
||||
reqwest = { version = "0.12.23", features=["json"]}
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.143"
|
||||
|
||||
133
src/main.rs
133
src/main.rs
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user