Skip to content

Instantly share code, notes, and snippets.

@ChristopherDavenport
Created July 10, 2023 14:43
Show Gist options
  • Save ChristopherDavenport/071b86c843ab4a03e9c4f398c4eaab76 to your computer and use it in GitHub Desktop.
Save ChristopherDavenport/071b86c843ab4a03e9c4f398c4eaab76 to your computer and use it in GitHub Desktop.
Segment Allow List Implementation
import org.http4s.RequestPrelude
import org.typelevel.ci.CIString
object SegmentAllowList {
def fromAllowList(set: Set[CIString])(req: RequestPrelude): String = {
classifier(req)((s: String) => if (set.contains(CIString(s))) SegmentFilter.LeaveAsIs else SegmentFilter.star)
}
private val SLASH = "/"
sealed trait SegmentFilter{
def &&(that: => SegmentFilter): SegmentFilter = this match {
case SegmentFilter.LeaveAsIs => that
case otherwise => otherwise
}
}
object SegmentFilter {
def fromBool(b: Boolean) = b match {
case false => star
case true => LeaveAsIs
}
final case class TurnToSanitizedSymbol(symbol: String) extends SegmentFilter
case object LeaveAsIs extends SegmentFilter
val star: SegmentFilter = TurnToSanitizedSymbol("*")
}
private def classifier[F[_]](r: RequestPrelude)(segmentFilter: String => SegmentFilter): String = {
val p = r.uri.path.renderString
val uriBaseArray = p.split('/')
if (uriBaseArray.size <= 1){
SLASH
} else {
val base = uriBaseArray.drop(1)
.foldLeft(new StringBuilder("/")){ case (builder, s) =>
builder
.append(
segmentFilter(s) match {
case SegmentFilter.LeaveAsIs => s
case SegmentFilter.TurnToSanitizedSymbol(symbol) => symbol
}
)
.append(SLASH)
}
val b2 = if (p.endsWith(SLASH)) base else base.dropRight(1)
b2.result()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment