🧹 Remove unused legacy modules and functions
- Deleted quota.rs module (quota management not needed via HTTP) - Removed legacy get_id_by_token GraphQL function - Removed unused set_user_quota and increase_user_quota methods - Cleaned up unused imports and legacy structs - Simplified handlers/mod.rs to only expose universal_handler Architecture now focused on core functionality: - GET / (user info) - GET /<filename> (file serving) - POST / (file upload)
This commit is contained in:
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,3 +1,22 @@
|
||||
## [0.5.3] - 2025-09-02
|
||||
|
||||
### 🔄 Архитектурные изменения
|
||||
- **УПРОЩЕНО**: Убран сложный роутинг Actix-web в пользу универсального обработчика
|
||||
- **ДОБАВЛЕНО**: Прямое определение HTTP методов (GET/POST) в единой точке
|
||||
- **УБРАНО**: HTTP API для управления квотами (quota endpoints)
|
||||
- **СОХРАНЕНО**: ACME challenge поддержка для SSL сертификатов
|
||||
|
||||
### 📋 API Структура
|
||||
- `GET /` - авторизованная информация о персональном хранилище
|
||||
- `GET /<filename>` - статические файлы с миниатюрами
|
||||
- `POST /` - авторизованная загрузка файлов
|
||||
|
||||
### 🔧 Технические детали
|
||||
- Единый `universal_handler` для всех запросов
|
||||
- Определение метода через `req.method()`
|
||||
- Маршрутизация по пути через `req.path()`
|
||||
- CORS и middleware сохранены
|
||||
|
||||
## [0.5.2] - 2025-09-02
|
||||
|
||||
### Fixed
|
||||
|
||||
48
Cargo.lock
generated
48
Cargo.lock
generated
@@ -117,7 +117,7 @@ dependencies = [
|
||||
"actix-multipart-derive",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"derive_more 0.99.18",
|
||||
"derive_more 0.99.20",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"httparse",
|
||||
@@ -855,9 +855,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "8.0.1"
|
||||
version = "8.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d"
|
||||
checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
@@ -1106,18 +1106,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.13"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
|
||||
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
@@ -1137,9 +1137,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
@@ -1147,9 +1147,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
@@ -1161,9 +1161,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
@@ -1201,9 +1201,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.18"
|
||||
version = "0.99.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
|
||||
checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
@@ -2644,7 +2644,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quoter"
|
||||
version = "0.5.1"
|
||||
version = "0.5.3"
|
||||
dependencies = [
|
||||
"actix",
|
||||
"actix-cors",
|
||||
@@ -3787,9 +3787,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.18.0"
|
||||
version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
|
||||
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
@@ -4277,27 +4277,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.2"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
|
||||
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.2.1"
|
||||
version = "7.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
|
||||
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.13+zstd.1.5.6"
|
||||
version = "2.0.15+zstd.1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
|
||||
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "quoter"
|
||||
version = "0.5.1"
|
||||
version = "0.5.3"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
@@ -8,7 +8,6 @@ futures = "0.3.30"
|
||||
serde_json = "1.0.143"
|
||||
actix-web = "4.11.0"
|
||||
actix-cors = "0.7.0"
|
||||
actix-files = "0.6.7"
|
||||
reqwest = { version = "0.12.23", features = ["json"] }
|
||||
sentry = { version = "0.42", features = ["tokio"] }
|
||||
uuid = { version = "1.18.0", features = ["v4"] }
|
||||
|
||||
@@ -179,42 +179,4 @@ impl AppState {
|
||||
|
||||
Ok(new_quota)
|
||||
}
|
||||
|
||||
/// Устанавливает квоту пользователя в байтах (позволяет увеличить или уменьшить)
|
||||
pub async fn set_user_quota(&self, user_id: &str, bytes: u64) -> Result<u64, actix_web::Error> {
|
||||
let mut redis = self.redis.clone();
|
||||
let quota_key = format!("quota:{}", user_id);
|
||||
|
||||
// Устанавливаем новое значение квоты
|
||||
redis
|
||||
.set::<_, u64, ()>("a_key, bytes)
|
||||
.await
|
||||
.map_err(|_| ErrorInternalServerError("Failed to set user quota in Redis"))?;
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
/// Увеличивает квоту пользователя на указанное количество байт
|
||||
pub async fn increase_user_quota(
|
||||
&self,
|
||||
user_id: &str,
|
||||
additional_bytes: u64,
|
||||
) -> Result<u64, actix_web::Error> {
|
||||
let mut redis = self.redis.clone();
|
||||
let quota_key = format!("quota:{}", user_id);
|
||||
|
||||
// Получаем текущую квоту
|
||||
let current_quota: u64 = redis.get("a_key).await.unwrap_or(0);
|
||||
|
||||
// Вычисляем новую квоту
|
||||
let new_quota = current_quota + additional_bytes;
|
||||
|
||||
// Устанавливаем новое значение
|
||||
redis
|
||||
.set::<_, u64, ()>("a_key, new_quota)
|
||||
.await
|
||||
.map_err(|_| ErrorInternalServerError("Failed to increase user quota in Redis"))?;
|
||||
|
||||
Ok(new_quota)
|
||||
}
|
||||
}
|
||||
|
||||
78
src/auth.rs
78
src/auth.rs
@@ -2,33 +2,8 @@ use actix_web::error::ErrorInternalServerError;
|
||||
use jsonwebtoken::{Algorithm, DecodingKey, Validation, decode};
|
||||
use log::{info, warn};
|
||||
use redis::{AsyncCommands, aio::MultiplexedConnection};
|
||||
use reqwest::Client as HTTPClient;
|
||||
use reqwest::header::{CONTENT_TYPE, HeaderMap, HeaderValue};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use std::{collections::HashMap, env, error::Error};
|
||||
|
||||
// Старые структуры для совместимости с get_id_by_token
|
||||
#[derive(Deserialize)]
|
||||
struct AuthResponse {
|
||||
data: Option<AuthData>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AuthData {
|
||||
validate_jwt_token: Option<ValidateJWTToken>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ValidateJWTToken {
|
||||
is_valid: bool,
|
||||
claims: Option<Claims>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Claims {
|
||||
sub: Option<String>,
|
||||
}
|
||||
use std::error::Error;
|
||||
|
||||
// Структуры для JWT токенов
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -51,57 +26,6 @@ pub struct Author {
|
||||
pub device_info: Option<String>,
|
||||
}
|
||||
|
||||
/// Получает айди пользователя из токена в заголовке
|
||||
#[allow(clippy::collapsible_if)]
|
||||
pub async fn get_id_by_token(token: &str) -> Result<String, Box<dyn Error>> {
|
||||
let auth_api_base = env::var("CORE_URL")?;
|
||||
let query_name = "validate_jwt_token";
|
||||
let operation = "ValidateToken";
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
|
||||
|
||||
let mut variables = HashMap::<String, HashMap<String, String>>::new();
|
||||
let mut params = HashMap::<String, String>::new();
|
||||
params.insert("token".to_string(), token.to_string());
|
||||
params.insert("token_type".to_string(), "access_token".to_string());
|
||||
variables.insert("params".to_string(), params);
|
||||
|
||||
let gql = json!({
|
||||
"query": format!("query {}($params: ValidateJWTTokenInput!) {{ {}(params: $params) {{ is_valid claims }} }}", operation, query_name),
|
||||
"operationName": operation,
|
||||
"variables": variables
|
||||
});
|
||||
|
||||
let client = HTTPClient::new();
|
||||
let response = client
|
||||
.post(&auth_api_base)
|
||||
.headers(headers)
|
||||
.json(&gql)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if response.status().is_success() {
|
||||
let auth_response: AuthResponse = response.json().await?;
|
||||
if let Some(auth_data) = auth_response.data {
|
||||
if let Some(validate_jwt_token) = auth_data.validate_jwt_token {
|
||||
if validate_jwt_token.is_valid {
|
||||
if let Some(claims) = validate_jwt_token.claims {
|
||||
if let Some(sub) = claims.sub {
|
||||
return Ok(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(Box::new(std::io::Error::other("Invalid token response")))
|
||||
} else {
|
||||
Err(Box::new(std::io::Error::other(format!(
|
||||
"Request failed with status: {}",
|
||||
response.status()
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
/// Декодирует JWT токен и извлекает claims с проверкой истечения
|
||||
fn decode_jwt_token(token: &str) -> Result<TokenClaims, Box<dyn Error>> {
|
||||
// В реальном приложении здесь должен быть настоящий секретный ключ
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
mod proxy;
|
||||
mod quota;
|
||||
mod serve_file;
|
||||
mod upload;
|
||||
mod user;
|
||||
mod universal;
|
||||
|
||||
pub use proxy::proxy_handler;
|
||||
pub use quota::{get_quota_handler, increase_quota_handler, set_quota_handler};
|
||||
pub use upload::upload_handler;
|
||||
pub use user::get_current_user_handler;
|
||||
pub use universal::universal_handler;
|
||||
|
||||
// Общий лимит квоты на пользователя: 5 ГБ
|
||||
pub const MAX_USER_QUOTA_BYTES: u64 = 5 * 1024 * 1024 * 1024;
|
||||
// Общий лимит квоты на пользователя: 12 ГБ
|
||||
pub const MAX_USER_QUOTA_BYTES: u64 = 12 * 1024 * 1024 * 1024;
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
use actix_web::{HttpRequest, HttpResponse, Result, web};
|
||||
use log::warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::app_state::AppState;
|
||||
use crate::auth::get_id_by_token;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QuotaRequest {
|
||||
pub user_id: String,
|
||||
pub additional_bytes: Option<u64>,
|
||||
pub new_quota_bytes: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct QuotaResponse {
|
||||
pub user_id: String,
|
||||
pub current_quota: u64,
|
||||
pub max_quota: u64,
|
||||
}
|
||||
|
||||
/// Обработчик для получения информации о квоте пользователя
|
||||
pub async fn get_quota_handler(
|
||||
req: HttpRequest,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
// Проверяем авторизацию
|
||||
let token = req
|
||||
.headers()
|
||||
.get("Authorization")
|
||||
.and_then(|header_value| header_value.to_str().ok());
|
||||
|
||||
if token.is_none() {
|
||||
return Err(actix_web::error::ErrorUnauthorized("Unauthorized"));
|
||||
}
|
||||
|
||||
let _admin_id = get_id_by_token(token.unwrap()).await.map_err(|e| {
|
||||
let error_msg = if e.to_string().contains("expired") {
|
||||
"Admin token has expired"
|
||||
} else {
|
||||
"Invalid admin token"
|
||||
};
|
||||
actix_web::error::ErrorUnauthorized(error_msg)
|
||||
})?;
|
||||
|
||||
// Получаем user_id из query параметров
|
||||
let user_id = req
|
||||
.query_string()
|
||||
.split("user_id=")
|
||||
.nth(1)
|
||||
.and_then(|s| s.split('&').next())
|
||||
.ok_or_else(|| actix_web::error::ErrorBadRequest("Missing user_id parameter"))?;
|
||||
|
||||
// Получаем текущую квоту пользователя
|
||||
let current_quota = state.get_or_create_quota(user_id).await?;
|
||||
|
||||
let response = QuotaResponse {
|
||||
user_id: user_id.to_string(),
|
||||
current_quota,
|
||||
max_quota: crate::handlers::MAX_USER_QUOTA_BYTES,
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
}
|
||||
|
||||
/// Обработчик для увеличения квоты пользователя
|
||||
pub async fn increase_quota_handler(
|
||||
req: HttpRequest,
|
||||
quota_data: web::Json<QuotaRequest>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
// Проверяем авторизацию
|
||||
let token = req
|
||||
.headers()
|
||||
.get("Authorization")
|
||||
.and_then(|header_value| header_value.to_str().ok());
|
||||
|
||||
if token.is_none() {
|
||||
return Err(actix_web::error::ErrorUnauthorized("Unauthorized"));
|
||||
}
|
||||
|
||||
let _admin_id = get_id_by_token(token.unwrap()).await.map_err(|e| {
|
||||
let error_msg = if e.to_string().contains("expired") {
|
||||
"Admin token has expired"
|
||||
} else {
|
||||
"Invalid admin token"
|
||||
};
|
||||
actix_web::error::ErrorUnauthorized(error_msg)
|
||||
})?;
|
||||
|
||||
let additional_bytes = quota_data
|
||||
.additional_bytes
|
||||
.ok_or_else(|| actix_web::error::ErrorBadRequest("Missing additional_bytes parameter"))?;
|
||||
|
||||
if additional_bytes == 0 {
|
||||
return Err(actix_web::error::ErrorBadRequest(
|
||||
"additional_bytes must be greater than 0",
|
||||
));
|
||||
}
|
||||
|
||||
// Увеличиваем квоту пользователя
|
||||
let new_quota = state
|
||||
.increase_user_quota("a_data.user_id, additional_bytes)
|
||||
.await?;
|
||||
|
||||
warn!(
|
||||
"Increased quota for user {} by {} bytes, new total: {} bytes",
|
||||
quota_data.user_id, additional_bytes, new_quota
|
||||
);
|
||||
|
||||
let response = QuotaResponse {
|
||||
user_id: quota_data.user_id.clone(),
|
||||
current_quota: new_quota,
|
||||
max_quota: crate::handlers::MAX_USER_QUOTA_BYTES,
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
}
|
||||
|
||||
/// Обработчик для установки квоты пользователя
|
||||
pub async fn set_quota_handler(
|
||||
req: HttpRequest,
|
||||
quota_data: web::Json<QuotaRequest>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
// Проверяем авторизацию
|
||||
let token = req
|
||||
.headers()
|
||||
.get("Authorization")
|
||||
.and_then(|header_value| header_value.to_str().ok());
|
||||
|
||||
if token.is_none() {
|
||||
return Err(actix_web::error::ErrorUnauthorized("Unauthorized"));
|
||||
}
|
||||
|
||||
let _admin_id = get_id_by_token(token.unwrap()).await.map_err(|e| {
|
||||
let error_msg = if e.to_string().contains("expired") {
|
||||
"Admin token has expired"
|
||||
} else {
|
||||
"Invalid admin token"
|
||||
};
|
||||
actix_web::error::ErrorUnauthorized(error_msg)
|
||||
})?;
|
||||
|
||||
let new_quota_bytes = quota_data
|
||||
.new_quota_bytes
|
||||
.ok_or_else(|| actix_web::error::ErrorBadRequest("Missing new_quota_bytes parameter"))?;
|
||||
|
||||
// Устанавливаем новую квоту пользователя
|
||||
let new_quota = state
|
||||
.set_user_quota("a_data.user_id, new_quota_bytes)
|
||||
.await?;
|
||||
|
||||
warn!(
|
||||
"Set quota for user {} to {} bytes",
|
||||
quota_data.user_id, new_quota
|
||||
);
|
||||
|
||||
let response = QuotaResponse {
|
||||
user_id: quota_data.user_id.clone(),
|
||||
current_quota: new_quota,
|
||||
max_quota: crate::handlers::MAX_USER_QUOTA_BYTES,
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
}
|
||||
68
src/handlers/universal.rs
Normal file
68
src/handlers/universal.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use actix_web::{HttpRequest, HttpResponse, Result, web};
|
||||
use actix_multipart::Multipart;
|
||||
use log::{info, warn};
|
||||
|
||||
use crate::app_state::AppState;
|
||||
|
||||
/// Универсальный обработчик, который определяет HTTP метод и путь
|
||||
pub async fn universal_handler(
|
||||
req: HttpRequest,
|
||||
payload: web::Payload,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let method = req.method().clone();
|
||||
let path = req.path().to_string();
|
||||
|
||||
info!("Universal handler: {} {}", method, path);
|
||||
|
||||
// Возвращаем 404 для .well-known путей (для Let's Encrypt ACME)
|
||||
if path.starts_with("/.well-known/") {
|
||||
warn!("ACME challenge path requested: {}", path);
|
||||
return Ok(HttpResponse::NotFound().finish());
|
||||
}
|
||||
|
||||
match method.as_str() {
|
||||
"GET" => handle_get(req, state, &path).await,
|
||||
"POST" => handle_post(req, payload, state, &path).await,
|
||||
_ => {
|
||||
warn!("Unsupported HTTP method: {}", method);
|
||||
Ok(HttpResponse::MethodNotAllowed().json(serde_json::json!({
|
||||
"error": "Method not allowed"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_get(
|
||||
req: HttpRequest,
|
||||
state: web::Data<AppState>,
|
||||
path: &str,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
if path == "/" {
|
||||
// GET / - получение информации о пользователе
|
||||
crate::handlers::user::get_current_user_handler(req, state).await
|
||||
} else {
|
||||
// GET /{path} - получение файла через proxy
|
||||
let path_without_slash = path.trim_start_matches('/');
|
||||
let requested_res = web::Path::from(path_without_slash.to_string());
|
||||
crate::handlers::proxy::proxy_handler(req, requested_res, state).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_post(
|
||||
req: HttpRequest,
|
||||
payload: web::Payload,
|
||||
state: web::Data<AppState>,
|
||||
path: &str,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
if path == "/" {
|
||||
// POST / - загрузка файла (multipart)
|
||||
let multipart = Multipart::new(&req.headers(), payload);
|
||||
crate::handlers::upload::upload_handler(req, multipart, state).await
|
||||
} else {
|
||||
warn!("Unsupported POST path: {}", path);
|
||||
Ok(HttpResponse::NotFound().json(serde_json::json!({
|
||||
"error": "Endpoint not found"
|
||||
})))
|
||||
}
|
||||
}
|
||||
19
src/main.rs
19
src/main.rs
@@ -14,10 +14,7 @@ use actix_web::{
|
||||
};
|
||||
use app_state::AppState;
|
||||
|
||||
use handlers::{
|
||||
get_current_user_handler, get_quota_handler, increase_quota_handler, proxy_handler,
|
||||
set_quota_handler, upload_handler,
|
||||
};
|
||||
use handlers::universal_handler;
|
||||
use log::warn;
|
||||
use std::env;
|
||||
use tokio::task::spawn_blocking;
|
||||
@@ -63,19 +60,7 @@ async fn main() -> std::io::Result<()> {
|
||||
.app_data(web::Data::new(app_state.clone()))
|
||||
.wrap(cors)
|
||||
.wrap(Logger::default())
|
||||
.route("/", web::get().to(get_current_user_handler))
|
||||
.route("/", web::post().to(upload_handler))
|
||||
.route("/quota", web::get().to(get_quota_handler))
|
||||
.route("/quota/increase", web::post().to(increase_quota_handler))
|
||||
.route("/quota/set", web::post().to(set_quota_handler))
|
||||
.service(
|
||||
web::scope("/.well-known")
|
||||
.service(
|
||||
actix_files::Files::new("/", "/tmp/.well-known")
|
||||
.show_files_listing()
|
||||
)
|
||||
)
|
||||
.route("/{path:.*}", web::get().to(proxy_handler))
|
||||
.default_service(web::to(universal_handler))
|
||||
})
|
||||
.bind(addr)?
|
||||
.run()
|
||||
|
||||
Reference in New Issue
Block a user