'Quarkus RestEasy reactive InputStream response using wrong writer

I tried to optimize a reactive endpoint streaming input of an audio file based on Quarkus REST Score Console. I replaced generic Response with Reactive RestResponse. It increased the score to 100 but it is using ServerStringMessageBodyHandler instead of ServerInputStreamMessageBodyHandler now. Is there a way to tell Quarkus what MessageBodyHandler to use? Now it is calling .toString() method on inputStream object. I tried to return directly ByteArray, but the issue is the same. Any idea what is going on wrong here?

@GET
@Path("/{lectureId}/stream")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
fun getLectureStreamById(
    @RestHeader("Range") rangeParam: String?,
    @RestPath lectureId: LectureId
): Uni<RestResponse<InputStream>> {
    return lectureAudioService.getAudioFile(lectureId).map { lectureStream ->
            downloadResponse(ByteArrayInputStream(lectureStream.data), filename = "$lectureId.mp3").build()
    }
}

fun downloadResponse(
    data: InputStream,
    filename: String,
): ResponseBuilder<InputStream> {
    return ResponseBuilder.ok(data)
        .header("Content-Disposition", "attachment;filename=$filename")
}


Solution 1:[1]

Based on answer in github issue it should be fixed in upcoming releases but original approach was not good as well because it blocked event loop. Better approach will be:

@Path("/{filename}/async-file")
@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
fun getAsyncFile(filename: String): Uni<RestResponse<AsyncFile>> {
    return Uni.createFrom().emitter { emitter: UniEmitter<in RestResponse<AsyncFile>> ->
        vertx.fileSystem().open(
            "$filename.mp3", OpenOptions()
        ) { result: AsyncResult<AsyncFile> ->
            if (result.succeeded()) emitter.complete(
                ResponseBuilder.ok(result.result()).header("Content-Disposition", "attachment;filename=$filename.mp3").build()
            ) else emitter.fail(result.cause())
        }
    }
}

Thanks to @geoand

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Filip Krawiec