Skip to content

Commit

Permalink
Merge pull request #1220 from disneystreaming/dfrancoeur/439-host
Browse files Browse the repository at this point in the history
Attempt to compute the original url, otherwise keep behaviour
  • Loading branch information
Baccata authored Sep 29, 2023
2 parents ca880f4 + 47dde00 commit 6b438cc
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
32 changes: 28 additions & 4 deletions modules/http4s-swagger/src-jvm/smithy4s/http4s/swagger/Docs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ package http4s
package swagger

import cats.data.NonEmptyList
import cats.data.OptionT
import cats.effect.Sync
import org.http4s.HttpRoutes
import org.http4s._
import org.http4s.dsl.Http4sDsl
import org.http4s.headers.Host
import org.http4s.headers.Location
import org.http4s.HttpRoutes
import org.webjars.WebJarAssetLocator
import cats.data.OptionT

private[smithy4s] abstract class Docs[F[_]](
ids: NonEmptyList[HasId],
Expand All @@ -48,7 +49,7 @@ private[smithy4s] abstract class Docs[F[_]](
private val validSpecs = ids.map(toSwaggerUrl).map(_._1).toList
private val specsUrls = ids.map(toSwaggerUrl).map(_._2)

val actualPath: Path = Uri.Path.unsafeFromString("/" + path)
private val actualPath: Path = Uri.Path.unsafeFromString("/" + path)

object DocPath {
def unapply(p: Path): Boolean = {
Expand All @@ -59,9 +60,32 @@ private[smithy4s] abstract class Docs[F[_]](
}
}
}

private def fromReqToReclaimedUri(req: Request[F]): Option[Uri] = {
for {
isSecure <- req.isSecure
auth <- req.uri.authority.orElse(
req.headers
.get[Host]
.map(h =>
Uri.Authority(None, host = Uri.RegName(h.host), port = h.port)
)
)
} yield {
val scheme =
if (isSecure) Uri.Scheme.https
else Uri.Scheme.http
req.uri.copy(authority = Some(auth), scheme = Some(scheme))
}
}

def routes: HttpRoutes[F] = HttpRoutes.of[F] {
case r @ GET -> DocPath() if r.uri.query.isEmpty =>
Found(Location(Uri(path = actualPath / "index.html")))
val finalUri = fromReqToReclaimedUri(r) match {
case None => Uri(path = actualPath / "index.html")
case Some(uri) => uri.withPath(uri.path / "index.html")
}
Found(Location(finalUri))

case request @ GET -> `actualPath` / `specsPath` / jsonSpec
if validSpecs.contains(jsonSpec) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
package smithy4s.http4s.swagger

import cats.effect.IO
import com.comcast.ip4s._
import org.http4s._
import org.http4s.implicits._
import org.typelevel.ci.CIString
import weaver._
import smithy4s.HasId
import smithy4s.ShapeId
import weaver._

object DocsSpec extends SimpleIOSuite {

Expand Down Expand Up @@ -98,6 +99,32 @@ object DocsSpec extends SimpleIOSuite {
}
}

test(s"GET http://localhost:8080/docs redirects to with absolute uri") {
val socket = SocketAddress(ip"127.0.0.1", port"8080")
val dummyConnection = Request.Connection(socket, socket, secure = false)
val path = "docs"
val baseUri = uri"http://localhost:8080"
val app = docs(path).orNotFound
val request =
Request[IO](
method = Method.GET,
uri = baseUri / path
)
.withAttribute(Request.Keys.ConnectionInfo, dummyConnection)
app.run(request).map { response =>
val redirectUri = response.headers
.get(CIString("Location"))
.map(_.head)
.map(_.value)

expect(response.status == Status.Found) and
expect.eql(
redirectUri,
Some((baseUri / path / "index.html").renderString)
)
}
}

test(s"GET /irrelevant returns 404") {
val filePath = s"/irrelevant"
val request =
Expand Down

0 comments on commit 6b438cc

Please sign in to comment.