feat: 实现后端多环境配置机制
- 使用 toml crate 替代 config crate 直接读取配置文件 - 创建 config/default.toml、config/development.toml、config/production.toml - 重写 config.rs 支持多环境配置加载 - 增强 deploy.sh 支持 development/production 环境参数 - 更新 IMPROVEMENTS.md 标记环境区分完成
This commit is contained in:
82
AGENTS.md
82
AGENTS.md
@@ -22,7 +22,7 @@ src/
|
||||
├── auth.rs # JWT 中间件,令牌生成/验证
|
||||
├── db.rs # 数据库操作(通过 sqlx 执行原始 SQL)
|
||||
├── models.rs # 数据结构(Claims、User、WeatherData 等)
|
||||
├── config.rs # 配置结构体(未使用 — 死代码,待清理)
|
||||
├── config.rs # 配置加载(支持多环境:config/*.toml)
|
||||
└── handlers/ # 路由处理器模块
|
||||
├── mod.rs # 模块导出
|
||||
├── auth.rs # 登录相关 (login)
|
||||
@@ -32,6 +32,11 @@ src/
|
||||
├── health.rs # 健康检查 (/health)
|
||||
└── static_files.rs # 静态文件服务 (/static/{path})
|
||||
|
||||
config/
|
||||
├── default.toml # 默认配置(所有环境的共同默认值)
|
||||
├── development.toml # 开发/测试环境配置
|
||||
└── production.toml # 生产环境配置
|
||||
|
||||
migrations/
|
||||
└── 001_add_payment_fields.sql # 用于添加支付字段的 ALTER TABLE
|
||||
|
||||
@@ -40,6 +45,9 @@ static/
|
||||
|
||||
tests/
|
||||
└── integration_test.rs # 基础测试框架
|
||||
|
||||
deploy.sh # 部署脚本(支持 development/production 参数)
|
||||
.env.example # 环境变量模板
|
||||
```
|
||||
|
||||
## 数据库表结构
|
||||
@@ -149,18 +157,54 @@ pub async fn function_name(pool: &PgPool, param: i32) -> Result<Type, String> {
|
||||
|
||||
## 环境变量
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgres://user:pass@host:5432/dbname
|
||||
WECHAT_APPID=wx...
|
||||
WECHAT_SECRET=...
|
||||
JWT_SECRET=your_secret_key
|
||||
SSL_KEY_PATH=/path/to/key
|
||||
SSL_CERT_PATH=/path/to/cert
|
||||
RUST_LOG=info
|
||||
APP_VERSION=0.2.0
|
||||
FREE_USER_DATA_LIMIT=20
|
||||
### 方式一:使用配置文件(推荐)
|
||||
|
||||
通过 `APP_ENV` 环境变量选择配置文件:
|
||||
|
||||
```bash
|
||||
APP_ENV=development cargo run # 使用 config/development.toml
|
||||
APP_ENV=production cargo run # 使用 config/production.toml
|
||||
```
|
||||
|
||||
**配置文件**:
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| `config/default.toml` | 所有环境的共同默认值 |
|
||||
| `config/development.toml` | 开发/测试环境覆盖 |
|
||||
| `config/production.toml` | 生产环境覆盖 |
|
||||
|
||||
**示例 production.toml**:
|
||||
```toml
|
||||
database_url = "postgres://user:pass@host:5432/dbname"
|
||||
wechat_appid = "wx..."
|
||||
jwt_secret = "your_secret_key"
|
||||
rust_log = "info"
|
||||
free_user_data_limit = 20
|
||||
server_host = "0.0.0.0"
|
||||
server_ports = [4433, 8443, 8080, 3000, 8000, 8888]
|
||||
```
|
||||
|
||||
### 方式二:直接环境变量
|
||||
|
||||
最高优先级,可覆盖配置文件:
|
||||
|
||||
```env
|
||||
APP_DATABASE_URL=postgres://user:pass@host:5432/dbname
|
||||
APP_JWT_SECRET=your_secret_key
|
||||
APP_WECHAT_APPID=wx...
|
||||
APP_RUST_LOG=info
|
||||
```
|
||||
|
||||
### systemd service 配置
|
||||
|
||||
测试服务和生产服务通过不同 systemd unit 和工作目录隔离:
|
||||
|
||||
| 服务 | systemd unit | 工作目录 | APP_ENV |
|
||||
|------|-------------|---------|---------|
|
||||
| 测试 | `rust-backend-dev.service` | `/root/rust/rust_backend_dev` | `development` |
|
||||
| 生产 | `rust-backend.service` | `/root/rust/rust_backend` | (使用 .env) |
|
||||
|
||||
## 约束条件
|
||||
|
||||
### 已知兼容性问题
|
||||
@@ -178,7 +222,6 @@ FREE_USER_DATA_LIMIT=20
|
||||
- 在 JWT Claims 中添加 `is_admin`(必须查询数据库)
|
||||
- 信任 JWT 中的 `is_paid` 来做配额决策(必须查询数据库)
|
||||
- 使用 `as any`、`@ts-ignore` 或类型错误抑制
|
||||
- 修改 config.rs(死代码)
|
||||
- 添加支付网关集成
|
||||
- 添加审计日志
|
||||
|
||||
@@ -232,10 +275,17 @@ App::new()
|
||||
## 构建与运行
|
||||
|
||||
```bash
|
||||
cargo build # 编译
|
||||
cargo run # 启动服务器
|
||||
cargo test # 运行测试
|
||||
cargo clippy # 代码检查
|
||||
cargo build # 编译
|
||||
APP_ENV=development cargo run # 开发环境运行
|
||||
APP_ENV=production cargo run # 生产环境运行
|
||||
cargo test # 运行测试
|
||||
cargo clippy # 代码检查
|
||||
```
|
||||
|
||||
**部署**:
|
||||
```bash
|
||||
./deploy.sh development # 部署到测试服务器
|
||||
./deploy.sh production # 部署到生产服务器
|
||||
```
|
||||
|
||||
服务器尝试端口顺序:4433、8443、8080、3000、8000、8888
|
||||
|
||||
60
Cargo.lock
generated
60
Cargo.lock
generated
@@ -1976,6 +1976,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber",
|
||||
@@ -2116,6 +2117,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
@@ -2706,6 +2716,47 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_write",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_write"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.2"
|
||||
@@ -3332,6 +3383,15 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.45.0"
|
||||
|
||||
@@ -21,6 +21,7 @@ serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.143"
|
||||
sqlx = { version = "0.8.6", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
toml = "0.8"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
||||
@@ -538,6 +538,28 @@ fi
|
||||
- 本改进与"前后端版本统一管理"(改进路线图 P1)可合并实施
|
||||
- 本改进与"拆分 main.rs 路由处理器"(改进路线图 P1)有协同效应
|
||||
|
||||
### 实施结果
|
||||
|
||||
✅ **已完成** (2026-04-17)
|
||||
|
||||
**实际实施方案**:采用简化方案 + TOML 配置文件
|
||||
|
||||
| 改动项 | 说明 |
|
||||
|--------|------|
|
||||
| `config.rs` | 重写为使用 `toml` crate 直接读取配置文件 |
|
||||
| `config/*.toml` | 创建 `default.toml`、`development.toml`、`production.toml` |
|
||||
| `Cargo.toml` | 添加 `toml = "0.8"` 依赖,移除 `config = "0.14"` |
|
||||
| `deploy.sh` | 重写支持 `development`/`production` 环境参数 |
|
||||
| systemd service | 创建 `rust-backend-dev.service` 测试服务 |
|
||||
|
||||
**关键修复**:
|
||||
- TOML 文件去掉 `[development]` 等 section 头(config crate 遗留语法)
|
||||
- `database_url` 使用 `127.0.0.1` 而非 `localhost`(Docker PostgreSQL 监听地址)
|
||||
|
||||
**测试验证**:
|
||||
- 测试服务运行在端口 8080
|
||||
- Nginx 代理 `https://xmclassmate.top/dev/api/login` 正常工作
|
||||
|
||||
---
|
||||
|
||||
## 十二、付费功能系统
|
||||
@@ -732,5 +754,5 @@ pages/
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-04-14
|
||||
**最后更新**:2026-04-17
|
||||
**维护者**:milky
|
||||
|
||||
54
deploy.sh
54
deploy.sh
@@ -1,18 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# 部署脚本 - Rust Backend
|
||||
# ==============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
# --- 1. 配置 ---
|
||||
PROJECT_NAME="rust-backend"
|
||||
REMOTE_USER="root"
|
||||
REMOTE_HOST="1panel-server"
|
||||
REMOTE_DIR="/root/rust/rust_backend"
|
||||
SERVICE_NAME="rust-backend.service"
|
||||
APP_ENV="${1:-production}"
|
||||
|
||||
# --- 2. 脚本初始化 ---
|
||||
set -euo pipefail
|
||||
# 根据环境选择远程目录和服务
|
||||
case "${APP_ENV}" in
|
||||
development)
|
||||
REMOTE_DIR="/root/rust/rust_backend_dev"
|
||||
SERVICE_NAME="rust-backend-dev.service"
|
||||
;;
|
||||
production)
|
||||
REMOTE_DIR="/root/rust/rust_backend"
|
||||
SERVICE_NAME="rust-backend.service"
|
||||
;;
|
||||
*)
|
||||
echo "无效的环境: ${APP_ENV}"
|
||||
echo "支持的環境: development, production"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log_info() {
|
||||
echo -e "\033[32m[INFO]\033[0m $1"
|
||||
@@ -23,7 +33,6 @@ log_error() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# --- 3. 检查依赖 ---
|
||||
check_dependencies() {
|
||||
local deps=("cargo" "rsync" "ssh")
|
||||
for cmd in "${deps[@]}"; do
|
||||
@@ -34,17 +43,15 @@ check_dependencies() {
|
||||
log_info "所有依赖项检查通过。"
|
||||
}
|
||||
|
||||
# --- 4. 编译项目 ---
|
||||
build_project() {
|
||||
log_info "开始编译项目 (release模式)..."
|
||||
if cargo build --release; then
|
||||
log_info "开始编译项目 (release模式),环境=${APP_ENV}..."
|
||||
if APP_ENV="${APP_ENV}" cargo build --release; then
|
||||
log_info "项目编译成功。"
|
||||
else
|
||||
log_error "项目编译失败!"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- 5. 上传二进制文件 ---
|
||||
upload_binary() {
|
||||
local binary_path="./target/release/${PROJECT_NAME}"
|
||||
if [ ! -f "$binary_path" ]; then
|
||||
@@ -56,7 +63,18 @@ upload_binary() {
|
||||
log_info "文件上传成功。"
|
||||
}
|
||||
|
||||
# --- 6. 重启远程服务 ---
|
||||
upload_config() {
|
||||
# development 环境跳过(远程已有正确配置,使用 localhost 连接)
|
||||
if [ "${APP_ENV}" = "development" ]; then
|
||||
log_info "跳过配置文件上传(development 环境使用远程已有配置)..."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "正在上传配置文件到 ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/config/..."
|
||||
rsync -avzP --progress ./config/ "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/config/"
|
||||
log_info "配置文件上传成功。"
|
||||
}
|
||||
|
||||
restart_remote_service() {
|
||||
log_info "正在重启远程服务 '${SERVICE_NAME}'..."
|
||||
if ssh "${REMOTE_USER}@${REMOTE_HOST}" "systemctl restart ${SERVICE_NAME}"; then
|
||||
@@ -66,14 +84,16 @@ restart_remote_service() {
|
||||
fi
|
||||
}
|
||||
|
||||
# --- 7. 主执行流程 ---
|
||||
main() {
|
||||
log_info "========== 开始部署 =========="
|
||||
log_info "========== 开始部署 (环境: ${APP_ENV}) =========="
|
||||
log_info "远程目录: ${REMOTE_DIR}"
|
||||
log_info "服务名称: ${SERVICE_NAME}"
|
||||
check_dependencies
|
||||
build_project
|
||||
upload_binary
|
||||
upload_config
|
||||
restart_remote_service
|
||||
log_info "========== 部署完成! =========="
|
||||
}
|
||||
|
||||
main
|
||||
main
|
||||
116
src/config.rs
116
src/config.rs
@@ -1,33 +1,105 @@
|
||||
use std::env;
|
||||
use dotenvy::dotenv;
|
||||
use tracing;
|
||||
//! 应用配置模块
|
||||
//!
|
||||
//! 支持多环境配置加载,优先级:环境变量 > 环境配置 > 默认配置
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
use serde::Deserialize;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct AppConfig {
|
||||
pub database_url: String,
|
||||
pub jwt_secret: String,
|
||||
pub wechat_appid: String,
|
||||
pub wechat_secret: String,
|
||||
pub jwt_secret: String,
|
||||
pub ssl_key_path: String,
|
||||
pub ssl_cert_path: String,
|
||||
pub rust_log: String,
|
||||
pub app_version: String,
|
||||
pub environment: String,
|
||||
pub free_user_data_limit: i32,
|
||||
pub server_host: String,
|
||||
#[serde(rename = "server_ports")]
|
||||
pub server_ports: Vec<u16>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
impl AppConfig {
|
||||
pub fn load() -> Result<Self, String> {
|
||||
// 加载.env文件
|
||||
if let Err(e) = dotenv() {
|
||||
tracing::warn!("无法加载.env文件 - {}", e);
|
||||
let env = std::env::var("APP_ENV").unwrap_or_else(|_| "development".into());
|
||||
|
||||
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| std::env::current_dir().unwrap());
|
||||
|
||||
let config_dir = manifest_dir.join("config");
|
||||
|
||||
let default_path = config_dir.join("default.toml");
|
||||
let env_path = config_dir.join(&format!("{}.toml", env));
|
||||
|
||||
let mut settings = toml::Table::new();
|
||||
|
||||
// 1. 加载 default.toml
|
||||
if default_path.exists() {
|
||||
let content = std::fs::read_to_string(&default_path)
|
||||
.map_err(|e| format!("读取 default.toml 失败: {}", e))?;
|
||||
let parsed: toml::Table =
|
||||
toml::from_str(&content).map_err(|e| format!("解析 default.toml 失败: {}", e))?;
|
||||
settings.extend(parsed);
|
||||
} else {
|
||||
return Err(format!("配置文件不存在: {}", default_path.display()));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
database_url: env::var("DATABASE_URL")
|
||||
.map_err(|_| "环境变量DATABASE_URL未设置".to_string())?,
|
||||
jwt_secret: env::var("JWT_SECRET")
|
||||
.map_err(|_| "环境变量JWT_SECRET未设置".to_string())?,
|
||||
wechat_appid: env::var("WECHAT_APPID")
|
||||
.map_err(|_| "环境变量WECHAT_APPID未设置".to_string())?,
|
||||
wechat_secret: env::var("WECHAT_SECRET")
|
||||
.map_err(|_| "环境变量WECHAT_SECRET未设置".to_string())?,
|
||||
server_ports: vec![8080, 3000, 8000, 8888],
|
||||
})
|
||||
// 2. 合并环境配置(覆盖默认值)
|
||||
if env_path.exists() {
|
||||
let content = std::fs::read_to_string(&env_path)
|
||||
.map_err(|e| format!("读取 {}.toml 失败: {}", env, e))?;
|
||||
let parsed: toml::Table =
|
||||
toml::from_str(&content).map_err(|e| format!("解析 {}.toml 失败: {}", env, e))?;
|
||||
settings.extend(parsed);
|
||||
}
|
||||
|
||||
// 3. 从环境变量加载(最高优先级)
|
||||
if let Ok(val) = std::env::var("APP_DATABASE_URL") {
|
||||
settings.insert("database_url".into(), toml::Value::String(val));
|
||||
}
|
||||
if let Ok(val) = std::env::var("APP_JWT_SECRET") {
|
||||
settings.insert("jwt_secret".into(), toml::Value::String(val));
|
||||
}
|
||||
if let Ok(val) = std::env::var("APP_WECHAT_APPID") {
|
||||
settings.insert("wechat_appid".into(), toml::Value::String(val));
|
||||
}
|
||||
if let Ok(val) = std::env::var("APP_WECHAT_SECRET") {
|
||||
settings.insert("wechat_secret".into(), toml::Value::String(val));
|
||||
}
|
||||
if let Ok(val) = std::env::var("APP_RUST_LOG") {
|
||||
settings.insert("rust_log".into(), toml::Value::String(val));
|
||||
}
|
||||
if let Ok(val) = std::env::var("APP_FREE_USER_DATA_LIMIT") {
|
||||
if let Ok(num) = val.parse::<i64>() {
|
||||
settings.insert("free_user_data_limit".into(), toml::Value::Integer(num));
|
||||
}
|
||||
}
|
||||
|
||||
let app_config: AppConfig = toml::from_str(&settings.to_string())
|
||||
.map_err(|e| format!("配置反序列化失败: {}", e))?;
|
||||
|
||||
tracing::info!(
|
||||
"配置加载成功,环境={},app_version={}",
|
||||
app_config.environment,
|
||||
app_config.app_version
|
||||
);
|
||||
|
||||
Ok(app_config)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn database_url(&self) -> &str {
|
||||
&self.database_url
|
||||
}
|
||||
|
||||
pub fn rust_log(&self) -> &str {
|
||||
&self.rust_log
|
||||
}
|
||||
|
||||
pub fn is_production(&self) -> bool {
|
||||
self.environment == "production"
|
||||
}
|
||||
}
|
||||
|
||||
29
src/main.rs
29
src/main.rs
@@ -8,11 +8,13 @@ use sqlx::postgres::PgPool;
|
||||
use std::pin::Pin;
|
||||
|
||||
mod auth;
|
||||
mod config;
|
||||
mod db;
|
||||
mod handlers;
|
||||
mod models;
|
||||
|
||||
use auth::jwt_middleware;
|
||||
use config::AppConfig;
|
||||
use db::create_pool;
|
||||
use handlers::{
|
||||
admin_get_user, admin_update_user_payment, delete_weather, generate_temp_token_handler,
|
||||
@@ -79,8 +81,25 @@ fn create_server_config(
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
if let Err(e) = dotenvy::dotenv() {
|
||||
tracing::warn!("加载.env文件失败,使用系统环境变量: {}", e);
|
||||
// 加载配置文件(支持多环境)
|
||||
let app_config = match AppConfig::load() {
|
||||
Ok(cfg) => cfg,
|
||||
Err(e) => {
|
||||
eprintln!("配置加载失败: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// 设置环境变量(向后兼容依赖 env var 的组件)
|
||||
unsafe {
|
||||
std::env::set_var("DATABASE_URL", &app_config.database_url);
|
||||
std::env::set_var("JWT_SECRET", &app_config.jwt_secret);
|
||||
std::env::set_var("WECHAT_APPID", &app_config.wechat_appid);
|
||||
std::env::set_var("WECHAT_SECRET", &app_config.wechat_secret);
|
||||
std::env::set_var("SSL_KEY_PATH", &app_config.ssl_key_path);
|
||||
std::env::set_var("SSL_CERT_PATH", &app_config.ssl_cert_path);
|
||||
std::env::set_var("RUST_LOG", &app_config.rust_log);
|
||||
std::env::set_var("FREE_USER_DATA_LIMIT", app_config.free_user_data_limit.to_string());
|
||||
}
|
||||
|
||||
// 初始化文件日志(JSON 格式,带轮转)
|
||||
@@ -102,9 +121,9 @@ async fn main() -> std::io::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
tracing_subscriber::EnvFilter::from_default_env()
|
||||
.add_directive("rust_backend=info".parse().unwrap())
|
||||
.add_directive("actix_web=info".parse().unwrap())
|
||||
.add_directive("sqlx=warn".parse().unwrap()) // SQLx 日志太多,降级
|
||||
.add_directive(format!("rust_backend={}", app_config.rust_log).parse().unwrap())
|
||||
.add_directive(format!("actix_web={}", app_config.rust_log).parse().unwrap())
|
||||
.add_directive("sqlx=warn".parse().unwrap())
|
||||
)
|
||||
.with_target(true)
|
||||
.with_thread_ids(false) // 生产环境可开启
|
||||
|
||||
@@ -149,7 +149,11 @@ pub struct WeatherData {
|
||||
#[sqlx(rename = "averagewindspeed")]
|
||||
pub average_wind_speed: f64,
|
||||
|
||||
#[serde(rename = "calculatedWindSpeed", alias = "calculated_wind_speed", alias = "calculatedwindspeed")]
|
||||
#[serde(
|
||||
rename = "calculatedWindSpeed",
|
||||
alias = "calculated_wind_speed",
|
||||
alias = "calculatedwindspeed"
|
||||
)]
|
||||
#[sqlx(rename = "calculatedwindspeed")]
|
||||
pub calculated_wind_speed: Option<f64>, // 这个已经是 Option,很好
|
||||
|
||||
@@ -305,6 +309,7 @@ pub struct AppState {
|
||||
pub jwt_secret: String,
|
||||
pub wechat_appid: String,
|
||||
pub wechat_secret: String,
|
||||
pub free_user_data_limit: i32,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
@@ -316,6 +321,9 @@ impl AppState {
|
||||
.map_err(|_| "环境变量WECHAT_APPID未设置".to_string())?,
|
||||
wechat_secret: std::env::var("WECHAT_SECRET")
|
||||
.map_err(|_| "环境变量WECHAT_SECRET未设置".to_string())?,
|
||||
free_user_data_limit: std::env::var("FREE_USER_DATA_LIMIT")
|
||||
.map(|v| v.parse().unwrap_or(20))
|
||||
.unwrap_or(20),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user