Skip to content

Commit

Permalink
add HttpExchange.fileName() method
Browse files Browse the repository at this point in the history
  • Loading branch information
angryziber committed Jul 27, 2023
1 parent c47950b commit c2c36da
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased
* jdbc: DB_READONLY=true env var can be used to make the whole app read-only (e.g. when migrating the DB, instead of Heroku maintenance mode)
* HttpExchange.fileName() added for setting of Content-Disposition

# 1.5.5
* jdbc: support reading of collections of Decimal from DB array columns
Expand Down
10 changes: 8 additions & 2 deletions server/src/klite/HttpExchange.kt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ open class HttpExchange(
get() = responseHeaders["Content-type"]?.firstOrNull()
set(value) { value?.let { header("Content-type", MimeTypes.withCharset(it)) } }

fun fileName(fileName: String, attachment: Boolean = true) {
header("Content-disposition", (if (attachment) "attachment" else "inline") + "; filename=\"$fileName\"")
responseType = MimeTypes.typeFor(fileName)
}

val accept get() = Accept(header("Accept"))

fun render(code: StatusCode, body: Any?) {
Expand All @@ -103,9 +108,10 @@ open class HttpExchange(
* Sends response headers and provides the stream
* @param length 0 -> no response, null -> use chunked encoding
*/
fun startResponse(code: StatusCode, length: Long? = null, contentType: String? = null): OutputStream {
fun startResponse(code: StatusCode, length: Long? = null, contentType: String? = null, fileName: String? = null): OutputStream {
sessionStore?.save(this, session)
responseType = contentType
fileName?.let { fileName(it) }
contentType?.let { responseType = it }
val bodyNotAllowed = method == HEAD || method == OPTIONS
original.sendResponseHeaders(code.value, if (length == 0L || bodyNotAllowed) -1 else length ?: 0)
if (bodyNotAllowed) throw BodyNotAllowedException()
Expand Down
25 changes: 25 additions & 0 deletions server/test/klite/HttpExchangeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,31 @@ class HttpExchangeTest {
verify { original.responseHeaders.add("Set-Cookie", "LANG=et; Domain=angryip.org; SameSite=Strict") }
}

@Test fun `response content-type`() {
exchange.responseType = MimeTypes.csv
verify { original.responseHeaders.set("Content-type", "application/csv; charset=UTF-8") }

exchange.responseType = "text/hello; charset=ISO-8859-1"
verify { original.responseHeaders.set("Content-type", "text/hello; charset=ISO-8859-1") }

exchange.responseType = MimeTypes.pdf
verify { original.responseHeaders.set("Content-type", "application/pdf") }
}

@Test fun `response content-disposition`() {
exchange.fileName("hello.xml")
verify {
original.responseHeaders.set("Content-disposition", "attachment; filename=\"hello.xml\"")
original.responseHeaders.set("Content-type", "text/xml; charset=UTF-8")
}

exchange.fileName("mega.pdf", attachment = false)
verify {
original.responseHeaders.set("Content-disposition", "inline; filename=\"mega.pdf\"")
original.responseHeaders.set("Content-type", "application/pdf")
}
}

@Test fun `body as text`() {
every { exchange.requestType } returns null
every { original.requestBody } answers { "123".byteInputStream() }
Expand Down

0 comments on commit c2c36da

Please sign in to comment.