mirror of https://github.com/fafhrd91/actix-web
add Allow header to resource's default 405 handler
This commit is contained in:
parent
29bd6a1dd5
commit
fd831deb95
|
@ -286,11 +286,26 @@ pub fn Method(method: HttpMethod) -> impl Guard {
|
||||||
MethodGuard(method)
|
MethodGuard(method)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct RegisteredMethods(pub(crate) Vec<HttpMethod>);
|
||||||
|
|
||||||
/// HTTP method guard.
|
/// HTTP method guard.
|
||||||
struct MethodGuard(HttpMethod);
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct MethodGuard(HttpMethod);
|
||||||
|
|
||||||
impl Guard for MethodGuard {
|
impl Guard for MethodGuard {
|
||||||
fn check(&self, ctx: &GuardContext<'_>) -> bool {
|
fn check(&self, ctx: &GuardContext<'_>) -> bool {
|
||||||
|
let registered = ctx.req_data_mut().remove::<RegisteredMethods>();
|
||||||
|
|
||||||
|
if let Some(mut methods) = registered {
|
||||||
|
eprintln!("here one");
|
||||||
|
methods.0.push(self.0.clone());
|
||||||
|
ctx.req_data_mut().insert(methods);
|
||||||
|
} else {
|
||||||
|
ctx.req_data_mut()
|
||||||
|
.insert(RegisteredMethods(vec![self.0.clone()]));
|
||||||
|
}
|
||||||
|
|
||||||
ctx.head().method == self.0
|
ctx.head().method == self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,9 @@ use crate::{
|
||||||
body::MessageBody,
|
body::MessageBody,
|
||||||
data::Data,
|
data::Data,
|
||||||
dev::{ensure_leading_slash, AppService, ResourceDef},
|
dev::{ensure_leading_slash, AppService, ResourceDef},
|
||||||
guard::Guard,
|
guard::{self, Guard},
|
||||||
handler::Handler,
|
handler::Handler,
|
||||||
|
http::header,
|
||||||
route::{Route, RouteService},
|
route::{Route, RouteService},
|
||||||
service::{
|
service::{
|
||||||
BoxedHttpService, BoxedHttpServiceFactory, HttpServiceFactory, ServiceRequest,
|
BoxedHttpService, BoxedHttpServiceFactory, HttpServiceFactory, ServiceRequest,
|
||||||
|
@ -66,7 +67,19 @@ impl Resource {
|
||||||
guards: Vec::new(),
|
guards: Vec::new(),
|
||||||
app_data: None,
|
app_data: None,
|
||||||
default: boxed::factory(fn_service(|req: ServiceRequest| async {
|
default: boxed::factory(fn_service(|req: ServiceRequest| async {
|
||||||
|
use crate::HttpMessage as _;
|
||||||
|
|
||||||
|
let allowed = req.extensions().get::<guard::RegisteredMethods>().cloned();
|
||||||
|
|
||||||
|
if let Some(methods) = allowed {
|
||||||
|
Ok(req.into_response(
|
||||||
|
HttpResponse::MethodNotAllowed()
|
||||||
|
.insert_header(header::Allow(methods.0))
|
||||||
|
.finish(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
Ok(req.into_response(HttpResponse::MethodNotAllowed()))
|
Ok(req.into_response(HttpResponse::MethodNotAllowed()))
|
||||||
|
}
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,7 +619,11 @@ mod tests {
|
||||||
async fn test_default_resource() {
|
async fn test_default_resource() {
|
||||||
let srv = init_service(
|
let srv = init_service(
|
||||||
App::new()
|
App::new()
|
||||||
.service(web::resource("/test").route(web::get().to(HttpResponse::Ok)))
|
.service(
|
||||||
|
web::resource("/test")
|
||||||
|
.route(web::get().to(HttpResponse::Ok))
|
||||||
|
.route(web::delete().to(HttpResponse::Ok)),
|
||||||
|
)
|
||||||
.default_service(|r: ServiceRequest| {
|
.default_service(|r: ServiceRequest| {
|
||||||
ok(r.into_response(HttpResponse::BadRequest()))
|
ok(r.into_response(HttpResponse::BadRequest()))
|
||||||
}),
|
}),
|
||||||
|
@ -621,6 +638,10 @@ mod tests {
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = call_service(&srv, req).await;
|
let resp = call_service(&srv, req).await;
|
||||||
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
|
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers().get(header::ALLOW).unwrap().as_bytes(),
|
||||||
|
b"GET, DELETE"
|
||||||
|
);
|
||||||
|
|
||||||
let srv = init_service(
|
let srv = init_service(
|
||||||
App::new().service(
|
App::new().service(
|
||||||
|
|
Loading…
Reference in New Issue