I'm using Akka HTTP 10.0.9, but struggling to get my unit tests to have a working Remote Address.
eg unit test:
Get("/").withHeaders(
RawHeader("Remote-Address", "192.168.1.1"), RawHeader("X-Forwarded-For", "192.168.1.1")
) ~> route ~> check {
status must_== StatusCodes.OK
}
And in the web server code:
extractClientIP{ clientAddr =>
complete(s"$clientAddr")
}
When running the app via the command line, the client address is returned correctly. But when run via unit tests, the client address always comes back as "Unknown"
What am I doing wrong?
This is caused by akka http can't handle the RawHeader in test. You can solve it by use the Remote-Address object for set the IP for test:
import akka.http.scaladsl.model.headers.`Remote-Address`
Get().withHeaders(
`Remote-Address`(RemoteAddress(new InetSocketAddress("192.168.1.1", 23)))
)
Related
I have a service using Akka HTTP that I have been doing some load testing on. Under stress, I've found that my service will ocassionally run into StreamTcpException when calling other service endpoints.
I create one flow for each endpoint which is shared by all of my actors. I am using something like this:
//this is done only once
val connectionFlow = Http(sys).outgoingConnection("host_name")
...
//each actor does this
val response = Source.single(HttpRequest(...)).via(connectionFlow).runWith(Sink.head)
I use Apache JMeter to load test my service, and with 40 threads, it typically takes 2000-4000 requests before I see my first error message. With 10 threads, it took me 9000 requests before I saw it.
The message looks like:
akka.stream.StreamTcpException: Tcp command [Connect(<host_here>/<ip_here>,None,List(),Some(10 seconds),true)] failed
I actually have 4 separate flows for 4 different endpoints my service relies on. I usually see StreamTcpException from all four if my service fails.
Anyone have any ideas why this is happening? Thanks in advance.
I face same issue previously, for me it is working as expected.
val httpClient: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] = Http().outgoingConnection(host,port,None,connSetts)
Problem place 👍 Source.single(request).via(httpClient)
It is unable to connect my host so I use proxy server for this.
val httpsProxyTransport : ClientTransport = ClientTransport.httpsProxy(InetSocketAddress.createUnresolved("proxyservicesHost", 90))
val connSetts: ClientConnectionSettings = ClientConnectionSettings(system).withTransport(httpsProxyTransport).withIdleTimeout(Duration(180, "second"))
val httpClient: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] = Http().outgoingConnection(host,port,None,connSetts)
Then I pass the httpclient in .via(httpclient), it works.
I'm using the Play framework 2.5. I created a new project and tried testing web service.
For the moment I just copied the example at https://www.playframework.com/documentation/2.5.x/ScalaTestingWebServiceClients#testing-a-github-client .
On my machine I'm using a proxy, and when running GitHubClientSpec
testOnly GitHubClientSpec
I get an error from the proxy as response.
What I also tried from the scala console is the piece of code :
import play.core.server._
import play.api.routing.sird._
import play.api.mvc._
val server = NettyServer.fromRouter(ServerConfig(
port = Some(19000),
address = "127.0.0.1"
)) {
case GET(p"/hello") => Action {
Results.Ok(s"Hello")
}
}
And curl http://localhost:19000/hello, returned "Hello".
So this works fine, but when running testOnly GitHubClientSpec it is not.
How to prevent Play from using the proxy ?
Does Akka use ports (by default) other than port 2551 for clustering?
I have a 3-node Akka cluster--each node running in a Docker using 2.4's bind-hostname/port. I have a seed running outside a Docker in some test code. I can successfully send messages to the nodes point-to-point, directly, so basic Akka messaging works fine for the Docker-ized nodes.
My Seed code looks like this:
class Seed() extends Actor {
def receive = {
case "report" =>
mediator ! DistributedPubSubMediator.SendToAll("/user/sender", ReportCommand(), false)
case r:ReportCommand => println("Report, please!")
}
}
val seed = system.actorOf(Props(new Seed()),"sender")
val mediator = DistributedPubSub(system).mediator
mediator ! DistributedPubSubMediator.Put(seed)
My worker nodes look like this:
class SenderActor(senderLike:SenderLike) extends Actor {
val mediator = DistributedPubSub(context.system).mediator
mediator ! Put(self)
def receive = {
case report:ReportCommand => println("REPORT CMD!")
}
}
When I run this and send a "report" message to the Seed, I see the Seed's "Report, please!" message, so it received its own broadcast, but the 3 workers in the Dockers don't register having received anything (no output on receive). Not sure what's wrong so I'm wondering if there is another port besides 2551 I need to EXPOSE in my Dockers for clustering?
You'll need to configure Akka using port and bind-port, since in docker the "local port" is different from the port "the outside world can reach me at".
In order to do this see this documentation page: Peer to Peer vs Client Server
And this FAQ section Why are replies not received from a remote actor?
I am currently in the process of moving all our Rest tests to the CI server and have noticed that all tests are failing due to the an SSL handshake, now I have successfully disabled this with the TrustManager with our Java test suite, but am unsure how to do it with Scala dispatch library, and havent been able to find many examples that could apply in this scenario.
val JSONstr = "{samplekey:samplevalue}"
val response:String = Http(url("https://www.host.com/path/to/post")
<< (checkInJSONstr, "application/json") as_str)
The following exception is occuring as expected:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
...
Is there a way to do it cleanly syntactically ignore SSL with the dispatch library?
import dispatch._
val http = new Http with HttpsLeniency
val response:String = http(url("https://www.host.com/path/to/post")
<< (checkInJSONstr, "application/json") as_str)
viktortnk's answer doesn't work anymore with the newest version of Dispatch (0.13.2). For the newest version, you can use the following to create an http client that accepts any certificate:
val myHttp = Http.withConfiguration(config => config.setAcceptAnyCertificate(true))
Then you can use it for GET requests like this:
myHttp(url("https://www.host.com/path").GET OK as.String)
I found this out here: Why does dispatch throw "java.net.ConnectException: General SSLEngine ..." and "unexpected status" exceptions for a particular URL?
I got a little problem. I just moved the client-server-communication of my current project from remote Scala Actors to remote Akka Actors.
Everything worked fine while testing on my local machine but once I tried to run the code with the client and server at different machines the client can't reach the server anymore (I get a java.nio.channels.NotYetConnectedException). I double and tripple checked the ip and port being used. It's the same host data I used in the code with the Scala actors (which by the way still work. So apparently nothing changed at the firewall settings and server is technically reachable)
Here are the important parts of the code (which I mostly copy pasted from akkas homepage):
On the server actor
import akka.actor.Actor._
import akka.actor.{Actor, ActorRef, Supervisor}
override def preStart = {
// I also tried the servers external ip here
remote.start(host, 1357)
// SERVER_SERVICE_NAME is a string constant in a trait that both server
// and client extend
// all actual work is refered to SessionActor
remote.registerPerSession(SERVER_SERVICE_NAME, actorOf[SessionActor])
}
and on the client:
import akka.actor.Actor._
import akka.actor.{Actor, ActorRef, Supervisor}
override def preStart = {
// CLIENT_SERVICE_NAME is a string constant
Actor.remote.start("localhost", 5678).register(CLIENT_SERVICE_NAME, self)
// I also tried "Thread sleep 1000" here just in case
// internalServer is a private var of the type Option[ActorRef]
// host and serverPort are actually read from a propertiesfile. Guess this
// doesn't matter. I checked them.
internalServer = Some(
remote.actorFor(SERVER_SERVICE_NAME, host, serverPort)
)
// Again I tried "Thread sleep 1000" here. Didn't help neither
internalServer foreach (server => {
(server !! Ping) foreach (_ match { // !!! this is where the exception is thrown !!!
case Pong => println("connected")
case _ => println("something's fishy")
})
})
}
I am using:
Scala 2.8.1 (although I'm no sure whether the machines at my client are 2.8 or 2.8.1, I use the scala-library.jar from the akka distribution)
Akka 1.0
I know that you can't debugg my code her but I'd be very thankfull for any kind of hint or idea what might be going wrong here.
P.S.: the Exception is thrown within a splitsecond after trying to send the Ping. So I didn't bother increasing the Timeout-time.
DISCLAIMER: I am the PO of Akka
Try using a raw IP address instead of a hostname in remote.start(), if that doesn't solve it you have 2 options:
Make sure that the two parties can
DNS resolve eachother
Upgrade to
current master (1.1-SNAPSHOT), since
I've made quite a few changes to
avoid name resolution.
Does that help?