From cee9da0da53ba9d04fbb989e2b35108266b2e787 Mon Sep 17 00:00:00 2001
From: Quentin Gliech <quenting@element.io>
Date: Tue, 26 Nov 2024 19:43:26 +0100
Subject: [PATCH] MSC4108: Add a Content-Type header on the PUT response
 (#17253)

This is a workaround for some proxy setup, where the ETag header gets
stripped from the response headers unless there is a Content-Type header
set.

In particular, we saw this bug when putting Cloudflare in front of
Synapse.
I'm pretty sure this is a Cloudflare bug, as this behaviour isn't
documented anywhere, and doesn't make sense whatsoever.

---------

Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
---
 changelog.d/17253.misc     | 1 +
 rust/src/rendezvous/mod.rs | 7 +++++++
 2 files changed, 8 insertions(+)
 create mode 100644 changelog.d/17253.misc

diff --git a/changelog.d/17253.misc b/changelog.d/17253.misc
new file mode 100644
index 0000000000..868691624d
--- /dev/null
+++ b/changelog.d/17253.misc
@@ -0,0 +1 @@
+[MSC4108](https://github.com/matrix-org/matrix-spec-proposals/pull/4108): Add a `Content-Type` header on the `PUT` response to work around a faulty behavior in some caching reverse proxies.
diff --git a/rust/src/rendezvous/mod.rs b/rust/src/rendezvous/mod.rs
index f69f45490f..55df0203f3 100644
--- a/rust/src/rendezvous/mod.rs
+++ b/rust/src/rendezvous/mod.rs
@@ -288,6 +288,13 @@ impl RendezvousHandler {
         let mut response = Response::new(Bytes::new());
         *response.status_mut() = StatusCode::ACCEPTED;
         prepare_headers(response.headers_mut(), session);
+
+        // Even though this isn't mandated by the MSC, we set a Content-Type on the response. It
+        // doesn't do any harm as the body is empty, but this helps escape a bug in some reverse
+        // proxy/cache setup which strips the ETag header if there is no Content-Type set.
+        // Specifically, we noticed this behaviour when placing Synapse behind Cloudflare.
+        response.headers_mut().typed_insert(ContentType::text());
+
         http_response_to_twisted(twisted_request, response)?;
 
         Ok(())
-- 
GitLab