Skip to content

fix: normalize urls in stylejson payloads#42

Merged
achou11 merged 15 commits intomainfrom
29/transform-mapbox-style
Apr 13, 2026
Merged

fix: normalize urls in stylejson payloads#42
achou11 merged 15 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

Comment thread src/lib/style.ts
Comment thread src/lib/style.ts
@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 thread src/routes/maps.ts Outdated
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

Comment thread src/routes/maps.ts Outdated
})
}
} 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 thread src/routes/maps.ts Outdated
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 thread src/routes/maps.ts Outdated
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 thread src/routes/maps.ts Outdated
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 thread src/routes/maps.ts Outdated
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.

Comment thread src/routes/maps.ts Outdated
})
}
} 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 thread src/routes/maps.ts Outdated
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

Comment thread package.json
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
@gmaclennan
Copy link
Copy Markdown
Member

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.

I think it's probably fine to just have this code here, duplicated. It's pretty simple code.

@achou11 achou11 merged commit 9f44c41 into main Apr 13, 2026
20 of 22 checks passed
@achou11 achou11 deleted the 29/transform-mapbox-style branch April 13, 2026 15:12
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (581ba0f) to head (ad359d6).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@    Coverage Diff     @@
##   main   #42   +/-   ##
==========================
==========================

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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