fix(Maps): ensure asset urls resolve correctly

This commit is contained in:
Jake Turner 2026-02-03 23:32:01 -08:00
parent ab07551719
commit 576e5b65f1
No known key found for this signature in database
GPG Key ID: D11724A09ED19E59
2 changed files with 15 additions and 9 deletions

View File

@ -69,7 +69,7 @@ export default class MapsController {
return await this.mapService.listRegions() return await this.mapService.listRegions()
} }
async styles({ response }: HttpContext) { async styles({ request, response }: HttpContext) {
// Automatically ensure base assets are present before generating styles // Automatically ensure base assets are present before generating styles
const baseAssetsExist = await this.mapService.ensureBaseAssets() const baseAssetsExist = await this.mapService.ensureBaseAssets()
if (!baseAssetsExist) { if (!baseAssetsExist) {
@ -79,7 +79,7 @@ export default class MapsController {
}) })
} }
const styles = await this.mapService.generateStylesJSON() const styles = await this.mapService.generateStylesJSON(request.host())
return response.json(styles) return response.json(styles)
} }

View File

@ -234,7 +234,7 @@ export class MapService implements IMapService {
} }
} }
async generateStylesJSON() { async generateStylesJSON(host: string | null = null): Promise<BaseStylesFile> {
if (!(await this.checkBaseAssetsExist())) { if (!(await this.checkBaseAssetsExist())) {
throw new Error('Base map assets are missing from storage/maps') throw new Error('Base map assets are missing from storage/maps')
} }
@ -248,9 +248,15 @@ export class MapService implements IMapService {
const rawStyles = JSON.parse(baseStyle.toString()) as BaseStylesFile const rawStyles = JSON.parse(baseStyle.toString()) as BaseStylesFile
const regions = (await this.listRegions()).files const regions = (await this.listRegions()).files
const sources = this.generateSourcesArray(regions)
const baseUrl = this.getPublicFileBaseUrl(this.basemapsAssetsDir) /** If we have the host, use it to build public URLs, otherwise we'll fallback to defaults
* This is mainly useful because we need to know what host the user is accessing from in order to
* properly generate URLs in the styles file
* e.g. user is accessing from "example.com", but we would by default generate "localhost:8080/..." so maps would
* fail to load.
*/
const sources = this.generateSourcesArray(host, regions)
const baseUrl = this.getPublicFileBaseUrl(host, this.basemapsAssetsDir)
const styles = await this.generateStylesFile( const styles = await this.generateStylesFile(
rawStyles, rawStyles,
@ -341,9 +347,9 @@ export class MapService implements IMapService {
return await listDirectoryContentsRecursive(this.baseDirPath) return await listDirectoryContentsRecursive(this.baseDirPath)
} }
private generateSourcesArray(regions: FileEntry[]): BaseStylesFile['sources'][] { private generateSourcesArray(host: string | null, regions: FileEntry[]): BaseStylesFile['sources'][] {
const sources: BaseStylesFile['sources'][] = [] const sources: BaseStylesFile['sources'][] = []
const baseUrl = this.getPublicFileBaseUrl('pmtiles') const baseUrl = this.getPublicFileBaseUrl(host, 'pmtiles')
for (const region of regions) { for (const region of regions) {
if (region.type === 'file' && region.name.endsWith('.pmtiles')) { if (region.type === 'file' && region.name.endsWith('.pmtiles')) {
@ -414,7 +420,7 @@ export class MapService implements IMapService {
/* /*
* Gets the appropriate public URL for a map asset depending on environment * Gets the appropriate public URL for a map asset depending on environment
*/ */
private getPublicFileBaseUrl(childPath: string): string { private getPublicFileBaseUrl(specifiedHost: string | null, childPath: string): string {
function getHost() { function getHost() {
try { try {
const localUrlRaw = env.get('URL') const localUrlRaw = env.get('URL')
@ -427,7 +433,7 @@ export class MapService implements IMapService {
} }
} }
const host = getHost() const host = specifiedHost || getHost()
const withProtocol = host.startsWith('http') ? host : `http://${host}` const withProtocol = host.startsWith('http') ? host : `http://${host}`
const baseUrlPath = const baseUrlPath =
process.env.NODE_ENV === 'production' ? childPath : urlJoin(this.mapStoragePath, childPath) process.env.NODE_ENV === 'production' ? childPath : urlJoin(this.mapStoragePath, childPath)