Skip to content

Commit

Permalink
handle multipart form data requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Alessio Coser committed Nov 5, 2020
1 parent 90367d9 commit 1c5ba71
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies {

compile 'org.eclipse.jetty:jetty-server:9.4.27.v20200227'
compile 'org.eclipse.jetty:jetty-servlet:9.4.27.v20200227'
compile 'com.github.DaikonWeb:daikon-core:1.4.0'
compile 'com.github.DaikonWeb:daikon-core:1.4.1'

testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
Expand Down
11 changes: 10 additions & 1 deletion src/main/kotlin/daikon/HttpRequest.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package daikon

import daikon.core.Method
import daikon.core.Part
import daikon.core.PathParams
import daikon.core.Request
import java.net.URLDecoder.decode
import java.nio.charset.StandardCharsets
import java.nio.charset.StandardCharsets.UTF_8
import javax.servlet.http.HttpServletRequest

class HttpRequest(private val request: HttpServletRequest) : Request {
private val body by lazy { request.inputStream.readBytes() }
private val multipartBody by lazy { request.parts }
private lateinit var pathParams: PathParams

override fun withPathParams(value: String): HttpRequest {
Expand All @@ -34,6 +35,14 @@ class HttpRequest(private val request: HttpServletRequest) : Request {

override fun body() = body.toString(UTF_8)

override fun multipart(name: String): Part {
val part = multipartBody.single { it.name == name }
val file = part.inputStream.readBytes()
val partName = part.submittedFileName ?: part.name

return Part(partName, part.contentType, file)
}

override fun header(name: String): String = request.getHeader(name)

override fun hasHeader(name: String) = request.headerNames.toList().contains(name)
Expand Down
5 changes: 4 additions & 1 deletion src/main/kotlin/daikon/HttpServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.eclipse.jetty.servlet.ServletHolder
import org.eclipse.jetty.util.log.Log
import java.time.LocalDateTime.now
import java.time.temporal.ChronoUnit.MILLIS
import javax.servlet.MultipartConfigElement


class HttpServer(private val port: Int = 4545, initializeActions: DaikonServer.() -> Unit = {}): DaikonServer(initializeActions) {
Expand All @@ -22,7 +23,9 @@ class HttpServer(private val port: Int = 4545, initializeActions: DaikonServer.(
val beginStarting = now()
server = Server(port)
context.addAttribute("port", port)
handler.addServlet(ServletHolder(RoutingServlet(routingHandler)), "/*")
val servletHolder = ServletHolder(RoutingServlet(routingHandler))
servletHolder.registration.setMultipartConfig(MultipartConfigElement("/tmp"))
handler.addServlet(servletHolder, "/*")
server.handler = handler
server.start()
val endStarting = now()
Expand Down
43 changes: 43 additions & 0 deletions src/test/kotlin/daikon/RequestTest.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package daikon

import daikon.core.HttpStatus.INTERNAL_SERVER_ERROR_500
import daikon.core.Request
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import topinambur.FieldPart
import topinambur.FilePart
import topinambur.http

class RequestTest {
Expand Down Expand Up @@ -215,4 +218,44 @@ class RequestTest {
assertThat(local("/").http.post().body).isEqualTo("POST")
}
}

@Test
fun `receive a file`() {
HttpServer()
.post("/*") { req: Request, res ->
val file = req.multipart("firstData")

res.write(file.content)
}
.start()
.use {
val response = local("/").http.post(
data = mapOf("firstData" to FilePart("file", "txt", "testo da convertire".toByteArray()))
)

assertThat(response.body).isEqualTo("testo da convertire")
}
}

@Test
fun `receive a file and a field`() {
HttpServer()
.post("/*") { req: Request, res ->
val file = req.multipart("firstData")
val field = req.multipart("secondData")

res.write("""${file.content.toString(Charsets.UTF_8)} | ${field.content.toString(Charsets.UTF_8)}""")
}
.start()
.use {
val response = local("/").http.post(
data = mapOf(
"firstData" to FilePart("file", "txt", "testo da convertire".toByteArray()),
"secondData" to FieldPart("valore")
)
)

assertThat(response.body).isEqualTo("testo da convertire | valore")
}
}
}

0 comments on commit 1c5ba71

Please sign in to comment.