【问题标题】:Why does an actix-web service send text/plain instead of JSON for an auth error?为什么 actix-web 服务发送文本/纯文本而不是 JSON 以获取身份验证错误?
【发布时间】:2019-09-12 00:41:39
【问题描述】:

我用 actix 做了一个网络服务,我正在尝试像Auth Web Microservice with Rust using Actix-Web 1.0 - Complete Tutorial 那样实现身份验证流程:

use std::sync::Arc;
use std::sync::Mutex;

use actix_cors::Cors;
use actix_identity::{CookieIdentityPolicy, Identity, IdentityService};

use actix::prelude::*;
use actix::{Actor, SyncContext};
use actix_web::{
    dev::Payload, error, guard, http::header, middleware, web, App, Error as AWError, FromRequest,
    HttpRequest, HttpResponse, HttpServer, Responder, ResponseError,
};
use derive_more::Display;

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TokenResult {
    pub company: String,
    pub config: String,
}

#[derive(Debug, Display)]
pub enum ServiceError {
    #[display(fmt = "Internal Server Error")]
    InternalServerError(String),

    #[display(fmt = "BadRequest: {}", _0)]
    BadRequest(String),

    #[display(fmt = "Unauthorized")]
    Unauthorized,
}

impl ResponseError for ServiceError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            ServiceError::InternalServerError(ref message) => {
                HttpResponse::InternalServerError().json(message)
            }
            ServiceError::BadRequest(ref message) => HttpResponse::BadRequest().json(message),
            ServiceError::Unauthorized => HttpResponse::Unauthorized().json("Unauthorized"), //This is executed
        }
    }
}

impl FromRequest for TokenResult {
    type Error = AWError;
    type Future = Result<TokenResult, Self::Error>;
    type Config = ();

    fn from_request(req: &HttpRequest, pl: &mut Payload) -> Self::Future {
        if let Some(identity) = Identity::from_request(req, pl)?.identity() {
            let user: TokenResult = serde_json::from_str(&identity)?;
            return Ok(user);
        }
        //This is executed
        Err(ServiceError::Unauthorized.into())
    }
}

fn client_config(token: TokenResult) -> HttpResponse {
    HttpResponse::Ok().json(token.config)
}

fn main() -> Result<(), AWError> {
    let sys = actix_rt::System::new("Api");

    let mut server = HttpServer::new(move || {
        App::new()
            .wrap(IdentityService::new(
                CookieIdentityPolicy::new(&[0; 32])
                    .name("auth-cookie")
                    .secure(false),
            ))
            .service(web::resource("/config").to(client_config))
    });

    server = server.bind("127.0.0.1:8080").unwrap();

    server.start();
    println!("Started http client: 127.0.0.1:8080");
    sys.run()?;
    Ok(())
}

当我使用 httpie 和其他人进行测试时,我得到的是文本而不是 JSON:

http -v  POST http://localhost:8080/config
POST /config HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 0
Host: localhost:8080
User-Agent: HTTPie/1.0.2


HTTP/1.1 401 Unauthorized
content-length: 12
content-type: text/plain
date: Tue, 10 Sep 2019 20:41:46 GMT

Unauthorized

TokenResult 之外的所有其他方法和错误均返回 JSON。

我的依赖:

[dependencies]
actix = "0.8.3"
actix-files = "0.1.4"
actix-rt = "0.2.5"
actix-identity = "0.1.0"
actix-cors = "0.1.0"
actix-web = {version = "1.0.7", features=["flate2-rust"], default-features = false}
derive_more = "0.15.0"
futures = "0.1.29"
json = "0.12.0"
serde = { version = "1.0.100", features = ["derive"] }
serde_json = "1.0.40"
snafu = "0.5.0"

【问题讨论】:

    标签: json rust actix-web


    【解决方案1】:

    需要覆盖render_response:

    impl ResponseError for ServiceError {
        fn error_response(&self) -> HttpResponse {
            match *self {
                ServiceError::InternalServerError(ref message) => {
                    HttpResponse::InternalServerError().json(message)
                }
                ServiceError::BadRequest(ref message) => HttpResponse::BadRequest().json(message),
                ServiceError::Unauthorized => HttpResponse::Unauthorized().json("Unauthorized"),
            }
        }
    
        fn render_response(&self) -> HttpResponse {
            self.error_response()
        }
    }
    

    感谢ddboline on Reddit 指出解决方案。

    【讨论】:

      猜你喜欢
      • 2021-12-17
      • 2015-07-22
      • 1970-01-01
      • 2020-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-16
      • 1970-01-01
      相关资源
      最近更新 更多