~jan0sch/smederee

Showing details for patch 0f9348a883c6a6ad93fc03547a3e1dec8f271bab.
2023-08-16 (Wed), 8:52 AM - Jens Grassel - 0f9348a883c6a6ad93fc03547a3e1dec8f271bab

VCS: Explicitly add content disposition headers upon archive download.

- add content disposition header containing the filename upon repository
  archive download

Fixes: https://tickets.smeder.ee/~jan0sch/smederee/tickets/3
Summary of changes
1 files modified with 14 lines added and 5 lines removed
  • modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala with 14 added and 5 removed lines
diff -rN -u old-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala new-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala
--- old-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala	2025-01-15 12:50:52.752662126 +0000
+++ new-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala	2025-01-15 12:50:52.756662132 +0000
@@ -39,10 +39,11 @@
 import org.http4s._
 import org.http4s.dsl.Http4sDsl
 import org.http4s.dsl.impl._
-import org.http4s.headers.Location
+import org.http4s.headers._
 import org.http4s.implicits._
 import org.http4s.twirl.TwirlInstances._
 import org.slf4j.LoggerFactory
+import org.typelevel.ci.CIStringSyntax
 
 /** Routes for handling VCS repositories, including creation, management and public serving.
   *
@@ -887,8 +888,12 @@
         csrf <- Sync[F].delay(ar.req.getCsrfToken)
         file <- doDownloadDistribution(user.some)(repositoryOwnerName, repositoryName)
         resp <- file match {
-          case None           => NotFound()
-          case Some(filePath) => StaticFile.fromPath(filePath, ar.req.some).getOrElseF(NotFound())
+          case None => NotFound()
+          case Some(filePath) =>
+            StaticFile
+              .fromPath(filePath, ar.req.some)
+              .map(_.putHeaders(`Content-Disposition`("attachment", Map(ci"filename" -> s"${repositoryName}.tar.gz"))))
+              .getOrElseF(NotFound())
         }
       } yield resp
   }
@@ -901,8 +906,12 @@
         csrf <- Sync[F].delay(req.getCsrfToken)
         file <- doDownloadDistribution(None)(repositoryOwnerName, repositoryName)
         resp <- file match {
-          case None           => NotFound()
-          case Some(filePath) => StaticFile.fromPath(filePath, req.some).getOrElseF(NotFound())
+          case None => NotFound()
+          case Some(filePath) =>
+            StaticFile
+              .fromPath(filePath, req.some)
+              .map(_.putHeaders(`Content-Disposition`("attachment", Map(ci"filename" -> s"${repositoryName}.tar.gz"))))
+              .getOrElseF(NotFound())
         }
       } yield resp
   }