Skip to content

Commit

Permalink
handle route rejections in the path matchers instrumentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ivantopo committed Oct 19, 2021
1 parent f55e9f5 commit bac02a9
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package kamon.instrumentation.akka.http

import java.util.concurrent.Callable

import akka.http.scaladsl.marshalling.{ToEntityMarshaller, ToResponseMarshallable, ToResponseMarshaller}
import akka.http.scaladsl.model.StatusCodes.Redirection
import akka.http.scaladsl.model.{HttpHeader, HttpRequest, HttpResponse, StatusCode, Uri}
Expand All @@ -22,8 +21,8 @@ import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.util.control.NonFatal
import scala.util.{Failure, Success, Try}
import java.util.regex.Pattern

import akka.NotUsed
import akka.http.scaladsl.server.RouteResult.Rejected
import akka.stream.scaladsl.Flow
import kamon.context.Context
import kanela.agent.libs.net.bytebuddy.matcher.ElementMatchers.isPublic
Expand Down Expand Up @@ -103,6 +102,7 @@ trait HasMatchingContext {
def setMatchingContext(ctx: Seq[PathMatchingContext]): Unit
def setDefaultOperationName(defaultOperationName: String): Unit
def prependMatchingContext(matched: PathMatchingContext): Unit
def popOneMatchingContext(): Unit
}

object HasMatchingContext {
Expand All @@ -123,6 +123,9 @@ object HasMatchingContext {
override def prependMatchingContext(matched: PathMatchingContext): Unit =
matchingContext = matched +: matchingContext

override def popOneMatchingContext(): Unit =
matchingContext = matchingContext.tail

@Initializer
def initialize(): Unit =
matchingContext = Seq.empty
Expand Down Expand Up @@ -280,18 +283,29 @@ object PathDirectivesRawPathPrefixInterceptor {
def rawPathPrefix[T](@Argument(1) matcher: PathMatcher[T]): Directive[T] = {
implicit val LIsTuple = matcher.ev

extract(ctx => {
extract { ctx =>
val fullPath = ctx.unmatchedPath.toString()
val matching = matcher(ctx.unmatchedPath)

matching match {
case m: Matched[_] =>
ctx.asInstanceOf[HasMatchingContext].prependMatchingContext(PathMatchingContext(fullPath, m))
ctx.asInstanceOf[HasMatchingContext]
.prependMatchingContext(PathMatchingContext(fullPath, m))
case _ =>
}
matching
}).flatMap {
case Matched(rest, values) => tprovide(values) & mapRequestContext(_ withUnmatchedPath rest)
case Unmatched => reject

(ctx, matching)
} flatMap {
case (ctx, Matched(rest, values)) =>
tprovide(values) & mapRequestContext(_ withUnmatchedPath rest) & mapRouteResult { routeResult =>

if(routeResult.isInstanceOf[Rejected])
ctx.asInstanceOf[HasMatchingContext].popOneMatchingContext()

routeResult
}

case (_, Unmatched) => reject
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package kamon.instrumentation.akka.http

import java.util.concurrent.Callable

import akka.http.scaladsl.marshalling.{ToEntityMarshaller, ToResponseMarshallable, ToResponseMarshaller}
import akka.http.scaladsl.model.StatusCodes.Redirection
import akka.http.scaladsl.model.{HttpHeader, HttpRequest, HttpResponse, StatusCode, Uri}
Expand All @@ -38,8 +37,8 @@ import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.util.control.NonFatal
import scala.util.{Failure, Success, Try}
import java.util.regex.Pattern

import akka.NotUsed
import akka.http.scaladsl.server.RouteResult.Rejected
import akka.stream.scaladsl.Flow
import kamon.context.Context
import kanela.agent.libs.net.bytebuddy.matcher.ElementMatchers.isPublic
Expand Down Expand Up @@ -127,6 +126,7 @@ trait HasMatchingContext {
def setMatchingContext(ctx: Seq[PathMatchingContext]): Unit
def setDefaultOperationName(defaultOperationName: String): Unit
def prependMatchingContext(matched: PathMatchingContext): Unit
def popOneMatchingContext(): Unit
}

object HasMatchingContext {
Expand All @@ -147,6 +147,9 @@ object HasMatchingContext {
override def prependMatchingContext(matched: PathMatchingContext): Unit =
matchingContext = matched +: matchingContext

override def popOneMatchingContext(): Unit =
matchingContext = matchingContext.tail

@Initializer
def initialize(): Unit =
matchingContext = Seq.empty
Expand Down Expand Up @@ -303,18 +306,29 @@ object PathDirectivesRawPathPrefixInterceptor {
def rawPathPrefix[T](@Argument(0) matcher: PathMatcher[T]): Directive[T] = {
implicit val LIsTuple = matcher.ev

extract(ctx => {
extract { ctx =>
val fullPath = ctx.unmatchedPath.toString()
val matching = matcher(ctx.unmatchedPath)

matching match {
case m: Matched[_] =>
ctx.asInstanceOf[HasMatchingContext].prependMatchingContext(PathMatchingContext(fullPath, m))
ctx.asInstanceOf[HasMatchingContext]
.prependMatchingContext(PathMatchingContext(fullPath, m))
case _ =>
}
matching
}).flatMap {
case Matched(rest, values) => tprovide(values) & mapRequestContext(_ withUnmatchedPath rest)
case Unmatched => reject

(ctx, matching)
} flatMap {
case (ctx, Matched(rest, values)) =>
tprovide(values) & mapRequestContext(_ withUnmatchedPath rest) & mapRouteResult { routeResult =>

if(routeResult.isInstanceOf[Rejected])
ctx.asInstanceOf[HasMatchingContext].popOneMatchingContext()

routeResult
}

case (_, Unmatched) => reject
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package kamon.instrumentation.akka.http

import java.util.concurrent.Callable

import akka.http.scaladsl.marshalling.{ToEntityMarshaller, ToResponseMarshallable, ToResponseMarshaller}
import akka.http.scaladsl.model.StatusCodes.Redirection
import akka.http.scaladsl.model.{HttpHeader, HttpRequest, HttpResponse, StatusCode, Uri}
Expand All @@ -22,8 +21,8 @@ import scala.concurrent.{Batchable, ExecutionContext, Future, Promise}
import scala.util.control.NonFatal
import scala.util.{Failure, Success, Try}
import java.util.regex.Pattern

import akka.NotUsed
import akka.http.scaladsl.server.RouteResult.Rejected
import akka.stream.scaladsl.Flow
import kamon.context.Context
import kanela.agent.libs.net.bytebuddy.matcher.ElementMatchers.isPublic
Expand Down Expand Up @@ -110,6 +109,7 @@ trait HasMatchingContext {
def setMatchingContext(ctx: Seq[PathMatchingContext]): Unit
def setDefaultOperationName(defaultOperationName: String): Unit
def prependMatchingContext(matched: PathMatchingContext): Unit
def popOneMatchingContext(): Unit
}

object HasMatchingContext {
Expand All @@ -130,6 +130,9 @@ object HasMatchingContext {
override def prependMatchingContext(matched: PathMatchingContext): Unit =
matchingContext = matched +: matchingContext

override def popOneMatchingContext(): Unit =
matchingContext = matchingContext.tail

@Initializer
def initialize(): Unit =
matchingContext = Seq.empty
Expand Down Expand Up @@ -286,18 +289,29 @@ object PathDirectivesRawPathPrefixInterceptor {
def rawPathPrefix[T](@Argument(0) matcher: PathMatcher[T]): Directive[T] = {
implicit val LIsTuple = matcher.ev

extract(ctx => {
extract { ctx =>
val fullPath = ctx.unmatchedPath.toString()
val matching = matcher(ctx.unmatchedPath)

matching match {
case m: Matched[_] =>
ctx.asInstanceOf[HasMatchingContext].prependMatchingContext(PathMatchingContext(fullPath, m))
ctx.asInstanceOf[HasMatchingContext]
.prependMatchingContext(PathMatchingContext(fullPath, m))
case _ =>
}
matching
}).flatMap {
case Matched(rest, values) => tprovide(values) & mapRequestContext(_ withUnmatchedPath rest)
case Unmatched => reject

(ctx, matching)
} flatMap {
case (ctx, Matched(rest, values)) =>
tprovide(values) & mapRequestContext(_ withUnmatchedPath rest) & mapRouteResult { routeResult =>

if(routeResult.isInstanceOf[Rejected])
ctx.asInstanceOf[HasMatchingContext].popOneMatchingContext()

routeResult
}

case (_, Unmatched) => reject
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,6 @@ class AkkaHttpServerTracingSpec extends WordSpecLike with Matchers with ScalaFut
"return the correct operation name with overloaded route" in {
val target = s"$protocol://$interface:$port/some_endpoint"

// this endpoint isn't affected
// okHttp.newCall(new Request.Builder()
// .post(RequestBody.create(MediaType.get("application/json"), "{}"))
// .url(target).build())
// .execute()

okHttp.newCall(new Request.Builder()
.get()
.url(target).build())
Expand Down

0 comments on commit bac02a9

Please sign in to comment.