Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement respondBytes similar to responding with text #395

Closed
thomasweitzel opened this issue Apr 28, 2018 · 2 comments
Closed

Implement respondBytes similar to responding with text #395

thomasweitzel opened this issue Apr 28, 2018 · 2 comments

Comments

@thomasweitzel
Copy link

I have a resources page that delivers binary content in a safe way, either from a backing file, a resource, or dynamically calculated content (like PNG, SVG, ICO, MP3, ...):

call.response.contentType(content.type)
call.respond(content.bytes)

Since 0.9.1 I get an exception (was no problem in 0.9.0):

io.ktor.response.UnsafeHeaderException:
Header Content-Type is controlled by the engine and cannot be set explicitly

When I omit the setting of the content type, the browser rightfully complains:

Resource interpreted as Stylesheet but transferred with MIME type text/plain:
https://domain.tld/resources?name=screen&ext=css

Resource interpreted as Document but transferred with MIME type application/zip:
https://domain.tld/resources?privileged=1&name=simulation&ext=xlsx

How can I solve the situation and still have a generic content producer page?

@orangy
Copy link
Contributor

orangy commented Apr 28, 2018

I was pretty sure we have respondBytes, but looks like it is an unfortunate omission… We will add it.
As a workaround, you may write your own low level OutgoingContent and a helper function:

class ByteContent(val bytes: ByteArray, override val contentType: ContentType, override val status: HttpStatusCode? = null): OutgoingContent.ByteArrayContent(){
    override val contentLength: Long
        get() = bytes.size.toLong()

    override fun bytes(): ByteArray = bytes

    override fun toString() = "ByteContent[$contentType] ${bytes.size} bytes"
}

suspend fun ApplicationCall.respondBytes(bytes: ByteArray, contentType: ContentType? = null, status: HttpStatusCode? = null, configure: OutgoingContent.() -> Unit = {}) {
    val message = ByteContent(bytes, defaultTextContentType(contentType), status).apply(configure)
    return respond(message)
}

And use it like

call.respondBytes(content.bytes, content.type)

@orangy orangy changed the title Cannot set content type anymore: safeHeaders Implement respondBytes similar to responding with text Apr 28, 2018
@thomasweitzel
Copy link
Author

Thank you for the workaround: it works. Looking forward to the next ktor release.

cy6erGn0m pushed a commit that referenced this issue May 3, 2018
schleinzer pushed a commit to schleinzer/ktor that referenced this issue Feb 26, 2019
schleinzer pushed a commit to schleinzer/ktor that referenced this issue Feb 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants