Skip to content

fix: normalize urls in stylejson payloads#42

Open
achou11 wants to merge 14 commits intomainfrom
29/transform-mapbox-style
Open

fix: normalize urls in stylejson payloads#42
achou11 wants to merge 14 commits intomainfrom
29/transform-mapbox-style

Conversation

@achou11
Copy link
Copy Markdown
Member

@achou11 achou11 commented Apr 1, 2026

Fixes #29

Mapbox style fixture is taken from here. Might consider just creating much smaller fixture that covers the properties of interest.

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 1, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​maplibre/​maplibre-gl-style-spec@​24.7.093100999770
Added@​mapbox/​mapbox-gl-style-spec@​14.21.0921009310080

View full report

@achou11
Copy link
Copy Markdown
Member Author

achou11 commented Apr 2, 2026

TODO: integrate implementation from https://github.com/digidem/mapbox-style-transformer instead of the one done here

@achou11 achou11 changed the title [WIP] fix: normalize urls in stylejson payloads fix: normalize urls in stylejson payloads Apr 6, 2026
@achou11 achou11 marked this pull request as ready for review April 6, 2026 19:03
@achou11
Copy link
Copy Markdown
Member Author

achou11 commented Apr 6, 2026

TODO: integrate implementation from https://github.com/digidem/mapbox-style-transformer instead of the one done here

@gmaclennan Haven't done this yet because the module needs to a new version released to be usable.

Comment on lines +125 to +141
// Can use `?mapbox_access_token=...` to override the access token used
// for upstream mapbox style request
if (defaultOnlineStyleUrl.toString().startsWith(BASE_MAPBOX_API_URL)) {
const accessTokenFromRequest = Array.isArray(
request.query['mapbox_access_token'],
)
? request.query['mapbox_access_token'][0]
: request.query['mapbox_access_token']

// Prioritize the access token from the request
if (accessTokenFromRequest) {
defaultOnlineStyleUrl.searchParams.set(
'access_token',
accessTokenFromRequest,
)
}
}
Copy link
Copy Markdown
Member Author

@achou11 achou11 Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this could be a useful feature to support. Still undecided on that and whether the access token in the request should be scoped to the specific use case i.e. mapbox_access_token vs access_token.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the use-case for this and I think this is potentially confusing. This is only used for the defaultOnlineStyleUrl (a static option passed to the constructor) which generally must include an ?access_token= search param if it is a mapbox URL. Having this possibly overridable and therefore also optional I think confuses the API with not a lot of benefit. We won't be using this in CoMapeo, and this is a temporary measure anyway until we move away from mapbox as the default online style, so I think we should just remove this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the situation this accounts for is when the access token you pass to the static option no longer works (because of expiry, deletion, etc) which has happened to us before 😄 being able to override it at the request level allows for workarounds in those situations without requiring new releases of the app, although that assumes that there's some client-side exposure for configuring your own access token.

but yeah, probably not worth trying to account for in this case. just trauma-based failure mode handling

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can address this risk a different way down the line.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed via 1a13856

})
}
} else {
response?.body?.cancel() // Close the connection
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this still necessary, or even placed in the right location?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only necessary if you return a 302 response without consuming the upstream response body. The code as-is now always consumes the body, so this is not necessary, however if you make the suggested changes, you will still need to do this if you do not consume the body (because it will be left hanging and the connection will remain open).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed via 787555b

Comment on lines +175 to +188
if (madeChanges) {
return new Response(JSON.stringify(body), {
status: 200,
headers: baseHeaders,
})
} else {
return new Response(null, {
status: 302,
headers: {
...baseHeaders,
location: url.toString(),
},
})
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this could make sense but maybe it's overcomplicating things. On the bright side, means I don't have to fix the existing tests 😄

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think overcomplicating things.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed via 787555b

@achou11 achou11 requested a review from gmaclennan April 6, 2026 19:07
Copy link
Copy Markdown
Member

@gmaclennan gmaclennan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this over-engineers things a bit. This is only a temporary transformation of the defaultOnlineStyleUrl until we switch to using a non-mapbox style, and it currently adds quite a few extra code paths to the code that need testing and maintaining, and a new feature of making the access token optional on the defaultOnlineStyleUrl and possibly overridable from the API. This seems to be moving towards a broader long-term support of mapbox styles in this package, which I don't think is needed at this stage, and we may not ever do.

Comment on lines +125 to +141
// Can use `?mapbox_access_token=...` to override the access token used
// for upstream mapbox style request
if (defaultOnlineStyleUrl.toString().startsWith(BASE_MAPBOX_API_URL)) {
const accessTokenFromRequest = Array.isArray(
request.query['mapbox_access_token'],
)
? request.query['mapbox_access_token'][0]
: request.query['mapbox_access_token']

// Prioritize the access token from the request
if (accessTokenFromRequest) {
defaultOnlineStyleUrl.searchParams.set(
'access_token',
accessTokenFromRequest,
)
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the use-case for this and I think this is potentially confusing. This is only used for the defaultOnlineStyleUrl (a static option passed to the constructor) which generally must include an ?access_token= search param if it is a mapbox URL. Having this possibly overridable and therefore also optional I think confuses the API with not a lot of benefit. We won't be using this in CoMapeo, and this is a temporary measure anyway until we move away from mapbox as the default online style, so I think we should just remove this.

Comment on lines 163 to 168
const body = await response.json()

const madeChanges = transformUrls(body, {
accessToken:
defaultOnlineStyleUrl.searchParams.get('access_token') || undefined,
})
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This unnecessarily loads the body of all style requests, when we only need to do it for the default online style URL. Also I don't think we need to load the body for non-mapbox styles. Currently the "is it a mapbox style" question is done by checking whether the transormUrls() funciton returns true. I think the detection used above (does the defaultOnlineStyleUrl start with BASE_MAPBOX_API_URL) is better, and that way we don't need to load the body of requests for non-mapbox styles

Copy link
Copy Markdown
Member Author

@achou11 achou11 Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense. based on that, then the more desirable behavior is the following?

  • for non-mapbox styles, there's no need to load the body and we keep the existing redirect behavior

  • for mapbox styles, we load the body, attempt to tranform, and provide a 200 response with the maybe-transformed body? basically, remove the conditional response type based on whether any transforms were actually made

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the detection used above (does the defaultOnlineStyleUrl start with BASE_MAPBOX_API_URL) is better

Just noting that doing this wouldn't account for online style urls whose payloads include fields that reference mapbox using their URIs. definitely an edge case but just highlighting that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I can't think of a situation where someone would choose to host a style that references MapBox resources somewhere other than MapBox, and in any case we are only really handling the case of our current default map tiles

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense. based on that, then the more desirable behavior is the following?

  • for non-mapbox styles, there's no need to load the body and we keep the existing redirect behavior

  • for mapbox styles, we load the body, attempt to tranform, and provide a 200 response with the maybe-transformed body? basically, remove the conditional response type based on whether any transforms were actually made

Yes

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed via 787555b

Comment on lines +175 to +188
if (madeChanges) {
return new Response(JSON.stringify(body), {
status: 200,
headers: baseHeaders,
})
} else {
return new Response(null, {
status: 302,
headers: {
...baseHeaders,
location: url.toString(),
},
})
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think overcomplicating things.

})
}
} else {
response?.body?.cancel() // Close the connection
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only necessary if you return a 302 response without consuming the upstream response body. The code as-is now always consumes the body, so this is not necessary, however if you make the suggested changes, you will still need to do this if you do not consume the body (because it will be left hanging and the connection will remain open).

Comment on lines +125 to +141
// Can use `?mapbox_access_token=...` to override the access token used
// for upstream mapbox style request
if (defaultOnlineStyleUrl.toString().startsWith(BASE_MAPBOX_API_URL)) {
const accessTokenFromRequest = Array.isArray(
request.query['mapbox_access_token'],
)
? request.query['mapbox_access_token'][0]
: request.query['mapbox_access_token']

// Prioritize the access token from the request
if (accessTokenFromRequest) {
defaultOnlineStyleUrl.searchParams.set(
'access_token',
accessTokenFromRequest,
)
}
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed via 1a13856

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guess this file wasn't updated to be formatted according to the prettier config?

@achou11 achou11 requested a review from gmaclennan April 8, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

transform custom url schemes in style json before returning it

2 participants