0
votes

I am learning to build server using Akka-Http and this is what I have written so far

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.stream.{Materializer, ActorMaterializer}
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._

import scala.concurrent.ExecutionContextExecutor


// todo() : add event timestamp
case class ECFailure(symbolicName:String)


trait Protocols extends DefaultJsonProtocol {
  implicit val ecFailureFormat = jsonFormat1(ECFailure.apply)
}

trait EmailService extends Protocols {
  implicit val system: ActorSystem
  implicit def executor: ExecutionContextExecutor
  implicit val materializer: Materializer

  val route =
    logRequestResult("email-service") {
      pathPrefix("ec") {
        (post & entity(as[ECFailure])) { ecFailure =>
          complete {
            println("received: " + ecFailure)
            "Done"
          }
        }
      }
      path("") {
        get {
          complete {
            "Welcome."
          }
        }
      }
    }
}

object ECServer extends App with EmailService {
  override implicit val system = ActorSystem("ec-server")
  override implicit val executor = system.dispatcher
  override implicit val materializer = ActorMaterializer()
  val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
}

When I run that and hit the endpoints I see

$ curl -v  http://localhost:8080
* Rebuilt URL to: http://localhost:8080/
* Hostname was NOT found in DNS cache
*   Trying ::1...
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
* Server akka-http/2.3.12 is not blacklisted
< Server: akka-http/2.3.12
< Date: Tue, 28 Jul 2015 21:51:04 GMT
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 8
< 
* Connection #0 to host localhost left intact
Welcome.

but the other endpoint is not available

$ curl -v -XPOST -d "{'symbolicName': 'ABC'}" -H "Content-Type:application/json" http://localhost:8080/ec
* Hostname was NOT found in DNS cache
*   Trying ::1...
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /ec HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> Content-Type:application/json
> Content-Length: 23
> 
* upload completely sent off: 23 out of 23 bytes
< HTTP/1.1 404 Not Found
* Server akka-http/2.3.12 is not blacklisted
< Server: akka-http/2.3.12
< Date: Tue, 28 Jul 2015 21:51:06 GMT
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 42
< 
* Connection #0 to host localhost left intact
The requested resource could not be found.

On Server, I see logs as

Connected to the target VM, address: '127.0.0.1:58024', transport: 'socket'
[DEBUG] [07/28/2015 14:50:59.528] [main] [EventStream(akka://ec-server)] logger log1-Logging$DefaultLogger started
[DEBUG] [07/28/2015 14:50:59.530] [main] [EventStream(akka://ec-server)] Default Loggers started
[DEBUG] [07/28/2015 14:51:00.016] [ec-server-akka.actor.default-dispatcher-6] [akka://ec-server/system/IO-TCP/selectors/$a/0] Successfully bound to /127.0.0.1:8080
[DEBUG] [07/28/2015 14:51:03.917] [ec-server-akka.actor.default-dispatcher-6] [akka://ec-server/system/IO-TCP/selectors/$a/0] New connection accepted
[DEBUG] [07/28/2015 14:51:04.258] [ec-server-akka.actor.default-dispatcher-13] [ActorSystem(ec-server)] email-service: Response for
  Request : HttpRequest(HttpMethod(GET),http://localhost:8080/,List(User-Agent: curl/7.37.1, Host: localhost:8080, Accept: */*),HttpEntity.Strict(none/none,ByteString()),HttpProtocol(HTTP/1.1))
  Response: Complete(HttpResponse(200 OK,List(),HttpEntity.Strict(text/plain; charset=UTF-8,ByteString(87, 101, 108, 99, 111, 109, 101, 46)),HttpProtocol(HTTP/1.1)))
[DEBUG] [07/28/2015 14:51:06.265] [ec-server-akka.actor.default-dispatcher-19] [akka://ec-server/system/IO-TCP/selectors/$a/0] New connection accepted
[DEBUG] [07/28/2015 14:51:06.284] [ec-server-akka.actor.default-dispatcher-17] [ActorSystem(ec-server)] email-service: Response for
  Request : HttpRequest(HttpMethod(POST),http://localhost:8080/ec,List(User-Agent: curl/7.37.1, Host: localhost:8080, Accept: */*),HttpEntity.Strict(application/json,ByteString(123, 39, 115, 121, 109, 98, 111, 108, 105, 99, 78, 97, 109, 101, 39, 58, 32, 39, 65, 66, 67, 39, 125)),HttpProtocol(HTTP/1.1))
  Response: Rejected(List())

What is not correct here?

1
You need to add a ~ between your pathPrefix("ec") { ,,, ) and path("") { ... }.Peter Neyens

1 Answers

4
votes

The problem was missing ~ between different routes. The following fixed it

  val route =
    logRequestResult("email-service") {
      pathPrefix("ec") {
        (post & entity(as[ECFailure])) { ecFailure =>
          complete {
            println("received: " + ecFailure)
            "Done"
          }
        }
      } ~
        path("") {
          get {
            complete {
              "Welcome."
            }
          }
        }
    }

and curl works

$ curl -v -XPOST -d '{"symbolicName": "ABC"}' -H "Content-Type:application/json" http://localhost:8080/ec
* Hostname was NOT found in DNS cache
*   Trying ::1...
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /ec HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> Content-Type:application/json
> Content-Length: 23
> 
* upload completely sent off: 23 out of 23 bytes
< HTTP/1.1 200 OK
* Server akka-http/2.3.12 is not blacklisted
< Server: akka-http/2.3.12
< Date: Tue, 28 Jul 2015 22:05:37 GMT
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 4
< 
* Connection #0 to host localhost left intact
Done