Skip to content

Commit f381eac

Browse files
imsduSimon Dumas
andauthored
Do not use akka content type for files anymore (#5337)
Co-authored-by: Simon Dumas <simon.dumas@senscience.ai>
1 parent 7fd0e31 commit f381eac

File tree

62 files changed

+315
-316
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+315
-316
lines changed

delta/kernel/src/main/scala/ch/epfl/bluebrain/nexus/delta/kernel/instances/ContentTypeInstances.scala

Lines changed: 0 additions & 39 deletions
This file was deleted.

delta/kernel/src/main/scala/ch/epfl/bluebrain/nexus/delta/kernel/instances/instances.scala

Lines changed: 0 additions & 3 deletions
This file was deleted.

delta/kernel/src/test/scala/ch/epfl/bluebrain/nexus/delta/kernel/instances/ContentTypeInstancesSuite.scala

Lines changed: 0 additions & 32 deletions
This file was deleted.

delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchiveDownloadSpec.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import ch.epfl.bluebrain.nexus.delta.plugins.storage.FileSelf.ParsingError
1515
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.generators.FileGen
1616
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.FileAttributes.FileAttributesOrigin.Client
1717
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.FileRejection.FileNotFound
18-
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{Digest, FileAttributes}
18+
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{Digest, FileAttributes, MediaType}
1919
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.schemas
2020
import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.StorageFixtures
2121
import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.AbsolutePath
@@ -83,7 +83,7 @@ class ArchiveDownloadSpec
8383
Uri.unsafeFromString("http://localhost/file.txt"),
8484
Uri.Path.unsafeFromString("file.txt"),
8585
filename,
86-
Some(`text/plain(UTF-8)`),
86+
Some(MediaType.`text/plain`),
8787
Map.empty,
8888
None,
8989
None,

delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchiveRoutesSpec.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.generators.FileGen
1818
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.Digest.ComputedDigest
1919
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.FileAttributes.FileAttributesOrigin.Client
2020
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.FileRejection.FileNotFound
21-
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{File, FileAttributes}
21+
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{File, FileAttributes, MediaType}
2222
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.routes.FilesRoutesSpec
2323
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.schemas
2424
import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.StorageFixtures
@@ -97,7 +97,7 @@ class ArchiveRoutesSpec extends BaseRouteSpec with StorageFixtures with ArchiveH
9797
Uri.unsafeFromString("http://localhost/file.txt"),
9898
Uri.Path.unsafeFromString("file.txt"),
9999
"myfile",
100-
Some(`text/plain(UTF-8)`),
100+
Some(MediaType.`text/plain`),
101101
Map.empty,
102102
None,
103103
None,

delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/Files.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package ch.epfl.bluebrain.nexus.delta.plugins.storage.files
22

3-
import akka.http.scaladsl.model.ContentTypes.`application/octet-stream`
43
import cats.effect.{Clock, IO}
54
import cats.syntax.all.*
65
import ch.epfl.bluebrain.nexus.delta.kernel.kamon.KamonMetricComponent
@@ -344,10 +343,10 @@ final class Files(
344343
attributes = file.value.attributes
345344
storage <- fetchStorage.onRead(file.value.storage, id.project)
346345
s = fetchFile(storage, attributes, file.id)
347-
mediaType = attributes.mediaType.getOrElse(`application/octet-stream`)
346+
mediaType = attributes.mediaType.getOrElse(MediaType.`application/octet-stream`)
348347
} yield FileResponse[FileRejection](
349348
attributes.filename,
350-
mediaType,
349+
MediaType.toAkkaContentType(mediaType),
351350
Some(ResourceF.etagValue(file)),
352351
Some(attributes.bytes),
353352
s
@@ -382,7 +381,7 @@ final class Files(
382381
for {
383382
info <- formDataExtractor(uploadRequest.entity, storage.storageValue.maxFileSize)
384383
storageMetadata <- fileOperations.save(storage, info, uploadRequest.contentLength)
385-
} yield FileAttributes.from(info.filename, info.contentType, uploadRequest.metadata, storageMetadata)
384+
} yield FileAttributes.from(info.filename, info.mediaType, uploadRequest.metadata, storageMetadata)
386385
}.adaptError { case e: SaveFileRejection => SaveRejection(iri, storage.id, e) }
387386

388387
private def generateId(pc: ProjectContext): IO[Iri] =

delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/FilesConfig.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package ch.epfl.bluebrain.nexus.delta.plugins.storage.files
22

3-
import ch.epfl.bluebrain.nexus.delta.kernel.http.MediaTypeDetectorConfig
43
import ch.epfl.bluebrain.nexus.delta.sourcing.config.EventLogConfig
54
import pureconfig.ConfigReader
65
import pureconfig.generic.semiauto.deriveReader

delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/FormDataExtractor.scala

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.storage.files
22

33
import akka.NotUsed
44
import akka.actor.ActorSystem
5-
import akka.http.scaladsl.model.*
5+
import akka.http.scaladsl.model.{ContentType, ContentTypes, EntityStreamSizeException, ExceptionWithErrorInfo, HttpEntity, Multipart}
66
import akka.http.scaladsl.model.MediaTypes.`multipart/form-data`
77
import akka.http.scaladsl.model.Multipart.FormData
88
import akka.http.scaladsl.server.*
@@ -15,6 +15,7 @@ import cats.effect.IO
1515
import cats.syntax.all.*
1616
import ch.epfl.bluebrain.nexus.delta.kernel.error.NotARejection
1717
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.FileRejection.{FileTooLarge, InvalidMultipartFieldName, WrappedAkkaRejection}
18+
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.MediaType
1819
import ch.epfl.bluebrain.nexus.delta.sdk.stream.StreamConverter
1920

2021
import scala.concurrent.{ExecutionContext, Future}
@@ -37,7 +38,7 @@ trait FormDataExtractor {
3738

3839
final case class UploadedFileInformation(
3940
filename: String,
40-
contentType: Option[ContentType],
41+
mediaType: Option[MediaType],
4142
contents: FileData
4243
)
4344

@@ -54,7 +55,7 @@ object FormDataExtractor {
5455
MultipartUnmarshallers
5556
.multipartUnmarshaller[Multipart.FormData, Multipart.FormData.BodyPart, Multipart.FormData.BodyPart.Strict](
5657
mediaRange = `multipart/form-data`,
57-
defaultContentType = defaultContentType,
58+
defaultContentType = ContentTypes.`application/octet-stream`,
5859
createBodyPart = (entity, headers) => Multipart.General.BodyPart(entity, headers).toFormDataBodyPart.get,
5960
createStreamed = (_, parts) => Multipart.FormData(parts),
6061
createStrictBodyPart =
@@ -118,10 +119,16 @@ object FormDataExtractor {
118119
val contentTypeFromRequest = part.entity.contentType
119120
val suppliedContentType = Option.when(contentTypeFromRequest != defaultContentType)(contentTypeFromRequest)
120121

122+
val detectedMediaType = mediaTypeDetector(
123+
filename,
124+
suppliedContentType.flatMap(toHttp4sMediaType),
125+
Some(contentTypeFromRequest).flatMap(toHttp4sMediaType)
126+
)
127+
121128
Future(
122129
UploadedFileInformation(
123130
filename,
124-
mediaTypeDetector(filename, suppliedContentType, Some(contentTypeFromRequest)),
131+
detectedMediaType,
125132
convertStream(part.entity.dataBytes)
126133
).some
127134
)
@@ -133,5 +140,8 @@ object FormDataExtractor {
133140
StreamConverter(source.asInstanceOf[Graph[SourceShape[ByteString], NotUsed]]).map { byteString =>
134141
byteString.asByteBuffer
135142
}
143+
144+
private def toHttp4sMediaType(contentType: ContentType) =
145+
MediaType.parse(contentType.value).toOption
136146
}
137147
}
Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
11
package ch.epfl.bluebrain.nexus.delta.plugins.storage.files
22

3-
import akka.http.scaladsl.model.{ContentType, HttpCharsets, MediaType, MediaTypes}
4-
import ch.epfl.bluebrain.nexus.delta.kernel.http.MediaTypeDetectorConfig
53
import ch.epfl.bluebrain.nexus.delta.kernel.utils.FileUtils
6-
7-
import scala.util.Try
4+
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.MediaType
85

96
/**
10-
* Allows to detect a content type from incoming files from their extensions when the client has not provided one
7+
* Allows to detect a media type from incoming files from their extensions when the client has not provided one
118
*
129
* @param config
13-
* the config with a mapping from the extension to the content type
10+
* the config with a mapping from the extension to the media type
1411
*/
1512
final class MediaTypeDetector(config: MediaTypeDetectorConfig) {
1613

17-
def apply(filename: String, provided: Option[ContentType], fallback: Option[ContentType]): Option[ContentType] = {
14+
def apply(filename: String, provided: Option[MediaType], fallback: Option[MediaType]): Option[MediaType] = {
1815
val extensionOpt = FileUtils.extension(filename)
1916

2017
def detectFromConfig = for {
2118
extension <- extensionOpt
2219
customMediaType <- config.find(extension)
23-
} yield contentType(customMediaType)
20+
} yield customMediaType
2421

25-
def detectAkkaFromExtension = extensionOpt.flatMap { e =>
26-
Try(MediaTypes.forExtension(e)).map(contentType).toOption
22+
def detectHttp4sFromExtension = extensionOpt.flatMap { e =>
23+
org.http4s.MediaType.extensionMap.get(e).map(MediaType(_))
2724
}
2825

2926
provided
3027
.orElse(detectFromConfig)
31-
.orElse(detectAkkaFromExtension)
28+
.orElse(detectHttp4sFromExtension)
3229
.orElse(fallback)
3330
}
34-
35-
private def contentType(mediaType: MediaType) = ContentType(mediaType, () => HttpCharsets.`UTF-8`)
36-
3731
}

delta/kernel/src/main/scala/ch/epfl/bluebrain/nexus/delta/kernel/http/MediaTypeDetectorConfig.scala renamed to delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/MediaTypeDetectorConfig.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
package ch.epfl.bluebrain.nexus.delta.kernel.http
1+
package ch.epfl.bluebrain.nexus.delta.plugins.storage.files
22

3-
import akka.http.scaladsl.model.MediaType
43
import cats.syntax.all.*
4+
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.MediaType
55
import pureconfig.ConfigReader
66
import pureconfig.configurable.genericMapReader
77
import pureconfig.error.CannotConvert
@@ -25,7 +25,7 @@ object MediaTypeDetectorConfig {
2525
ConfigReader.fromString(str =>
2626
MediaType
2727
.parse(str)
28-
.leftMap(_ => CannotConvert(str, classOf[MediaType].getSimpleName, s"'$str' is not a valid content type."))
28+
.leftMap(_ => CannotConvert(str, classOf[MediaType].getSimpleName, s"'$str' is not a valid media type."))
2929
)
3030
implicit val mapReader: ConfigReader[Map[String, MediaType]] = genericMapReader(Right(_))
3131

0 commit comments

Comments
 (0)