2024-08-31 03:32:37 +03:00
|
|
|
|
mod app_state;
|
|
|
|
|
|
mod auth;
|
|
|
|
|
|
mod handlers;
|
2025-08-02 00:18:09 +03:00
|
|
|
|
mod lookup;
|
2024-08-31 03:32:37 +03:00
|
|
|
|
mod s3_utils;
|
2025-09-02 11:40:43 +03:00
|
|
|
|
mod security;
|
2024-08-31 03:32:37 +03:00
|
|
|
|
mod thumbnail;
|
2024-04-08 10:17:14 +03:00
|
|
|
|
|
2025-06-02 22:20:37 +03:00
|
|
|
|
use actix_cors::Cors;
|
2025-08-02 00:18:09 +03:00
|
|
|
|
use actix_web::{
|
2025-09-01 22:58:03 +03:00
|
|
|
|
App, HttpServer,
|
2025-09-02 11:40:43 +03:00
|
|
|
|
http::header,
|
2025-09-02 14:00:54 +03:00
|
|
|
|
middleware::{DefaultHeaders, Logger},
|
2025-09-01 22:58:03 +03:00
|
|
|
|
web,
|
2025-08-02 00:18:09 +03:00
|
|
|
|
};
|
2024-08-31 03:32:37 +03:00
|
|
|
|
use app_state::AppState;
|
2025-09-02 14:00:54 +03:00
|
|
|
|
use security::SecurityConfig;
|
2025-08-12 14:13:35 +03:00
|
|
|
|
|
2025-09-02 11:27:48 +03:00
|
|
|
|
use handlers::universal_handler;
|
2025-09-02 14:00:54 +03:00
|
|
|
|
use log::{info, warn};
|
2024-10-02 18:56:52 +03:00
|
|
|
|
use std::env;
|
2025-08-02 00:18:09 +03:00
|
|
|
|
use tokio::task::spawn_blocking;
|
2023-09-28 02:08:48 +03:00
|
|
|
|
|
|
|
|
|
|
#[actix_web::main]
|
|
|
|
|
|
async fn main() -> std::io::Result<()> {
|
2024-10-02 18:56:52 +03:00
|
|
|
|
env_logger::init();
|
2024-10-23 16:21:18 +03:00
|
|
|
|
warn!("Started");
|
2024-08-30 22:11:21 +03:00
|
|
|
|
|
2024-10-22 13:18:57 +03:00
|
|
|
|
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
|
|
|
|
|
|
let addr = format!("0.0.0.0:{}", port);
|
|
|
|
|
|
let app_state = AppState::new().await;
|
2024-08-30 23:27:01 +03:00
|
|
|
|
let app_state_clone = app_state.clone();
|
2024-09-23 18:16:47 +03:00
|
|
|
|
|
2024-09-23 16:32:54 +03:00
|
|
|
|
// Используем spawn_blocking для работы, которая не совместима с Send
|
|
|
|
|
|
spawn_blocking(move || {
|
|
|
|
|
|
let rt = tokio::runtime::Handle::current();
|
|
|
|
|
|
rt.block_on(async move {
|
2024-10-22 19:34:08 +03:00
|
|
|
|
app_state_clone.cache_filelist().await;
|
2024-09-23 16:32:54 +03:00
|
|
|
|
});
|
2024-08-30 23:27:01 +03:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-02 11:40:43 +03:00
|
|
|
|
// Конфигурация безопасности
|
|
|
|
|
|
let security_config = SecurityConfig::default();
|
2025-09-02 14:00:54 +03:00
|
|
|
|
info!(
|
|
|
|
|
|
"Security config: max_payload={} MB, timeout={}s",
|
|
|
|
|
|
security_config.max_payload_size / (1024 * 1024),
|
|
|
|
|
|
security_config.request_timeout_seconds
|
|
|
|
|
|
);
|
2025-09-02 11:40:43 +03:00
|
|
|
|
|
2023-09-28 02:08:48 +03:00
|
|
|
|
HttpServer::new(move || {
|
2025-09-02 11:40:43 +03:00
|
|
|
|
// Настройка CORS middleware - ограничиваем в продакшене
|
2025-06-02 22:20:37 +03:00
|
|
|
|
let cors = Cors::default()
|
2025-09-02 11:40:43 +03:00
|
|
|
|
.allowed_origin("https://discours.io")
|
|
|
|
|
|
.allowed_origin("https://new.discours.io")
|
|
|
|
|
|
.allowed_origin("https://testing.discours.io")
|
|
|
|
|
|
.allowed_origin("https://testing3.discours.io")
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
.allowed_origin("https://vercel.app") // для Vercel edge functions
|
|
|
|
|
|
.allowed_origin("https://*.vercel.app") // для Vercel preview deployments
|
2025-09-02 11:40:43 +03:00
|
|
|
|
.allowed_origin("http://localhost:3000") // для разработки
|
|
|
|
|
|
.allowed_methods(vec!["GET", "POST", "OPTIONS"])
|
2025-06-02 22:20:37 +03:00
|
|
|
|
.allowed_headers(vec![
|
|
|
|
|
|
header::CONTENT_TYPE,
|
|
|
|
|
|
header::AUTHORIZATION,
|
2025-09-02 11:40:43 +03:00
|
|
|
|
header::IF_NONE_MATCH,
|
|
|
|
|
|
header::CACHE_CONTROL,
|
2025-06-02 22:20:37 +03:00
|
|
|
|
])
|
2025-09-02 11:40:43 +03:00
|
|
|
|
.expose_headers(vec![header::CONTENT_LENGTH, header::ETAG])
|
2025-06-02 22:20:37 +03:00
|
|
|
|
.supports_credentials()
|
2025-09-02 11:40:43 +03:00
|
|
|
|
.max_age(86400); // 1 день вместо 20
|
|
|
|
|
|
|
|
|
|
|
|
// Заголовки безопасности
|
|
|
|
|
|
let security_headers = DefaultHeaders::new()
|
|
|
|
|
|
.add(("X-Content-Type-Options", "nosniff"))
|
|
|
|
|
|
.add(("X-Frame-Options", "DENY"))
|
|
|
|
|
|
.add(("X-XSS-Protection", "1; mode=block"))
|
|
|
|
|
|
.add(("Referrer-Policy", "strict-origin-when-cross-origin"))
|
2025-09-02 14:00:54 +03:00
|
|
|
|
.add((
|
|
|
|
|
|
"Content-Security-Policy",
|
|
|
|
|
|
"default-src 'self'; img-src 'self' data: https:; object-src 'none';",
|
|
|
|
|
|
))
|
|
|
|
|
|
.add((
|
|
|
|
|
|
"Strict-Transport-Security",
|
|
|
|
|
|
"max-age=31536000; includeSubDomains",
|
|
|
|
|
|
));
|
2025-06-02 22:20:37 +03:00
|
|
|
|
|
2023-09-28 02:08:48 +03:00
|
|
|
|
App::new()
|
2024-08-30 22:11:21 +03:00
|
|
|
|
.app_data(web::Data::new(app_state.clone()))
|
2025-09-02 11:40:43 +03:00
|
|
|
|
.app_data(web::PayloadConfig::new(security_config.max_payload_size))
|
|
|
|
|
|
.app_data(web::JsonConfig::default().limit(1024 * 1024)) // 1MB для JSON
|
|
|
|
|
|
.wrap(security_headers)
|
2025-06-02 22:20:37 +03:00
|
|
|
|
.wrap(cors)
|
2023-10-11 23:03:12 +03:00
|
|
|
|
.wrap(Logger::default())
|
2025-09-02 11:27:48 +03:00
|
|
|
|
.default_service(web::to(universal_handler))
|
2023-09-28 02:08:48 +03:00
|
|
|
|
})
|
2024-10-02 18:56:52 +03:00
|
|
|
|
.bind(addr)?
|
2023-09-28 02:08:48 +03:00
|
|
|
|
.run()
|
|
|
|
|
|
.await
|
2024-09-23 18:16:47 +03:00
|
|
|
|
}
|