Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There are only successful examples and no failed examples. I need to return JSON immediately and not continue. What should I do #809

Open
WyntersN opened this issue May 9, 2024 · 0 comments

Comments

@WyntersN
Copy link

WyntersN commented May 9, 2024

use std::{
    future::{ready, Ready},
    rc::Rc,
};

use actix_web::{
    dev::{self, Service, ServiceRequest, ServiceResponse, Transform},
    web, Error, HttpResponse,
};
use futures_util::future::LocalBoxFuture;

pub struct Auth;

impl<S: 'static, B> Transform<S, ServiceRequest> for Auth
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = AuthMiddleware<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(AuthMiddleware {
            service: Rc::new(service),
        }))
    }
}

pub struct AuthMiddleware<S> {
    // This is special: We need this to avoid lifetime issues.
    service: Rc<S>,
}

impl<S, B> Service<ServiceRequest> for AuthMiddleware<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;

    dev::forward_ready!(service);

    fn call(&self, mut req: ServiceRequest) -> Self::Future {
        let svc = self.service.clone();
        let fut = async move {
            let token = req
            .headers()
            .get("Authorization")
            .and_then(|header| header.to_str().ok())
            .map(|token| token.trim_start_matches("Bearer "));

            match token {
                Some(_) => {
                    let res = svc.call(req).await?;
                    println!("response: {:?}", res.headers());
                    Ok(res)
                },
                None => {
                    
                    let json = serde_json::json!({"code": 401, "message": "Unauthorized"});
                    let response = HttpResponse::Unauthorized()
                        .content_type("application/json")
                        .body(json.to_string());
                    Ok(ServiceResponse::new(req, response))
                }
            }
        };
        Box::pin(fut)
    }
}

You can use this middleware example as a guide for writing your custom logger that can print the body it reads.

There are only successful examples and no failed examples. I need to return JSON immediately and not continue. What should I do

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant