From ac2470351270371453fa568eb75ce43b61abe7aa Mon Sep 17 00:00:00 2001
From: Max Frai <maxfrai@Max-Frai.local>
Date: Wed, 23 May 2018 09:12:23 +0300
Subject: [PATCH] Add ability to set encoding for exact NamedFile.

---
 src/fs.rs | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/src/fs.rs b/src/fs.rs
index 779b419a..02e0e577 100644
--- a/src/fs.rs
+++ b/src/fs.rs
@@ -38,6 +38,7 @@ pub struct NamedFile {
     md: Metadata,
     modified: Option<SystemTime>,
     cpu_pool: Option<CpuPool>,
+    encoding: Option<ContentEncoding>,
     only_get: bool,
     status_code: StatusCode,
 }
@@ -58,12 +59,14 @@ impl NamedFile {
         let path = path.as_ref().to_path_buf();
         let modified = md.modified().ok();
         let cpu_pool = None;
+        let encoding = None;
         Ok(NamedFile {
             path,
             file,
             md,
             modified,
             cpu_pool,
+            encoding,
             only_get: false,
             status_code: StatusCode::OK,
         })
@@ -114,6 +117,19 @@ impl NamedFile {
         self
     }
 
+    // Set content encoding for serving this file
+    #[inline]
+    pub fn set_content_encoding(mut self, enc: ContentEncoding) -> Self {
+        self.encoding = Some(enc);
+        self
+    }
+
+    // Get content encoding used for serving this file
+    #[inline]
+    pub fn content_encoding(&self) -> Option<ContentEncoding> {
+        self.encoding
+    }
+
     fn etag(&self) -> Option<header::EntityTag> {
         // This etag format is similar to Apache's.
         self.modified.as_ref().map(|mtime| {
@@ -219,6 +235,9 @@ impl Responder for NamedFile {
                     ),
                 );
             });
+            if let Some(current_encoding) = self.encoding {
+                resp.content_encoding(current_encoding);
+            }
             let reader = ChunkedReadFile {
                 size: self.md.len(),
                 offset: 0,
@@ -264,6 +283,9 @@ impl Responder for NamedFile {
         };
 
         let mut resp = HttpResponse::build(self.status_code);
+        if let Some(current_encoding) = self.encoding {
+            resp.content_encoding(current_encoding);
+        }
 
         resp.if_some(self.path().extension(), |ext, resp| {
             resp.set(header::ContentType(get_mime_type(&ext.to_string_lossy())));
@@ -941,6 +963,20 @@ mod tests {
         assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
     }
 
+    #[test]
+    fn test_named_file_content_encoding() {
+        let req = TestRequest::default().method(Method::GET).finish();
+        let file = NamedFile::open("Cargo.toml").unwrap();
+
+        assert!(file.content_encoding().is_none());
+        let resp = file.set_content_encoding(ContentEncoding::Identity)
+            .respond_to(&req)
+            .unwrap();
+
+        assert!(resp.content_encoding().is_some());
+        assert_eq!(resp.content_encoding().unwrap().as_str(), "identity");
+    }
+
     #[test]
     fn test_named_file_any_method() {
         let req = TestRequest::default().method(Method::POST).finish();