complete preparations for files uploading via posts

This commit is contained in:
InsanusMokrassar 2022-03-09 18:46:08 +06:00
parent 99b953635e
commit 38cd186e60
7 changed files with 81 additions and 12 deletions

View File

@ -190,7 +190,7 @@ fun getDIModule(
singleWithBinds { UsersStorageServerRoutesConfigurator(get(), get()) }
singleWithBinds { RolesStorageReadServerRoutesConfigurator<Role>(get(), RoleSerializer, get()) }
singleWithBinds { RolesManagerRolesStorageServerRoutesConfigurator(get(), get()) }
singleWithBinds { ServerPostsServiceRoutingConfigurator(get(), get(), get()) }
singleWithBinds { ServerPostsServiceRoutingConfigurator(get(), get(), get(), get()) }
singleWithBinds { ClientStaticRoutingConfiguration("web") }
singleWithBinds {

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,7 @@ import io.ktor.client.request.headers
import io.ktor.client.request.post
import io.ktor.http.HttpHeaders
import kotlinx.serialization.builtins.*
import kotlinx.serialization.modules.polymorphic
class ClientWritePostsService(
private val baseUrl: String,
@ -28,7 +29,9 @@ class ClientWritePostsService(
private val unifiedRequester = UnifiedRequester(
unifiedRequester.client,
unifiedRequester.serialFormat.createWithSerializerModuleExtension {
contextual()
polymorphic(Content::class) {
subclass(BinaryContent::class, BinaryContentSerializer(TempFileIdentifierInputProvider::class, TempFileIdentifierInputProvider.serializer()))
}
}
)

View File

@ -0,0 +1,58 @@
package dev.inmo.postssystem.services.posts.common
import dev.inmo.micro_utils.common.FileName
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.micro_utils.mime_types.MimeTypeSerializer
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import dev.inmo.postssystem.features.content.common.BinaryContent
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlin.reflect.KClass
@Serializer(BinaryContent::class)
class BinaryContentSerializer<T: SimpleInputProvider>(
private val kClass: KClass<T>,
private val serializer: KSerializer<T>
) : KSerializer<BinaryContent> {
@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
override val descriptor: SerialDescriptor = buildSerialDescriptor(
"BinaryContent",
SerialKind.CONTEXTUAL
) {
element("filename", FileName.serializer().descriptor)
element("mimetype", MimeTypeSerializer.descriptor)
element("data", serializer.descriptor)
}
override fun deserialize(decoder: Decoder): BinaryContent {
return decoder.decodeStructure(descriptor) {
var fileName: FileName? = null
var mimeType: MimeType? = null
var data: T? = null
while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> fileName = decodeSerializableElement(descriptor, 0, FileName.serializer())
1 -> mimeType = decodeSerializableElement(descriptor, 1, MimeTypeSerializer)
2 -> data = decodeSerializableElement(descriptor, 2, serializer)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
}
BinaryContent(
fileName ?: error("Filename must be presented, but was absent"),
mimeType ?: error("Mimetype must be presented, but was absent"),
data ?: error("Data must be presented, but was absent")
)
}
}
override fun serialize(encoder: Encoder, value: BinaryContent) {
require(kClass.isInstance(value.inputProvider)) { "${value.inputProvider} do not inherit $kClass" }
encoder.encodeStructure(descriptor) {
encodeSerializableElement(descriptor, 0, FileName.serializer(), value.filename)
encodeSerializableElement(descriptor, 1, MimeTypeSerializer, value.mimeType)
encodeSerializableElement(descriptor, 2, serializer, value.inputProvider as T)
}
}
}

View File

@ -2,8 +2,7 @@ package dev.inmo.postssystem.services.posts.common
import kotlinx.serialization.SerialFormat
import kotlinx.serialization.cbor.Cbor
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.SerializersModuleBuilder
import kotlinx.serialization.modules.*
const val postsRootPath = "posts"
const val postsCreateTempPathPart = "temp"
@ -13,8 +12,10 @@ const val postsPostIdParameter = "postId"
fun SerialFormat.createWithSerializerModuleExtension(
configurator: SerializersModuleBuilder.() -> Unit
) = Cbor {
serializersModule = SerializersModule {
include(this@createWithSerializerModuleExtension.serializersModule)
configurator()
}
serializersModule = this@createWithSerializerModuleExtension.serializersModule.overwriteWith(
SerializersModule {
include(this@createWithSerializerModuleExtension.serializersModule)
configurator()
}
)
}

View File

@ -34,6 +34,7 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.serialization.builtins.*
import kotlinx.serialization.modules.polymorphic
import java.io.File
import java.nio.file.Files
import java.nio.file.attribute.FileTime
@ -43,8 +44,15 @@ class ServerPostsServiceRoutingConfigurator(
private val readPostsService: ReadPostsService,
private val writePostsService: WritePostsService? = readPostsService as? WritePostsService,
private val scope: CoroutineScope,
private val unifiedRouter: UnifiedRouter
unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element {
private val unifiedRouter = UnifiedRouter(
serialFormat = unifiedRouter.serialFormat.createWithSerializerModuleExtension {
polymorphic(Content::class) {
subclass(BinaryContent::class, BinaryContentSerializer(TempFileIdentifierInputProvider::class, TempFileIdentifierInputProvider.serializer()))
}
}
)
private val contentEitherSerializer = EitherSerializer(ContentId.serializer(), ContentSerializer)
private val contentsEitherSerializer = ListSerializer(contentEitherSerializer)
private val contentsSerializer = ListSerializer(ContentSerializer)

View File

@ -22,8 +22,7 @@ class PublicationTargetTelegram(
) : PublicationTarget {
override suspend fun publish(post: PublicationPost) {
post.content.mapNotNull {
val content = it.content
when (content) {
when (val content = it.content) {
is BinaryContent -> {
val storageFile by lazy {
StorageFile(content.filename.name, content.inputProvider().readBytes()).asMultipartFile()