mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-03-25 16:45:05 +00:00
Move handling binary responses to a shared space
This commit is contained in:
parent
d376ef3ef1
commit
8cc89fd3b7
@ -0,0 +1,54 @@
|
||||
package docspell.restserver.http4s
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.backend.ops._
|
||||
|
||||
import bitpeace.FileMeta
|
||||
import org.http4s._
|
||||
import org.http4s.circe.CirceEntityEncoder._
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
import org.http4s.headers.ETag.EntityTag
|
||||
import org.http4s.headers._
|
||||
|
||||
object BinaryUtil {
|
||||
|
||||
def withResponseHeaders[F[_]: Sync](dsl: Http4sDsl[F], resp: F[Response[F]])(
|
||||
data: OItemSearch.BinaryData[F]
|
||||
): F[Response[F]] = {
|
||||
import dsl._
|
||||
|
||||
val mt = MediaType.unsafeParse(data.meta.mimetype.asString)
|
||||
val ctype = `Content-Type`(mt)
|
||||
val cntLen: Header = `Content-Length`.unsafeFromLong(data.meta.length)
|
||||
val eTag: Header = ETag(data.meta.checksum)
|
||||
val disp: Header =
|
||||
`Content-Disposition`("inline", Map("filename" -> data.name.getOrElse("")))
|
||||
|
||||
resp.map(r =>
|
||||
if (r.status == NotModified) r.withHeaders(ctype, eTag, disp)
|
||||
else r.withHeaders(ctype, cntLen, eTag, disp)
|
||||
)
|
||||
}
|
||||
|
||||
def makeByteResp[F[_]: Sync](
|
||||
dsl: Http4sDsl[F]
|
||||
)(data: OItemSearch.BinaryData[F]): F[Response[F]] = {
|
||||
import dsl._
|
||||
withResponseHeaders(dsl, Ok(data.data.take(data.meta.length)))(data)
|
||||
}
|
||||
|
||||
def matchETag[F[_]](
|
||||
fileData: Option[FileMeta],
|
||||
noneMatch: Option[NonEmptyList[EntityTag]]
|
||||
): Boolean =
|
||||
(fileData, noneMatch) match {
|
||||
case (Some(meta), Some(nm)) =>
|
||||
meta.checksum == nm.head.tag
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package docspell.restserver.routes
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
@ -10,14 +9,13 @@ import docspell.backend.ops._
|
||||
import docspell.common.Ident
|
||||
import docspell.restapi.model._
|
||||
import docspell.restserver.conv.Conversions
|
||||
import docspell.restserver.http4s.BinaryUtil
|
||||
import docspell.restserver.webapp.Webjars
|
||||
|
||||
import bitpeace.FileMeta
|
||||
import org.http4s._
|
||||
import org.http4s.circe.CirceEntityDecoder._
|
||||
import org.http4s.circe.CirceEntityEncoder._
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
import org.http4s.headers.ETag.EntityTag
|
||||
import org.http4s.headers._
|
||||
|
||||
object AttachmentRoutes {
|
||||
@ -26,24 +24,13 @@ object AttachmentRoutes {
|
||||
val dsl = new Http4sDsl[F] {}
|
||||
import dsl._
|
||||
|
||||
def withResponseHeaders(
|
||||
resp: F[Response[F]]
|
||||
)(data: OItemSearch.BinaryData[F]): F[Response[F]] = {
|
||||
val mt = MediaType.unsafeParse(data.meta.mimetype.asString)
|
||||
val ctype = `Content-Type`(mt)
|
||||
val cntLen: Header = `Content-Length`.unsafeFromLong(data.meta.length)
|
||||
val eTag: Header = ETag(data.meta.checksum)
|
||||
val disp: Header =
|
||||
`Content-Disposition`("inline", Map("filename" -> data.name.getOrElse("")))
|
||||
|
||||
resp.map(r =>
|
||||
if (r.status == NotModified) r.withHeaders(ctype, eTag, disp)
|
||||
else r.withHeaders(ctype, cntLen, eTag, disp)
|
||||
)
|
||||
}
|
||||
def withResponseHeaders(resp: F[Response[F]])(
|
||||
data: OItemSearch.BinaryData[F]
|
||||
): F[Response[F]] =
|
||||
BinaryUtil.withResponseHeaders[F](dsl, resp)(data)
|
||||
|
||||
def makeByteResp(data: OItemSearch.BinaryData[F]): F[Response[F]] =
|
||||
withResponseHeaders(Ok(data.data.take(data.meta.length)))(data)
|
||||
BinaryUtil.makeByteResp(dsl)(data)
|
||||
|
||||
HttpRoutes.of {
|
||||
case HEAD -> Root / Ident(id) =>
|
||||
@ -59,7 +46,7 @@ object AttachmentRoutes {
|
||||
for {
|
||||
fileData <- backend.itemSearch.findAttachment(id, user.account.collective)
|
||||
inm = req.headers.get(`If-None-Match`).flatMap(_.tags)
|
||||
matches = matchETag(fileData.map(_.meta), inm)
|
||||
matches = BinaryUtil.matchETag(fileData.map(_.meta), inm)
|
||||
resp <-
|
||||
fileData
|
||||
.map { data =>
|
||||
@ -82,7 +69,7 @@ object AttachmentRoutes {
|
||||
for {
|
||||
fileData <- backend.itemSearch.findAttachmentSource(id, user.account.collective)
|
||||
inm = req.headers.get(`If-None-Match`).flatMap(_.tags)
|
||||
matches = matchETag(fileData.map(_.meta), inm)
|
||||
matches = BinaryUtil.matchETag(fileData.map(_.meta), inm)
|
||||
resp <-
|
||||
fileData
|
||||
.map { data =>
|
||||
@ -107,7 +94,7 @@ object AttachmentRoutes {
|
||||
fileData <-
|
||||
backend.itemSearch.findAttachmentArchive(id, user.account.collective)
|
||||
inm = req.headers.get(`If-None-Match`).flatMap(_.tags)
|
||||
matches = matchETag(fileData.map(_.meta), inm)
|
||||
matches = BinaryUtil.matchETag(fileData.map(_.meta), inm)
|
||||
resp <-
|
||||
fileData
|
||||
.map { data =>
|
||||
@ -122,7 +109,7 @@ object AttachmentRoutes {
|
||||
fileData <-
|
||||
backend.itemSearch.findAttachmentPreview(id, user.account.collective)
|
||||
inm = req.headers.get(`If-None-Match`).flatMap(_.tags)
|
||||
matches = matchETag(fileData.map(_.meta), inm)
|
||||
matches = BinaryUtil.matchETag(fileData.map(_.meta), inm)
|
||||
resp <-
|
||||
fileData
|
||||
.map { data =>
|
||||
@ -173,16 +160,4 @@ object AttachmentRoutes {
|
||||
} yield resp
|
||||
}
|
||||
}
|
||||
|
||||
private def matchETag[F[_]](
|
||||
fileData: Option[FileMeta],
|
||||
noneMatch: Option[NonEmptyList[EntityTag]]
|
||||
): Boolean =
|
||||
(fileData, noneMatch) match {
|
||||
case (Some(meta), Some(nm)) =>
|
||||
meta.checksum == nm.head.tag
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user