BaseUri name is misleading — overloaded as path-prefix and as URL across consumers #32
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/support#32
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
works.iterative.tapir.BaseUricarries two different semantics depending on which iw-supportconsumer reads it, and the type signature (
case class BaseUri(value: Option[Uri])) doesn'tdistinguish them. The current name promises a URL; some consumers treat it as one, others as a
mount-path prefix. This is the root cause behind the Pac4j composition bug discussed in #31
(closed).
How each consumer interprets it
BlazeHttpServer.withBaseUriserver/http/.../impl/blaze/BlazeHttpServer.scala:13-16Router(u.toString -> routes)— concatenated as a path)ViteSupport.withBaseUriserver/http/.../ViteSupport.scala:43,96Pac4jConfigFactory(0.1.15+)server/http/.../impl/pac4j/Pac4jConfigFactory.scala:34,43urlBase + baseUri.toString + callbackBase + "/callback"and used as cookiePathattributeConsulKeyValueStorehashicorp/jvm/.../ConsulKeyValueStore.scala:62BaseUri(addr))fromLocationtapir/js/.../BaseUriPlatformSpecific.scala:6,13window.location)LiveClientEndpointFactory.defaulttapir/shared/.../LiveClientEndpointFactory.scala:56,61Why this is a bug-attractor
A natural-looking usage:
compiles cleanly (the
Stringconstructor onBaseUriaccepts anythingsttp.model.uri""canparse) but produces a malformed URL at runtime.
Pac4jConfigFactorycomposesurlBase + baseUri.toString + callbackBase + "/callback"→ for the example above,"https://app.example.comhttps://app.example.com/auth/oidc/callback". The same value alsobecomes the session-cookie
Pathattribute (Path=https://app.example.com).The original Phase 2 implementer of platform PLATFORM-210 hit this exact trap — the parameter is
called
baseUri, the type accepts aString, so passing the public URL felt like the rightthing. Existing iw-support projects don't hit it because they either leave
BASEURIunset(
BaseUri(None)→ fold returns"/"→ composition works modulo a tolerable double slash) orset it to a literal mount path like
/admin.Suggested fix
Two reasonable directions:
Rename to match the semantic.
BaseUri→BasePath(orMountPath) for the HTTP-serverstack consumers. The type stays
case class BasePath(value: Option[Uri])but the nameforbids the URL interpretation at the call site.
Split into two types. Introduce a separate
PublicOrigin(orOrigin) concept for thepublic-URL consumers (
ConsulKeyValueStore, Scala.jsfromLocation, tapir client factory).Each consumer takes the type that matches its intent.
Option 2 is structurally cleaner but ripples through more call sites and downstream apps.
Option 1 is a low-impact rename that closes the most common pitfall.
A
BasePath.fromStringsmart constructor that rejects values containing://would also help— it would have caught the platform bug at construction time. With the current
BaseUri(String)constructor accepting any input, the type system is too permissive.
Context
BaseUrishape at thefactory boundary and removing
urlBasefromPac4jSecurityConfig— operating on thehypothesis that
BaseUriwas the canonical public-URL source. Empirical wiring proved thatwas wrong: setting
BASEURI=http://localhost:8090to satisfy Pac4j causedBlazeHttpServer.withBaseUrito mount routes under/http://localhost:8090/*. The twoconsumers genuinely want different things.
urlBaseinPac4jSecurityConfig, readBaseUri.configfrom env with the path semantic, and neverconstruct
BaseUri(cfg.urlBase). That works against unmodified iw-support 0.1.15 — but theunderlying API trap remains.
Out of scope for this issue
The Pac4j-specific URL/cookie composition is correctly handled today provided callers respect
the unwritten "BaseUri is a path" contract. That's the safety-on-paper status quo this issue is
asking to make explicit through naming.