From e71ab0526d5b0dce69abeae88d46a0d298a76e4a Mon Sep 17 00:00:00 2001 From: N08I40K Date: Wed, 16 Apr 2025 16:21:53 +0400 Subject: [PATCH] =?UTF-8?q?Middleware=20=D0=B4=D0=BB=D1=8F=20=D1=8F=D0=B2?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=83=D0=BA=D0=B0=D0=B7=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B8=D1=80=D0=BE=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=20=D0=B7=D0=B0=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B5=20Content-Type.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 5 +-- src/middlewares/content_type.rs | 64 +++++++++++++++++++++++++++++++++ src/middlewares/mod.rs | 3 +- 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/middlewares/content_type.rs diff --git a/src/main.rs b/src/main.rs index 3e2db58..417943f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use crate::app_state::{AppState, app_state}; use crate::middlewares::authorization::JWTAuthorization; +use crate::middlewares::content_type::ContentTypeBootstrap; use actix_web::dev::{ServiceFactory, ServiceRequest}; use actix_web::{App, Error, HttpServer}; use dotenvy::dotenv; @@ -81,7 +82,7 @@ async fn main() { let (app, api) = App::new() .into_utoipa_app() .app_data(app_state.clone()) - .service(get_api_scope("/api/v1")) + .service(get_api_scope("/api/v1").wrap(ContentTypeBootstrap)) .split_for_parts(); let rapidoc_service = RapiDoc::with_openapi("/api-docs-json", api).path("/api-docs"); @@ -95,7 +96,7 @@ async fn main() { app.service(rapidoc_service.custom_html(patched_rapidoc_html)) }) .workers(4) - .bind(("0.0.0.0", 8080)) + .bind(("0.0.0.0", 5050)) .unwrap() .run() .await diff --git a/src/middlewares/content_type.rs b/src/middlewares/content_type.rs new file mode 100644 index 0000000..50ee2b4 --- /dev/null +++ b/src/middlewares/content_type.rs @@ -0,0 +1,64 @@ +use actix_web::Error; +use actix_web::body::{BoxBody, EitherBody}; +use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform, forward_ready}; +use actix_web::http::header; +use actix_web::http::header::HeaderValue; +use futures_util::future::LocalBoxFuture; +use std::future::{Ready, ready}; + +/// Middleware to specify the encoding in the Content-Type header. +pub struct ContentTypeBootstrap; + +impl Transform for ContentTypeBootstrap +where + S: Service, Error = Error>, + S::Future: 'static, + B: 'static, +{ + type Response = ServiceResponse>; + type Error = Error; + type Transform = ContentTypeMiddleware; + type InitError = (); + type Future = Ready>; + + fn new_transform(&self, service: S) -> Self::Future { + ready(Ok(ContentTypeMiddleware { service })) + } +} + +pub struct ContentTypeMiddleware { + service: S, +} + +impl<'a, S, B> Service for ContentTypeMiddleware +where + S: Service, Error = Error>, + S::Future: 'static, + B: 'static, +{ + type Response = ServiceResponse>; + type Error = Error; + type Future = LocalBoxFuture<'static, Result>; + + forward_ready!(service); + + fn call(&self, req: ServiceRequest) -> Self::Future { + let fut = self.service.call(req); + + Box::pin(async move { + let mut response = fut.await?; + + let headers = response.response_mut().headers_mut(); + if let Some(content_type) = headers.get("Content-Type") { + if content_type == "application/json" { + headers.insert( + header::CONTENT_TYPE, + HeaderValue::from_static("application/json; charset=utf8"), + ); + } + } + + Ok(response.map_into_left_body()) + }) + } +} diff --git a/src/middlewares/mod.rs b/src/middlewares/mod.rs index 3e8f8bd..5e87410 100644 --- a/src/middlewares/mod.rs +++ b/src/middlewares/mod.rs @@ -1 +1,2 @@ -pub mod authorization; \ No newline at end of file +pub mod authorization; +pub mod content_type; \ No newline at end of file