Skip to content

Commit

Permalink
Merge pull request #25 from Quafadas/proxyWork
Browse files Browse the repository at this point in the history
Proxy fixes
  • Loading branch information
Quafadas authored Jun 2, 2024
2 parents f3b7324 + 6027e87 commit 9321524
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 82 deletions.
5 changes: 5 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ test:
checkOpts:
mill project.run --help


jvmServe:
mill -w project.runBackground --build-tool scala-cli --project-dir /Users/simon/Code/indigoLite --log-level info --browse-on-open-at / --path-to-index-html /Users/simon/Code/indigoLite/static

proxy:
mill -w project.runBackground --project-dir /Users/simon/Code/viteless --port 3006 --proxy-prefix-path /api --proxy-target-port 8080 --log-level trace


goViteless:
mill -w project.run --project-dir /Users/simon/Code/viteless --styles-dir /Users/simon/Code/viteless/styles

Expand Down
12 changes: 8 additions & 4 deletions project/src/build.runner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,16 @@ def buildRunnerMill(
.background
.void

val millargs = List(
"-w",
s"$moduleName.fastLinkJS",
"-j",
"0"
) ++ extraBuildArgs
// TODO pipe this to stdout so that we can see linker progress / errors.
val builder = ProcessBuilder(
"mill",
List(
"-w",
s"$moduleName.fastLinkJS"
) ++ extraBuildArgs
millargs
).withWorkingDirectory(workDir)
.spawn[IO]
.use {
Expand All @@ -147,6 +150,7 @@ def buildRunnerMill(
for
_ <- logger.trace("Starting buildRunnerMill").toResource
_ <- logger.trace(s"watching path $watchLinkComplePath").toResource
_ <- logger.trace(s"running mill with args $millargs").toResource
_ <- builder
_ <- watcher
yield ()
Expand Down
49 changes: 2 additions & 47 deletions project/src/live.server.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ import cats.implicits.*
import _root_.io.circe.*
import _root_.io.circe.Encoder

import ProxyConfig.Equilibrium
import ProxyConfig.Server
import com.comcast.ip4s.Host
import cats.data.NonEmptyList
import ProxyConfig.LocationMatcher

sealed trait FrontendEvent derives Encoder.AsObject

case class KeepAlive() extends FrontendEvent derives Encoder.AsObject
Expand Down Expand Up @@ -213,46 +207,6 @@ object LiveServer extends IOApp:
.withHandler(minimumLevel = Some(Level.get(lvl).get))
.replace()

val proxyConf2: Resource[IO, Option[Equilibrium]] = proxyTarget
.zip(pathPrefix)
.traverse {
(pt, prfx) =>
IO(
Equilibrium(
ProxyConfig.HttpProxyConfig(
servers = NonEmptyList(
Server(
listen = port,
serverNames = List("localhost"),
locations = List(
ProxyConfig.Location(
matcher = LocationMatcher.Prefix(prfx),
proxyPass = s"http://$$backend"
)
)
),
List()
),
upstreams = List(
ProxyConfig.Upstream(
name = "backend",
servers = NonEmptyList(
ProxyConfig.UpstreamServer(
host = Host.fromString("localhost").get,
port = pt,
weight = 5
),
List()
)
)
)
)
)
)

}
.toResource

val server = for
_ <- logger
.debug(
Expand Down Expand Up @@ -295,7 +249,8 @@ object LiveServer extends IOApp:
CliValidationError("path-to-index-html and styles-dir can't be defined at the same time")
)

proxyRoutes <- makeProxyRoutes(client, pathPrefix, proxyConf2)(logger)
proxyConf2 <- proxyConf(proxyTarget, pathPrefix)
proxyRoutes: HttpRoutes[IO] = makeProxyRoutes(client, proxyConf2)(logger)

_ <- buildRunner(
buildTool,
Expand Down
3 changes: 2 additions & 1 deletion project/src/middleware/ETagMiddleware.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ object ETagMiddleware:
OptionT.liftF(logger.debug("No ETag header in query, service it")) >>
service(req).semiflatMap {
resp =>
respondWithEtag(resp)
logger.trace(resp.toString) >>
respondWithEtag(resp)
}
end match
}
Expand Down
5 changes: 3 additions & 2 deletions project/src/middleware/noCache.middleware.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import org.http4s.HttpRoutes
import org.http4s.Request
import org.typelevel.ci.CIStringSyntax

import scribe.Scribe

import cats.data.Kleisli
import cats.data.OptionT
import cats.effect.*
import cats.effect.IO
import scribe.Scribe
import cats.data.OptionT
import cats.syntax.all.*

object NoCacheMiddlware:
Expand Down
1 change: 0 additions & 1 deletion project/src/proxy.config.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import com.comcast.ip4s.*

import cats.data.NonEmptyList

import cats.syntax.all.*

object ProxyConfig:
Expand Down
19 changes: 15 additions & 4 deletions project/src/proxy.http.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ object HttpProxy:

val routes: HttpRoutes[F] = HttpRoutes.of {
case (req: Request[F]) =>
// println("in proxy")
// println(req)
val pathRendered = pathPrefix + req.uri.path.renderString
// println(pathRendered)
val host = req.headers.get[Host].map(_.host).getOrElse("") // Host set otherwise empty string
val newServers = servers.filter(_.serverNames.contains(host))

// println(host)
// println(newServers)
val exact =
newServers
.flatMap(_.locations)
Expand All @@ -59,12 +63,13 @@ object HttpProxy:
.headOption
.map(_._2)
}

proxy.fold(
Response[F](Status.NotFound).withEntity("No Route Found").pure[F]
)(
proxyThrough[F](_, upstreams)
.flatMap(uri => client.toHttpApp(req.removeHeader[Host].withUri(uri.addPath(pathRendered))))
proxyThrough[F](_, upstreams).flatMap {
uri =>
client.toHttpApp(req.removeHeader[Host].withUri(uri.addPath(pathRendered)))
}
)
}

Expand All @@ -76,6 +81,8 @@ object HttpProxy:
proxyPass: String,
upstreams: Map[String, NonEmptyList[ProxyConfig.UpstreamServer]]
): F[Uri] =
println(s"proxypass $proxyPass")
println(upstreams)
if !proxyPass.contains("$") then Uri.fromString(proxyPass).liftTo[F]
else
extractVariable(proxyPass).flatMap {
Expand All @@ -89,6 +96,8 @@ object HttpProxy:
)
)
}
end if
end proxyThrough

private def extractVariable[F[_]: ApplicativeThrow](s: String): F[(String, String, String)] =
s.split('$').toList match
Expand Down Expand Up @@ -131,6 +140,8 @@ object HttpProxy:

def xForwardedMiddleware[G[_], F[_]](http: Http[G, F]): Http[G, F] = Kleisli {
(req: Request[F]) =>
println("in middleware")
println(req)
req
.remote
.fold(http.run(req)) {
Expand Down
84 changes: 69 additions & 15 deletions project/src/proxy.routes.scala
Original file line number Diff line number Diff line change
@@ -1,32 +1,86 @@
import org.http4s.HttpRoutes
import org.http4s.client.Client
import org.http4s.server.Router
import org.http4s.server.middleware.Logger

import com.comcast.ip4s.Host
import com.comcast.ip4s.Port

import scribe.Scribe

import cats.data.NonEmptyList
import cats.effect.IO
import cats.effect.kernel.Resource
import cats.effect.std.Random
import cats.syntax.all.*

import ProxyConfig.Equilibrium
import ProxyConfig.LocationMatcher
import ProxyConfig.Server

def makeProxyRoutes(
client: Client[IO],
pathPrefix: Option[String],
proxyConfig: Resource[IO, Option[Equilibrium]]
)(logger: Scribe[IO]): Resource[IO, HttpRoutes[IO]] =
proxyConfig.flatMap {
case Some(pc) =>
{
given R: Random[IO] = Random.javaUtilConcurrentThreadLocalRandom[IO]
logger.debug("setup proxy server") >>
IO(HttpProxy.servers[IO](pc, client, pathPrefix.getOrElse(???)).head._2)
}.toResource
proxyConfig: Option[(Equilibrium, String)]
)(logger: Scribe[IO]): HttpRoutes[IO] =
proxyConfig match
case Some((pc, pathPrefix)) =>
given R: Random[IO] = Random.javaUtilConcurrentThreadLocalRandom[IO]
Logger.httpRoutes[IO](
logHeaders = true,
logBody = true,
redactHeadersWhen = _ => false,
logAction = Some((msg: String) => logger.trace(msg))
)(
Router(
pathPrefix -> HttpProxy.servers[IO](pc, client, pathPrefix).head._2
)
)

case None =>
(
logger.debug("no proxy set") >>
IO(HttpRoutes.empty[IO])
).toResource
}
HttpRoutes.empty[IO]

end makeProxyRoutes

def proxyConf(proxyTarget: Option[Port], pathPrefix: Option[String]): Resource[IO, Option[(Equilibrium, String)]] =
proxyTarget
.zip(pathPrefix)
.traverse {
(pt, prfx) =>
IO(
(
Equilibrium(
ProxyConfig.HttpProxyConfig(
servers = NonEmptyList(
Server(
listen = pt,
serverNames = List("localhost"),
locations = List(
ProxyConfig.Location(
matcher = LocationMatcher.Prefix(prfx),
proxyPass = "http://$backend"
)
)
),
List()
),
upstreams = List(
ProxyConfig.Upstream(
name = "backend",
servers = NonEmptyList(
ProxyConfig.UpstreamServer(
host = Host.fromString("localhost").get,
port = pt,
weight = 5
),
List()
)
)
)
)
),
prfx
)
)

}
.toResource
10 changes: 8 additions & 2 deletions project/src/routes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.http4s.Response
import org.http4s.ServerSentEvent
import org.http4s.StaticFile
import org.http4s.Status
import org.http4s.Uri.Path.SegmentEncoder
import org.http4s.dsl.io.*
import org.http4s.scalatags.*
import org.http4s.server.Router
Expand All @@ -35,7 +36,6 @@ import cats.effect.kernel.Resource
import cats.syntax.all.*

import _root_.io.circe.syntax.EncoderOps
import org.http4s.Uri.Path.SegmentEncoder

def routes[F[_]: Files: MonadThrow](
stringPath: String,
Expand All @@ -60,6 +60,12 @@ def routes[F[_]: Files: MonadThrow](
StaticFile
.fromPath(fs2.io.file.Path(stringPath) / req.uri.path.renderString, Some(req))
.getOrElseF(NotFound())

case req @ GET -> Root / fName ~ "map" =>
StaticFile
.fromPath(fs2.io.file.Path(stringPath) / req.uri.path.renderString, Some(req))
.getOrElseF(NotFound())

},
ref
)(logger)
Expand Down Expand Up @@ -209,9 +215,9 @@ def routes[F[_]: Files: MonadThrow](
val app = logMiddler(
refreshRoutes
.combineK(linkedAppWithCaching)
.combineK(proxyRoutes)
.combineK(clientSpaRoutes)
.combineK(staticAssetRoutes)
.combineK(proxyRoutes)
)

clientRoutingPrefix.fold(IO.unit)(s => logger.trace(s"client spa at : $s")).toResource >>
Expand Down
Loading

0 comments on commit 9321524

Please sign in to comment.