面试题答案
一键面试错误处理与返回合适HTTP状态码和错误信息
- 定义错误类型:
use actix_web::http::StatusCode; use thiserror::Error; #[derive(Error, Debug)] pub enum AppError { #[error("Database query failed")] DatabaseError, #[error("Parameter parsing error")] ParameterError, } impl actix_web::ResponseError for AppError { fn status_code(&self) -> StatusCode { match self { AppError::DatabaseError => StatusCode::INTERNAL_SERVER_ERROR, AppError::ParameterError => StatusCode::BAD_REQUEST, } } fn error_response(&self) -> actix_web::HttpResponse { actix_web::HttpResponse::build(self.status_code()) .content_type("application/json") .body(format!("{{\"error\":\"{}\"}}", self)) } }
- 在处理函数中返回错误:
use actix_web::{web, HttpResponse}; async fn index() -> Result<HttpResponse, AppError> { // 模拟数据库查询失败 if rand::random::<bool>() { Err(AppError::DatabaseError) } else { Ok(HttpResponse::Ok().body("Success")) } }
实现记录请求访问时间的中间件
- 中间件逻辑:
use actix_web::{dev::Service, dev::ServiceRequest, dev::ServiceResponse, Error, HttpResponse}; use std::time::{SystemTime, UNIX_EPOCH}; struct AccessTimeLogger; impl<S, B> Service<ServiceRequest> for AccessTimeLogger where S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S::Future: 'static, B: 'static, { type Response = ServiceResponse<B>; type Error = Error; type Future = Box<dyn std::future::Future<Output = Result<Self::Response, Self::Error>>>; fn poll_ready( &mut self, _cx: &mut std::task::Context<'_>, ) -> std::task::Poll<Result<(), Self::Error>> { std::task::Poll::Ready(Ok(())) } fn call(&mut self, req: ServiceRequest) -> Self::Future { let start = SystemTime::now(); let svc = req.get_ref(); Box::new(async move { let res = svc.call(req).await?; let elapsed = start.elapsed().unwrap().as_millis(); println!("Request took {} ms", elapsed); Ok(res) }) } }
- 应用中间件:
use actix_web::App; fn main() { let app = App::new() .wrap(AccessTimeLogger) .service(index); // 启动服务器相关代码 }
实现思路总结
- 错误处理:
- 使用
thiserror
库定义自定义错误类型AppError
,针对不同的错误情况(如数据库查询失败、参数解析错误)进行枚举。 - 为
AppError
实现actix_web::ResponseError
trait,在其中定义合适的HTTP状态码和错误响应格式。 - 在处理函数中,根据业务逻辑返回
Result<HttpResponse, AppError>
,当遇到错误时返回Err(AppError::具体错误类型)
。
- 使用
- 中间件:
- 定义一个结构体
AccessTimeLogger
,实现Service
trait。 - 在
call
方法中记录请求开始时间,调用下一个服务获取响应,计算请求处理时间并打印日志。 - 通过
App::wrap
方法将中间件应用到actix - web
应用中。
- 定义一个结构体