From 06c79458012457b2ef6e106b7fbe283a63683e73 Mon Sep 17 00:00:00 2001
From: Rob Ede <robjtede@icloud.com>
Date: Thu, 30 Jun 2022 09:19:16 +0100
Subject: [PATCH] retain previously set vary headers when using compress
 (#2798)

* retain previously set vary headers when using compress
---
 actix-http/CHANGES.md                |  8 +++++---
 actix-http/src/encoding/encoder.rs   |  2 +-
 actix-web/src/middleware/compress.rs | 25 +++++++++++++++++++++++++
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md
index dd6051b8..c9ab687f 100644
--- a/actix-http/CHANGES.md
+++ b/actix-http/CHANGES.md
@@ -1,13 +1,15 @@
 # Changes
 
 ## Unreleased - 2022-xx-xx
-### Fixed
-- Websocket parser no longer throws endless overflow errors after receiving an oversized frame. [#2790]
-
 ### Changed
 - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency.
 
+### Fixed
+- Websocket parser no longer throws endless overflow errors after receiving an oversized frame. [#2790]
+- Retain previously set Vary headers when using compression encoder. [#2798]
+
 [#2790]: https://github.com/actix/actix-web/pull/2790
+[#2798]: https://github.com/actix/actix-web/pull/2798
 
 
 ## 3.1.0 - 2022-06-11
diff --git a/actix-http/src/encoding/encoder.rs b/actix-http/src/encoding/encoder.rs
index 0bbb1c10..bbe53e8e 100644
--- a/actix-http/src/encoding/encoder.rs
+++ b/actix-http/src/encoding/encoder.rs
@@ -257,7 +257,7 @@ fn update_head(encoding: ContentEncoding, head: &mut ResponseHead) {
     head.headers_mut()
         .insert(header::CONTENT_ENCODING, encoding.to_header_value());
     head.headers_mut()
-        .insert(header::VARY, HeaderValue::from_static("accept-encoding"));
+        .append(header::VARY, HeaderValue::from_static("accept-encoding"));
 
     head.no_chunking(false);
 }
diff --git a/actix-web/src/middleware/compress.rs b/actix-web/src/middleware/compress.rs
index 4fdd7477..ed4291be 100644
--- a/actix-web/src/middleware/compress.rs
+++ b/actix-web/src/middleware/compress.rs
@@ -251,6 +251,8 @@ static SUPPORTED_ENCODINGS: Lazy<Vec<Encoding>> = Lazy::new(|| {
 #[cfg(feature = "compress-gzip")]
 #[cfg(test)]
 mod tests {
+    use std::collections::HashSet;
+
     use super::*;
     use crate::{middleware::DefaultHeaders, test, web, App};
 
@@ -305,4 +307,27 @@ mod tests {
         let bytes = test::read_body(res).await;
         assert_eq!(gzip_decode(bytes), DATA.as_bytes());
     }
+
+    #[actix_rt::test]
+    async fn retains_previously_set_vary_header() {
+        let app = test::init_service({
+            App::new()
+                .wrap(Compress::default())
+                .default_service(web::to(move || {
+                    HttpResponse::Ok()
+                        .insert_header((header::VARY, "x-test"))
+                        .finish()
+                }))
+        })
+        .await;
+
+        let req = test::TestRequest::default()
+            .insert_header((header::ACCEPT_ENCODING, "gzip"))
+            .to_request();
+        let res = test::call_service(&app, req).await;
+        assert_eq!(res.status(), StatusCode::OK);
+        let vary_headers = res.headers().get_all(header::VARY).collect::<HashSet<_>>();
+        assert!(vary_headers.contains(&HeaderValue::from_static("x-test")));
+        assert!(vary_headers.contains(&HeaderValue::from_static("accept-encoding")));
+    }
 }