Documentation
¶
Overview ¶
Package maps wires same-origin reverse-proxies that let the SPA reach self-hosted map services (Valhalla for routing + map matching, an nginx-served PMTiles bundle for vector basemaps) through the existing rivolt origin and session cookie.
Why proxy instead of CORS-on-the-upstream:
- Most upstreams (Valhalla, the tile nginx) have no native CORS. nginx can be configured for it, but exposing each upstream behind its own ingress + cert burns hostnames for what is effectively the SPA's own data path.
- Proxying through the rivolt API keeps drive maps same-origin, reuses the existing auth middleware (routes are mounted inside the requireUser group), and lets us add per-user rate limits later without touching the cluster.
- The frontend code change shrinks to "swap base URL"; no CORS preflight handling, no second fetch credential mode.
The proxy is intentionally dumb: it forwards every request path unchanged to the upstream. Path-prefix stripping is done at mount time via http.StripPrefix in api.go, so this package only handles host rewrite and credential scrubbing.
Index ¶
Constants ¶
const ( MaxValhallaBody = 1 << 20 MaxTraceShapePoints = 2000 MaxRouteLocations = 100 )
Ceilings on one Valhalla request, so the proxy serves what the clients draw and can't be used for bulk routing. The web and the iPhone send at most 1500 trace points plus the two parked ends to /trace_route, and the planner's /route carries the origin, the destination and up to 25 charging stops.
const MaxTileResponse = 2 << 20
MaxTileResponse is the most a single tile read may carry. Real reads are a header, a directory or one tile (the largest in the 19 GB basemap is 344 KiB); 2 MiB leaves room, and anything bigger is an upstream answering something other than the byte range that was asked for.
Variables ¶
var ErrInvalidURL = errors.New("maps: base URL must include scheme and host")
ErrInvalidURL is returned when a configured base URL parses but is missing a scheme or host. Treated as fatal at startup so a typo in RIVOLT_VALHALLA_BASE_URL / RIVOLT_TILES_BASE_URL fails fast instead of silently dropping every drive map back to public CDNs.
var ErrNoRoute = errors.New("valhalla: no route found")
ErrNoRoute means Valhalla found no road route between the locations (a location in the ocean, or islands with no ferry). It is the caller's input, not a service failure.
Functions ¶
func AllowTiles ¶ added in v0.37.5
AllowTiles admits only GET/HEAD of a single top-level *.pmtiles file (Range requests are plain GETs). Directory listings, nested paths and any other file on the tile server are refused. Whatever is admitted goes through guardTiles, so a GET can only ever be answered with a bounded byte range.
func AllowValhalla ¶ added in v0.37.5
AllowValhalla admits only what the SPA uses: POST /route and POST /trace_route. Everything else (isochrone, matrix, expansion, status, any GET) is refused before it reaches Valhalla.
func LimitValhalla ¶ added in v0.38.19
LimitValhalla refuses a body over MaxValhallaBody (413), a /trace_route with more than MaxTraceShapePoints shape points or a /route with more than MaxRouteLocations locations (413), and anything the counts can't see (400): a query string (Valhalla reads a whole request from ?json=), a body that isn't one JSON object, an encoded_polyline (a polyline string holds points the count can't see), and a top-level key repeated or spelled in another case (Go's decoder and Valhalla's may pick different copies). Our clients send none of these. What passes is handed on with its body intact.
func NewProxy ¶
NewProxy builds a reverse-proxy handler that forwards to baseURL. The empty string returns (nil, nil) - callers (api.New) treat nil as "feature off" and skip mounting the route.
baseURL is typically a cluster-internal Service address ("http://valhalla.valhalla.svc.cluster.local", "http://tiles.tiles.svc.cluster.local").
Types ¶
type Route ¶ added in v0.37.0
type Route struct {
Legs []RouteLeg
}
Route is a Valhalla route through an ordered list of locations.
type RouteLeg ¶ added in v0.37.0
type RouteLeg struct {
LengthMeters float64
TimeSec float64
// Shape is the leg's road geometry as (lat, lon) pairs.
Shape [][2]float64
}
RouteLeg is one leg of a Route: from one location to the next.
type Valhalla ¶
Valhalla is a thin server-to-server client for the in-cluster Valhalla routing service. It exists alongside the same-origin reverse proxy (NewProxy in this package) — the proxy is for the SPA, this client is for backend code that wants a routing answer directly without going through the user-facing HTTP path.
Today the only consumer is the live recorder's GPS-gap fill: when the WS feed drops fixes for several seconds, we ask Valhalla what road-level path is most likely between the last good fix and the new one, and splice that shape into the drive polyline so the rendered trace doesn't contain a straight-line shortcut across whatever the car actually drove.
func NewValhalla ¶
NewValhalla returns a client pointed at baseURL. Empty baseURL returns nil — callers must nil-check and skip the feature.
func (*Valhalla) Route ¶ added in v0.37.0
Route asks Valhalla for the auto route through locs (lat, lon pairs, at least two, every one a stop so each gap is its own leg) in one request, and returns per-leg length, time and shape. It sits beside RouteShape, which stays as it is.
func (*Valhalla) RouteShape ¶
RouteShape returns the on-road shape between two points as a sequence of (lat, lon) pairs, derived from a Valhalla /route call with auto costing. Used by the recorder to fill GPS-lag gaps with a plausible road-snapped path. The returned slice INCLUDES the requested endpoints (Valhalla always echoes them as the first/last shape vertex).
The context's deadline bounds the upstream call. Callers should pass a tight timeout (a few hundred ms) — if Valhalla can't answer quickly it's better to fall back to a straight line than to delay the live recorder.