Playframework接受版本路由
我试图在Play2.2中实现REST版本控制 我希望客户端在标题中发送以下内容:Playframework接受版本路由,playframework,playframework-2.2,Playframework,Playframework 2.2,我试图在Play2.2中实现REST版本控制 我希望客户端在标题中发送以下内容: Accept: application/vnd.helloworld+json; version=1 并且基于该版本头,服务器将调用匹配的控制器操作。我计划为每个api版本快照一个完整的控制器包 大概是这样的: com.helloworld.v1.controllers com.helloworld.v2.controllers 例如: POST /users/login { "email": "foo@gma
Accept: application/vnd.helloworld+json; version=1
并且基于该版本头,服务器将调用匹配的控制器操作。我计划为每个api版本快照一个完整的控制器包
大概是这样的:
com.helloworld.v1.controllers
com.helloworld.v2.controllers
例如:
POST /users/login
{ "email": "foo@gmail.com", "password": "bar" }
我想将该请求发送给以下控制员:
com.helloworld.v1.controllers.UserController
如何在Global.onRouterRequest中干净利落地实现这一点 在考虑了一会儿之后,我很难想象这是如何按照您描述的方式工作的,而不使用运行时反射按版本调用包/类。我也会厌倦这样做,因为你说你的API版本可能有不同的参数,这会使类型不兼容 下面是一种方法,通过在路由中定义默认的API URI,然后为每个版本定义一个URI。在
onroutereRequest
中,您可以将传入的请求重新路由到不同的URI(无需使用重定向
),并且用户仍然不知道这些URI是否存在。请注意,需要查询参数来允许它们通过默认url(如果类型要更改,我认为没有其他方法)
路线:
GET /api controllers.Application.index
GET /v1/api controllers.v1.Test.index(test: Int ?= 0)
GET /v2/api controllers.v2.Test.index(test: String ?= "")
在GlobalSettings
对象中:
override def onRouteRequest(request: RequestHeader): Option[Handler] = {
// Strip the version from the headers
val regex = "version=(\\d+)".r
val version: Option[Int] = request.headers.get("Accept").flatMap(x => regex.findFirstMatchIn(x).map(_.group(1).toInt))
// Copy the version to the URI (if found) in a new RequestHeader (if found), and re-route
val req: RequestHeader = version.map(v =>
request.copy(
uri = "/v" + v.toString + request.uri,
path = "/v" + v.toString + request.path
)
).getOrElse(request)
super.onRouteRequest(req)
}
我认为不清洁的唯一部分是列举路线的必要性,考虑到反向路由编译器通常所做的代码体操,这将是很难克服的。考虑了一段时间后,我很难想象这会以您描述的方式工作,而不使用运行时反射按版本调用包/类。我也会厌倦这样做,因为你说你的API版本可能有不同的参数,这会使类型不兼容 下面是一种方法,通过在路由中定义默认的API URI,然后为每个版本定义一个URI。在
onroutereRequest
中,您可以将传入的请求重新路由到不同的URI(无需使用重定向
),并且用户仍然不知道这些URI是否存在。请注意,需要查询参数来允许它们通过默认url(如果类型要更改,我认为没有其他方法)
路线:
GET /api controllers.Application.index
GET /v1/api controllers.v1.Test.index(test: Int ?= 0)
GET /v2/api controllers.v2.Test.index(test: String ?= "")
在GlobalSettings
对象中:
override def onRouteRequest(request: RequestHeader): Option[Handler] = {
// Strip the version from the headers
val regex = "version=(\\d+)".r
val version: Option[Int] = request.headers.get("Accept").flatMap(x => regex.findFirstMatchIn(x).map(_.group(1).toInt))
// Copy the version to the URI (if found) in a new RequestHeader (if found), and re-route
val req: RequestHeader = version.map(v =>
request.copy(
uri = "/v" + v.toString + request.uri,
path = "/v" + v.toString + request.path
)
).getOrElse(request)
super.onRouteRequest(req)
}
唯一的一部分,我认为不干净是必要的枚举路线,这将是难以克服的代码体操反向路线编译器通常做。< / P> URL是容易互换的?可能有额外的路线在后续版本的API,api在不同版本之间可能有不同的参数。我的意思是,就像regex在请求URI中为
v2
替换v1
一样。从客户端的角度来看,不会有v1或v2。我们试图实现这个规范:URL容易互换吗?在api的后续版本中可能会有额外的路由,api在不同版本之间可能有不同的参数。我的意思是,就像regex在请求URI中为v2
替换v1
一样。从客户端的角度来看,不会有v1或v2。我们正在尝试实现这个规范:我同意,这可能是最好的方法。枚举版本路由并不会让我太烦恼,可能会分割路由并在主路由文件中导入带有前缀的每个版本路由。此解决方案保留了反向路由器所做的所有工作nice@JamesCowhen“可能拆分路由并在主路由文件中导入带有前缀的每个版本路由”-如何完成?我也面临同样的问题。我同意,这可能是最好的办法。枚举版本路由并不会让我太烦恼,可能会分割路由并在主路由文件中导入带有前缀的每个版本路由。此解决方案保留了反向路由器所做的所有工作nice@JamesCowhen“可能拆分路由并在主路由文件中导入带有前缀的每个版本路由”-如何完成?我也面临同样的问题。