Akka HTTP api route structure

I am writing Akka-HTTP based REST API. Since I'm new to Akka and Scala, I'm not sure what might be the best way to organize the code in my project. I will have approx. 7 different objects with basic CRUD. This means that I will have more than 25 routes in the API. I would like to keep the routes grouped based on the entity with which they are logically connected. What could be a good way to achieve this? I am currently inspired by some of the projects available on GitHub and grouped these routes into features. I have a main feature that includes some common things, extends the directive and adds marshaling:

trait Resource extends Directives with JsonSupport{
   ...
}

Then I have other routes organized as shown below.

trait UserResource extends Resource{

  def userRoutes:Route =
    pathPrefix("authenticate") {
      pathEndOrSingleSlash {
        post {
          entity(as[LoginRequest]) { request =>
            ...
            }
          }
        }
      }
    } ~
    pathPrefix("subscribe") {
      pathEndOrSingleSlash {
        post {
          entity(as[UserSubscribeRequest]) { request =>
            ...
            }
          }
        }
      }
    }
}

, , :

class Routes extends UserResource with OtherResource with SomeOtherResource{

  ... handlers definitions ...
  ... helpers ...

  def allRoutesUnified: Route =
    handleErrors {
     cors() {
        pathPrefix("api") {
          authenticateOAuth2("api", PasswordAuthenticator) { _ =>
            //Routes defined in other traits
            otherRoutes ~ someOtherRoutes
          } 
        } ~ userRoutes  
      }
   }
}

, :

object Main extends App{

  ... usual Akka stuff ..

  val routes = new Routes ()
  val router = routes.allRoutesUnified
  Http().bindAndHandle(router, "localhost", 8080)
}

?

+4
1

- , . , OO, stackoverflow, scala java - .

, , , , OO. , , - .

, . , Route, , def, :

import akka.http.scaladsl.server.Directives._

//an object, not a class
object UserResource {

  //Note: val not def
  val userRoutes : Route = { 
    //same as in question 
  }

}

- , , .

allRoutesUnified , . :

object Routes {
  import UserResources.userRoutes

  def allRoutesUnified(innerRoute : Directive0 = userRoutes) : Route = 
    handleErrors {
      cors() {
        pathPrefix {
          authenticateOAuth2("api", PasswordAuthenticator) { _ =>
            innerRoute
          }
        }
      }
    }
}

, userRoutes.

, , Routes new:

object Main extends App {

  //no need to create a routes objects, i.e. no "new Routes()"

  Http().bindAndHandle(
    Routes.allRoutesUnified(), 
    "localhost", 
    8080
  )
} 
+3

Source: https://habr.com/ru/post/1681506/


All Articles