Created
July 10, 2023 14:43
-
-
Save ChristopherDavenport/071b86c843ab4a03e9c4f398c4eaab76 to your computer and use it in GitHub Desktop.
Segment Allow List Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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