如何在scala中定义通用路由akka-http

时间:2017-01-05 05:56:11

标签: scala akka-http

我想在Scala Akka-HTTP中创建可重用的通用路由,以便我可以为我定义的其余路由使用相同的通用路由。

到目前为止,我可以将路由定义如下,以便完美运行。

class TestApi(val modules: Configuration with PersistenceService)(implicit executionContext: ExecutionContext) extends BaseApi with CirceSupport {
  override val oauth2DataHandler = modules.oauth2DataHandler

  val userDao = new TestService
  val testApi = pathPrefix("auth") {
    path("users") {
      pathEndOrSingleSlash {
        get {
          authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) {
            //auth => complete(userService.getAll().map(_.asJson))
            auth => complete(userDao.getAll().map(_.asJson))
          }
        }
      }
    } ~
    path("allUsers") {
      pathEndOrSingleSlash {
        post {
          entity(as[UserEntity1]) { userUpdate =>
            authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) {
              //auth => complete(userService.getAll().map(_.asJson))
              auth => complete(userDao.getAll().map(_.asJson))
            }
          }
        }
      }
    }
  } ~
    path("user" / "upload" / "file") {
      pathEndOrSingleSlash {
        post {
          entity(as[Multipart.FormData]) { fileData =>
            authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) {
              auth => {
                val fileName = UUID.randomUUID().toString
                val temp = System.getProperty("java.io.tmpdir")
                val filePath = "/var/www/html" + "/" + fileName
                complete (
                  FileHandler.processFile(filePath,fileData).map { fileSize =>
                    ("success", fileSize)
                    //HttpResponse(StatusCodes.OK, entity = s"File successfully uploaded. File size is $fileSize")
                  }.recover {
                    case ex: Exception => ("error", 0) //HttpResponse(StatusCodes.InternalServerError, entity = "Error in file uploading")
                  }.map(_.asJson)
                )
              }
            }
          }
        }
      }
    }
}

我在代码中找到了pathEndOrSingleSlash

authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) {            
    auth => ...
}

但却难免重复。

我想得到类似下面的内容。

get(url, function)
post(url, function)
put(url, function)

这样我就可以重复使用重复代码了。我怎样才能实现定义的通用路由?

1 个答案:

答案 0 :(得分:1)

您可以使用功能组合提取authenticateOAuth2AsyncpathpathEndOrSingleSlash指令。您可以编写一个更高阶的函数来提供“通用”框架,然后调用一个提供特定功能的函数:

def commonRoute(p : String, subRoute : AuthInfo[OauthAccount] => Route) = 
  authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) { auth =>
    path(p) {
      pathendOrSingleSlash {
        subRoute(auth)
      }
    }
  }

然后可以将其应用于您的特定情况:

//example code doesn't use the auth variable anywhere, thus the "_ =>"
val getRoute : AuthInfo[OauthAccount] => Route = 
  _ =>
    get {
      complete(userDao.getAll().map(_.asJson))
    }

val postAllUsersRoute : AuthInfo[OauthAccount] => Route =
  _ =>
    post {
      entity(as[UserEntity1]) { userUpdate =>
        complete(userDao.getAll().map(_.asJson)
      }
    }

然后合并形成你的最终Route

val testApi = pathPrefix("auth") {
  commonRoute("users", getRoute) ~ commonRoute("allUsers", postAllUersRoute)
}