From c92aa31f9195372053865ecc0b1fcd058744405f Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 22 Jan 2022 16:17:46 +0000 Subject: [PATCH] document full percent-decoding of web::Path --- src/request.rs | 13 +++++++------ src/types/path.rs | 8 ++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/request.rs b/src/request.rs index b3db5ffbd..f04e551d4 100644 --- a/src/request.rs +++ b/src/request.rs @@ -129,10 +129,11 @@ impl HttpRequest { /// later in a request handler to access the matched value for that parameter. /// /// # Percent Encoding and URL Parameters - /// Because each URL parameter is able to capture multiple path segments, both `["%2F", "%25"]` - /// found in the request URI are not decoded into `["/", "%"]` in order to preserve path - /// segment boundaries. If a url parameter is expected to contain these characters, then it is - /// on the user to decode them. + /// Because each URL parameter is able to capture multiple path segments, none of + /// `["%2F", "%25", "%2B"]` found in the request URI are decoded into `["/", "%", "+"]` in order + /// to preserve path integrity. If a URL parameter is expected to contain these characters, then + /// it is on the user to decode them or use the [`web::Path`](crate::web::Path) extractor which + /// _will_ decode these special sequences. #[inline] pub fn match_info(&self) -> &Path { &self.inner.path @@ -504,12 +505,11 @@ impl HttpRequestPool { #[cfg(test)] mod tests { - use actix_service::Service; use bytes::Bytes; use super::*; use crate::{ - dev::{ResourceDef, ResourceMap}, + dev::{ResourceDef, ResourceMap, Service}, http::{header, StatusCode}, test::{self, call_service, init_service, read_body, TestRequest}, web, App, HttpResponse, @@ -902,6 +902,7 @@ mod tests { // `body` equals http://localhost:8080/bar/nested // because nested from /bar overrides /foo's // to do this any other way would require something like a custom tree search + // see https://github.com/actix/actix-web/issues/1763 assert_eq!(body, "http://localhost:8080/bar/nested"); let bar_resp = diff --git a/src/types/path.rs b/src/types/path.rs index 58a1a5bde..869269d09 100644 --- a/src/types/path.rs +++ b/src/types/path.rs @@ -18,6 +18,9 @@ use crate::{ /// /// Use [`PathConfig`] to configure extraction option. /// +/// Unlike, [`HttpRequest::match_info`], this extractor will fully percent-decode dynamic segments, +/// including `/`, `%`, and `+`. +/// /// # Examples /// ``` /// use actix_web::{get, web}; @@ -259,13 +262,14 @@ mod tests { #[actix_rt::test] async fn paths_decoded() { let resource = ResourceDef::new("/{key}/{value}"); - let mut req = TestRequest::with_uri("/na%2Bme/us%2Fer%251").to_srv_request(); + let mut req = TestRequest::with_uri("/na%2Bme/us%2Fer%254%32").to_srv_request(); resource.capture_match_info(req.match_info_mut()); let (req, mut pl) = req.into_parts(); let path_items = Path::::from_request(&req, &mut pl).await.unwrap(); assert_eq!(path_items.key, "na+me"); - assert_eq!(path_items.value, "us/er%1"); + assert_eq!(path_items.value, "us/er%42"); + assert_eq!(req.match_info().as_str(), "/na%2Bme/us%2Fer%2542"); } #[actix_rt::test]