-
Notifications
You must be signed in to change notification settings - Fork 596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] provide inspectable routes with minimal changes #2966
Conversation
Test FAILed. Pull request validation reportMima Failures
Other Failed Tasksakka-http / Compile / ./ headerCheck failed because of There are files without headers! akka-http-tests / Test / ./ headerCheck failed because of There are files without headers! |
@@ -23,17 +23,18 @@ import scala.concurrent.{ ExecutionContextExecutor, Future } | |||
private[http] class RequestContextImpl( | |||
val request: HttpRequest, | |||
val unmatchedPath: Uri.Path, | |||
val tokenValues: Map[ExtractionToken[_], Any], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a request attribute as well once they are managed but since it is specific to routing maybe it fits here well.
3b59ee8
to
551f060
Compare
new ParamMagnet { | ||
type Out = pdef.Out | ||
def apply() = pdef(value) | ||
def apply() = pdef(value) named "parameters" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately, that's not enough and we want to add separate information about each of the parameters.
private val _patch : Directive0 = method(PATCH) | ||
private val _post : Directive0 = method(POST) | ||
private val _put : Directive0 = method(PUT) | ||
private val _delete : Directive0 = method(DELETE) named "delete" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These ones override the name from the def method(HttpMethod)
one above.
Test PASSed. |
551f060
to
2f3c25b
Compare
case dr: DirectiveRoute => leaves(dr.child, prefix :+ dr) | ||
case last => Vector(RoutePath(prefix, last)) | ||
} | ||
leaves(route, Vector.empty).foreach(println) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What this prints currently is this:
[info] pathPrefix(<function1>) -> pathEnd -> post -> class akka.http.scaladsl.server.StandardRoute$$anon$1
[info] pathPrefix(<function1>) -> pathEnd -> put -> class akka.http.scaladsl.server.StandardRoute$$anon$1
[info] pathPrefix(<function1>) -> path(<function1>) -> get -> class akka.http.scaladsl.server.DynamicDirective$$$Lambda$310/1221027335
[info] pathPrefix(<function1>) -> path(<function1>) -> delete -> class akka.http.scaladsl.server.DynamicDirective$$$Lambda$310/1221027335
That means, we can already somewhat enumerate the chain of directives per leaf route. We don't have enough metadata available to look into the actual path matchers. That should be the next step.
} | ||
}(ctx) | ||
|
||
implicit class AddStatic[T](d: Directive1[T]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems, this one isn't necessary at all. Adding implicits like the above addByNameNullaryApply
and addDirective1Apply
means that we can change the semantics of route building with a single import that brings those implicits into scope.
private val _options: Directive0 = method(OPTIONS) named "options" | ||
private val _patch : Directive0 = method(PATCH) named "patch" | ||
private val _post : Directive0 = method(POST) named "post" | ||
private val _put : Directive0 = method(PUT) named "put" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately, these named
decorators are just a toy. What we should provide instead is something like meta
which allows to decorate a Directive with typed meta information.
Test FAILed. Pull request validation reportOther Failed Tasksakka-http / Compile / ./ headerCheck failed because of There are files without headers! akka-http-tests / Test / ./ headerCheck failed because of There are files without headers! |
complete(apiDescForRoute(forRoute)) | ||
|
||
private def apiDescForRoute(route: Route): OpenApi = { | ||
case class RoutePath(segments: Seq[DirectiveRoute], last: Route) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, what we get here per leaf route is an ordered chain of all (the metadata of) the directives that are applied for that leaf route. Once we expose enough metadata, we should be able to generate openapi specifications but also do "static" (= at route building time) analytics of the routing tree. Even with this simple prototype we could prevent that people would be accidentally nesting path
or method directives.
Test PASSed. |
193d255
to
9f86e0c
Compare
Test FAILed. !!! Couldn't read commit file !!! |
Refs #201, #2956
In a previous try, I tried to create a full AST of possible route structures. However, I don't think that's necessary. What we should strive for is