Akka HTTP client closing connection early

791 views
Skip to first unread message

Tom Eccles

unread,
Dec 4, 2014, 10:27:56 AM12/4/14
to akka...@googlegroups.com
I'm trying to use Akka HTTP to write an HttpClient to send a single request and receive a response. My current approach is the following method, having set up an OutgoingConnection:

  private def sendRequest(request: HttpRequest, connection: Http.OutgoingConnection): Future[HttpResponse] = {
    Source(List(request -> 'NoContext)).runWith(Sink(connection.requestSubscriber))
    Source(connection.responsePublisher).map(_._1).runWith(Sink.head[HttpResponse])
  }

In the resulting TCP stream, I see the client send the HTTP request as expected, immediately followed by a TCP [FIN, ACK] packet. This causes the server to immediately reply with its own [FIN, ACK], closing the connection without sending a response.

Am I using the OutgoingConnection wrong, or is this a problem with Akka HTTP?

Strangely, I do get an HttpResponse when making requests to servers running with Akka HTTP - they respond despite the early FIN.

Akka Team

unread,
Dec 4, 2014, 12:11:18 PM12/4/14
to Akka User List
Hi Tom,

There wasn't a fully operating Http Client in 0.11 only some initial parts. Please wait for the 1.0-M1 version which comes with a fresh new API and a proper client. The new version is just around the corner ;)

-Endre

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.



--
Akka Team
Typesafe - The software stack for applications that scale
Blog: letitcrash.com
Twitter: @akkateam

Konrad 'ktoso' Malawski

unread,
Dec 4, 2014, 12:13:25 PM12/4/14
to akka...@googlegroups.com
And one minute afterwards… 1.0-M1 released!

See details in the announcement email :-)


Happy hakking!

-- 
Konrad 'ktoso' Malawski
hAkker @ typesafe

Joe Edwards

unread,
Dec 8, 2014, 8:59:29 AM12/8/14
to akka...@googlegroups.com
I'm seeing similar behaviour in 1.0-M1, my client looks like this:

class SingleUseConnectionHttpClient()(implicit actorSystem: ActorSystem) {

  val http = Http()
  implicit val materializer = FlowMaterializer(namePrefix = Some("SingleUseConnectionHttpClient"))

  def sendRequest(request: HttpRequest): Future[HttpResponse] = {
    val connection = http.outgoingConnection(request.uri.authority.host.address(), request.uri.effectivePort)
 
    Source.singleton(request) via connection.flow runWith Sink.head
  }
}
 
My best guess is that the request source is terminating after the single request, and this causes the connection to signal a close even though it is still waiting for the response. I've tried putting more than one request in the Source, and it always sends the [FIN, ACK] as soon as the last request is sent, regardless of how many responses have arrived.

On a related note, is there a more fully featured client coming soon? For example I believe spray 1.3.1 had built-in support for connection pooling to a single host.

Roland Kuhn

unread,
Dec 8, 2014, 9:08:15 AM12/8/14
to akka-user
Which server do you see this with? A priori it makes sense to close the sending side if no further requests will follow, but if relevant HTTP servers misinterpret this then we’ll have to fix it (whether or not it is broken is a different question).

Regards,

Roland

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.



Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Reactive apps on the JVM.
twitter: @rolandkuhn


Endre Varga

unread,
Dec 8, 2014, 9:30:30 AM12/8/14
to akka...@googlegroups.com
On Mon, Dec 8, 2014 at 3:08 PM, Roland Kuhn <goo...@rkuhn.info> wrote:
Which server do you see this with? A priori it makes sense to close the sending side if no further requests will follow, but if relevant HTTP servers misinterpret this then we’ll have to fix it (whether or not it is broken is a different question).

Two scenarios are possible here:

 1. the server misinterprets half-closed connections
 2. The TCP implementation does not correctly half-close the connection. AFAIK we have tests for this, but we can double-check it.

-Endre

Joe Edwards

unread,
Dec 8, 2014, 12:06:25 PM12/8/14
to akka...@googlegroups.com
So is it valid to close your half of the TCP stream if you aren't sending more requests (even if you're waiting for a response)?

I'm seeing it close early consistently against a Spray 1.3.1 server, a Tomcat server and an akka-http 1.0-M1 server. (Interestingly not against a 0.11 server)

I can't find any publicly available servers that exhibit the same behaviour right now, but I can have a further look if you think it's helpful.

Joe

Joe Edwards

unread,
Dec 9, 2014, 7:57:36 PM12/9/14
to akka...@googlegroups.com
I've tried to look into it, and it seems unclear. There's an interesting discussion which explains the argument here:


My akka client behaves as a 'type 1', and so it doesn't work with servers of 'type B'.

I don't have a good list of 'type B' servers, but the few I listed above (noticeably all JVM based?) seem to exhibit it.

How easy would it be to implement a config option (say) to enable/disable this behaviour?

Roland Kuhn

unread,
Dec 10, 2014, 5:03:31 AM12/10/14
to akka-user
The best way to find out is to create a ticket with the information gathered so far, that way it won’t be accidentally forgotten.

Thanks,

Roland

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Joe Edwards

unread,
Dec 10, 2014, 6:51:40 AM12/10/14
to akka...@googlegroups.com

Roland Kuhn

unread,
Dec 10, 2014, 7:02:53 AM12/10/14
to akka-user
Thanks a lot! 

10 dec 2014 kl. 12:51 skrev Joe Edwards <joeyed...@googlemail.com>:


--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Peter Swift

unread,
Dec 10, 2014, 3:29:04 PM12/10/14
to akka...@googlegroups.com
Seems like I'm having the same issue.

object TestClient {
  implicit val system = ActorSystem()
  implicit val fm = FlowMaterializer()

  val connection = Http().outgoingConnection("localhost", 8080)

  def request() = {
    val result = Source.singleton(HttpRequest(GET, Uri("/ping"))).via(connection.flow).runWith(Sink.head)
    Await.result(result, 10.seconds)
  }
}

object TestServer {
  implicit val system = ActorSystem()
  implicit val fm = FlowMaterializer()

  def bind() {
    val binding = Http().bind(interface = "localhost", port = 8080)

    binding startHandlingWithSyncHandler {
      case HttpRequest(GET, Uri.Path("/ping"), _, _, _) => HttpResponse(entity = "PONG!")
      case _: HttpRequest                               => HttpResponse(404, entity = "Unknown resource!")
    }
  }
}

In repl: 
Server.bind

In another repl (first request works. subsequent requests fail)

scala> TestClient.request
res0: akka.http.model.HttpResponse = HttpResponse(200 OK,List(Date: Wed, 10 Dec 2014 20:22:04 GMT, Server: akka-http/2.3.7),HttpEntity.Default(text/plain; charset=UTF-8,5,SourcePipe(PublisherSource(akka.stream.impl.MultiStreamOutputProcessor$SubstreamOutput@5656b4fa),List(Collect(<function1>,OperationAttributes(List(Name(collect))))),List(),OperationAttributes(List()))),HttpProtocol(HTTP/1.1))

scala> TestClient.request
java.util.NoSuchElementException: empty stream
at akka.stream.scaladsl.HeadSink$HeadSinkSubscriber.onComplete(ActorFlowSink.scala:108)
at akka.stream.impl.fusing.ActorOutputBoundary.complete(ActorInterpreter.scala:167)
at akka.stream.impl.fusing.ActorOutputBoundary.onUpstreamFinish(ActorInterpreter.scala:194)


But I can 'curl localhost:8080/ping' all day long without problems.
Reply all
Reply to author
Forward
0 new messages