Skip to content

Commit

Permalink
Add http root response (close #397)
Browse files Browse the repository at this point in the history
Adds the ability to configure collector's root (GET `/`) response.
If `rootResponse.enabled = true` when `/` is requested a static, configured
response is returned.

With status code equal to `rootResponse.statusCode`,
http headers of `rootResponse.headers` and
body of `rootResponse.body`
  • Loading branch information
peel committed Nov 17, 2023
1 parent 2de0024 commit 1a45280
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import org.http4s.dsl.Http4sDsl
import org.http4s.implicits._
import com.comcast.ip4s.Dns

class Routes[F[_]: Sync](enableDefaultRedirect: Boolean, service: IService[F]) extends Http4sDsl[F] {
class Routes[F[_]: Sync](enableDefaultRedirect: Boolean, enableRootResponse: Boolean, service: IService[F])
extends Http4sDsl[F] {

implicit val dns: Dns[F] = Dns.forSync[F]

Expand Down Expand Up @@ -77,8 +78,13 @@ class Routes[F[_]: Sync](enableDefaultRedirect: Boolean, service: IService[F]) e
NotFound("redirects disabled")
}

private val rootRoute = HttpRoutes.of[F] {
case GET -> Root if enableRootResponse =>
service.rootResponse
}

val value: HttpApp[F] = {
val routes = healthRoutes <+> corsRoute <+> cookieRoutes
val routes = healthRoutes <+> corsRoute <+> cookieRoutes <+> rootRoute
val res = if (enableDefaultRedirect) routes else rejectRedirect <+> routes
res.orNotFound
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ object Run {
appInfo
)
httpServer = HttpServer.build[F](
new Routes[F](config.enableDefaultRedirect, collectorService).value,
new Routes[F](config.enableDefaultRedirect, config.rootResponse.enabled, collectorService).value,
if (config.ssl.enable) config.ssl.port else config.port,
config.ssl.enable,
config.networking
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ trait IService[F[_]] {
): F[Response[F]]
def determinePath(vendor: String, version: String): String
def sinksHealthy: F[Boolean]
def rootResponse: F[Response[F]]
}

object Service {
Expand Down Expand Up @@ -140,6 +141,20 @@ class Service[F[_]: Sync](
)
}

override def rootResponse: F[Response[F]] = Sync[F].fromEither {
for {
status <- Status.fromInt(config.rootResponse.statusCode)
body = Stream.emit(config.rootResponse.body).through(fs2.text.utf8.encode)
headers = Headers(
config.rootResponse.headers.toList.map { case (name, value) => Header.Raw(CIString(name), value) }
)
} yield Response[F](
status = status,
body = body,
headers = headers
)
}

def extractHeader(req: Request[F], headerName: String): Option[String] =
req.headers.get(CIString(headerName)).map(_.head.value)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class RoutesSpec extends Specification {
override def preflightResponse(req: Request[IO]): IO[Response[IO]] =
IO.pure(Response[IO](status = Ok, body = Stream.emit("preflight response").through(text.utf8.encode)))

override def rootResponse: IO[Response[IO]] =
IO.pure(Response(status = Ok, body = Stream.emit("root").through(text.utf8.encode)))

override def cookie(
body: IO[Option[String]],
path: String,
Expand All @@ -59,9 +62,9 @@ class RoutesSpec extends Specification {
override def sinksHealthy: IO[Boolean] = IO.pure(true)
}

def createTestServices(enabledDefaultRedirect: Boolean = true) = {
def createTestServices(enabledDefaultRedirect: Boolean = true, enableRootResponse: Boolean = false) = {
val service = new TestService()
val routes = new Routes(enabledDefaultRedirect, service).value
val routes = new Routes(enabledDefaultRedirect, enableRootResponse, service).value
(service, routes)
}

Expand Down Expand Up @@ -240,6 +243,24 @@ class RoutesSpec extends Specification {
test(Method.GET)
test(Method.POST)
}

"respond to the root route" in {
"enabled return the response" in {
val (_, routes) = createTestServices(enableRootResponse = true)
val request = Request[IO](method = Method.GET, uri = uri"/")
val response = routes.run(request).unsafeRunSync()

response.status must beEqualTo(Status.Ok)
response.as[String].unsafeRunSync() must beEqualTo("root")
}
"disabled return NotFound" in {
val (_, routes) = createTestServices(enableRootResponse = false)
val request = Request[IO](method = Method.GET, uri = uri"/")
val response = routes.run(request).unsafeRunSync()

response.status must beEqualTo(Status.NotFound)
}
}
}

}

0 comments on commit 1a45280

Please sign in to comment.