Akka HTTP has good support in the routing dsl for extracting path query parameters (those following the ?, concatenated by &), but not for path parameters separated by ; (such as /my/path;JSESSIONID=123)
How is this best accomplished?
Easier than I thought. Could probably remove dependency on scalaz (Lens) and optimize the code a bit, but this will do for now.
Btw, also discovered that path params destroys the ability to match paths with the path directive: /my/path;JSESSIONID=123 does not match the directive path("my" / "path")
The solution below addresses this by removing the path params from the request context, and instead providing them.
Note to Akka guys: maybe you could incorporate something similar in the framework so the next guy that looks for getting JSESSIONID from path params doesn't have to implement the same?
def pathParams: Directive1[List[String]] = {
val prv = provide(List.empty[String])
def somePathParams(ctxPathLens: Lens[RequestContext, Path]) =
extract(ctx => (Slash ~ Segments).apply(ctxPathLens.get(ctx))).flatMap {
case Matched(_, Tuple1(path)) =>
path.takeRight(1) match {
case last :: Nil => last.split(';').toList match {
case lastHead :: lastTail => provide(lastTail) & mapRequestContext(
ctxPathLens.set(_, Path((path.dropRight(1) :+ lastHead).mkString("/", "/", ""))))
case _ => prv
}
case _ => prv
}
case _ => prv
}
val unmatchedPath = somePathParams(Lens.lensu((ctx, path) =>
ctx.mapUnmatchedPath(_ => path),
_.unmatchedPath))
val requestPath = somePathParams(Lens.lensu((ctx, path) =>
ctx.mapRequest(r => r.withUri(r.uri.withPath(path)))
, _.request.uri.path))
unmatchedPath.tflatMap(_ => Directive.Empty) & requestPath
}
def pathParamsMap: Directive1[Map[String, String]] =
pathParams.map(_.map(_.split('=').toList match {
case key :: Nil => key -> ""
case key :: values => key -> values.mkString("=")
case _ => ???
}).toMap)
def optionalPathParam(name: String): Directive1[Option[String]] =
pathParamsMap.map(_.get(name))
def optionalPathParamSessionId:Directive1[Option[UUID]] =
optionalPathParam(jsessionidKey).map(_.flatMap(j => Try(UUID.fromString(j)).toOption))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.