http4s / http4s-servlet

http4s-servlet support
Apache License 2.0
6 stars 6 forks source link

Http4sServlet hangs on multipart requests #11

Open taig opened 5 years ago

taig commented 5 years ago

I noticed some odd behavior when sending a multipart request to an http4s service wrapped in a servlet.

object MyService {
  def apply(): HttpRoutes[IO] = HttpRoutes.of {
    case request =>
       request.decode[Multipart[IO]] { multipart =>
        Ok(s"Parts: ${multipart.parts.length}")
      }
  }
}

Requests work as expected when using the service without a Servlet.

curl -F "content=@/image.jpg" -v http://localhost:8080/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> POST / HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 4426
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------d3eedf51ac8c72ec
> 
* Done waiting for 100-continue
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
< Date: Fri, 04 Jan 2019 11:19:42 GMT
< Content-Length: 8
< 
* Connection #0 to host 127.0.0.1 left intact
Parts:  1

But doing the same with a (Blocking) Http4sServlet yields an odd response.

curl -F "content=@/image.jpg" -v http://localhost:8080/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 4426
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------2238d13e7d3aa3a6
> 
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< cache-control: no-cache
< expires: Mon, 01 Jan 1990 00:00:00 GMT
< Content-Type: text/html
< Content-Length: 0
< Server: Development/2.0
< Date: Fri, 04 Jan 2019 11:22:18 GMT
< 
* Connection #0 to host localhost left intact

After digging a bit deeper I realized that the servlet request processing is actually stuck here. I played around with it and managed to get it to work somehow, but without understanding why it's failing in the first place. In order to provide a proper patch a better understanding would be necessary though. I assume that the AsyncHttp4sServlet suffers from the same issue, but could not verify that yet.