From 1cc3e7b24cb05a48f495a5f0e1775d51adfe148d Mon Sep 17 00:00:00 2001
From: Rob Ede <robjtede@icloud.com>
Date: Wed, 19 Jan 2022 20:26:33 +0000
Subject: [PATCH] deprecate `Path::path` (#2590)

---
 actix-files/src/path_buf.rs  |  2 +-
 actix-files/src/service.rs   | 16 +++++++++-------
 actix-router/CHANGES.md      |  4 ++++
 actix-router/src/path.rs     | 34 ++++++++++++++++++++++------------
 actix-router/src/resource.rs |  6 +++---
 actix-router/src/url.rs      |  4 ++--
 src/service.rs               | 16 ++++++++--------
 7 files changed, 49 insertions(+), 33 deletions(-)

diff --git a/actix-files/src/path_buf.rs b/actix-files/src/path_buf.rs
index 03b2cd76..f7f7cdab 100644
--- a/actix-files/src/path_buf.rs
+++ b/actix-files/src/path_buf.rs
@@ -85,7 +85,7 @@ impl FromRequest for PathBufWrap {
     type Future = Ready<Result<Self, Self::Error>>;
 
     fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
-        ready(req.match_info().path().parse())
+        ready(req.match_info().unprocessed().parse())
     }
 }
 
diff --git a/actix-files/src/service.rs b/actix-files/src/service.rs
index 4e8b7231..5d494f87 100644
--- a/actix-files/src/service.rs
+++ b/actix-files/src/service.rs
@@ -120,14 +120,16 @@ impl Service<ServiceRequest> for FilesService {
                 ));
             }
 
-            let real_path =
-                match PathBufWrap::parse_path(req.match_info().path(), this.hidden_files) {
-                    Ok(item) => item,
-                    Err(err) => return Ok(req.error_response(err)),
-                };
+            let path_on_disk = match PathBufWrap::parse_path(
+                req.match_info().unprocessed(),
+                this.hidden_files,
+            ) {
+                Ok(item) => item,
+                Err(err) => return Ok(req.error_response(err)),
+            };
 
             if let Some(filter) = &this.path_filter {
-                if !filter(real_path.as_ref(), req.head()) {
+                if !filter(path_on_disk.as_ref(), req.head()) {
                     if let Some(ref default) = this.default {
                         return default.call(req).await;
                     } else {
@@ -137,7 +139,7 @@ impl Service<ServiceRequest> for FilesService {
             }
 
             // full file path
-            let path = this.directory.join(&real_path);
+            let path = this.directory.join(&path_on_disk);
             if let Err(err) = path.canonicalize() {
                 return this.handle_err(err, req).await;
             }
diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md
index f268ffa9..17d149b6 100644
--- a/actix-router/CHANGES.md
+++ b/actix-router/CHANGES.md
@@ -1,6 +1,10 @@
 # Changes
 
 ## Unreleased - 2021-xx-xx
+- Add `Path::as_str`. [#2590]
+- Deprecate `Path::path`. [#2590]
+
+[#2590]: https://github.com/actix/actix-web/pull/2590
 
 
 ## 0.5.0-rc.1 - 2022-01-14
diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs
index f8667ad8..dfb645d7 100644
--- a/actix-router/src/path.rs
+++ b/actix-router/src/path.rs
@@ -37,19 +37,39 @@ impl<T: ResourcePath> Path<T> {
         }
     }
 
-    /// Get reference to inner path instance.
+    /// Returns reference to inner path instance.
     #[inline]
     pub fn get_ref(&self) -> &T {
         &self.path
     }
 
-    /// Get mutable reference to inner path instance.
+    /// Returns mutable reference to inner path instance.
     #[inline]
     pub fn get_mut(&mut self) -> &mut T {
         &mut self.path
     }
 
+    /// Returns full path as a string.
+    #[inline]
+    pub fn as_str(&self) -> &str {
+        profile_method!(as_str);
+        self.path.path()
+    }
+
     /// Returns unprocessed part of the path.
+    ///
+    /// Returns empty string if no more is to be processed.
+    #[inline]
+    pub fn unprocessed(&self) -> &str {
+        profile_method!(unprocessed);
+        // clamp skip to path length
+        let skip = (self.skip as usize).min(self.as_str().len());
+        &self.path.path()[skip..]
+    }
+
+    /// Returns unprocessed part of the path.
+    #[doc(hidden)]
+    #[deprecated(since = "0.6.0", note = "Use `.as_str()` or `.unprocessed()`.")]
     #[inline]
     pub fn path(&self) -> &str {
         profile_method!(path);
@@ -63,16 +83,6 @@ impl<T: ResourcePath> Path<T> {
         }
     }
 
-    /// Returns unprocessed part of the path.
-    ///
-    /// # Panics
-    /// Unlike [`path`](Self::path), this will panic if `skip` indexes further than the path length.
-    #[inline]
-    pub fn unprocessed(&self) -> &str {
-        profile_method!(unprocessed);
-        &self.path.path()[(self.skip as usize)..]
-    }
-
     /// Set new path.
     #[inline]
     pub fn set(&mut self, path: T) {
diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs
index d39a6b92..c0b5522a 100644
--- a/actix-router/src/resource.rs
+++ b/actix-router/src/resource.rs
@@ -692,7 +692,7 @@ impl ResourceDef {
 
         let mut segments = <[PathItem; MAX_DYNAMIC_SEGMENTS]>::default();
         let path = resource.resource_path();
-        let path_str = path.path();
+        let path_str = path.unprocessed();
 
         let (matched_len, matched_vars) = match &self.pat_type {
             PatternType::Static(pattern) => {
@@ -710,7 +710,7 @@ impl ResourceDef {
                 let captures = {
                     profile_section!(pattern_dynamic_regex_exec);
 
-                    match re.captures(path.path()) {
+                    match re.captures(path.unprocessed()) {
                         Some(captures) => captures,
                         _ => return false,
                     }
@@ -738,7 +738,7 @@ impl ResourceDef {
             PatternType::DynamicSet(re, params) => {
                 profile_section!(pattern_dynamic_set);
 
-                let path = path.path();
+                let path = path.unprocessed();
                 let (pattern, names) = match re.matches(path).into_iter().next() {
                     Some(idx) => &params[idx],
                     _ => return false,
diff --git a/actix-router/src/url.rs b/actix-router/src/url.rs
index c5a3508a..f8d94ae4 100644
--- a/actix-router/src/url.rs
+++ b/actix-router/src/url.rs
@@ -121,7 +121,7 @@ mod tests {
     }
 
     #[test]
-    fn valid_utf8_multibyte() {
+    fn valid_utf8_multi_byte() {
         let test = ('\u{FF00}'..='\u{FFFF}').collect::<String>();
         let encoded = percent_encode(test.as_bytes());
         let path = match_url("/a/{id}/b", format!("/a/{}/b", &encoded));
@@ -135,6 +135,6 @@ mod tests {
         let path = Path::new(Url::new(uri));
 
         // We should always get a valid utf8 string
-        assert!(String::from_utf8(path.path().as_bytes().to_owned()).is_ok());
+        assert!(String::from_utf8(path.as_str().as_bytes().to_owned()).is_ok());
     }
 }
diff --git a/src/service.rs b/src/service.rs
index 03ea0b97..162c90ec 100644
--- a/src/service.rs
+++ b/src/service.rs
@@ -198,9 +198,9 @@ impl ServiceRequest {
         self.req.connection_info()
     }
 
-    /// Get a reference to the Path parameters.
+    /// Returns a reference to the Path parameters.
     ///
-    /// Params is a container for url parameters.
+    /// Params is a container for URL parameters.
     /// A variable segment is specified in the form `{identifier}`,
     /// where the identifier can be used later in a request handler to
     /// access the matched value for that segment.
@@ -209,6 +209,12 @@ impl ServiceRequest {
         self.req.match_info()
     }
 
+    /// Returns a mutable reference to the Path parameters.
+    #[inline]
+    pub fn match_info_mut(&mut self) -> &mut Path<Url> {
+        self.req.match_info_mut()
+    }
+
     /// Counterpart to [`HttpRequest::match_name`].
     #[inline]
     pub fn match_name(&self) -> Option<&str> {
@@ -221,12 +227,6 @@ impl ServiceRequest {
         self.req.match_pattern()
     }
 
-    /// Get a mutable reference to the Path parameters.
-    #[inline]
-    pub fn match_info_mut(&mut self) -> &mut Path<Url> {
-        self.req.match_info_mut()
-    }
-
     /// Get a reference to a `ResourceMap` of current application.
     #[inline]
     pub fn resource_map(&self) -> &ResourceMap {