How to get postgrest, postgis, and maplibre to cooperate and use geojson

Postgrest has a really snazzy feature where you can set the 'Accept: application/geo+json' header to get your results as geojson instead of simple rows.

And Maplibre has a handy function where you can pass in a request transformer to alter all your requests to a source, like this:

function customRequestTransformer(url: string): RequestParameters {     
    const params = {
      url: url,
      headers: {
        Authorization: `Bearer ${user.access_token}`,
        Accept: 'application/geo+json',
      },
    }
    return params;
  }



<Map
	....
	transformRequest={customRequestTransformer}
>

But if you do that, you'll see that your Authorization header is added, BUT your Accept one is not. Arrgg!

Annnnd I wrote the below while I was trying to find a fix, but instead I just wrote the fix and pushed it upstream at https://github.com/maplibre/maplibre-gl-js/pull/4210 . Enjoy! The next release of Maplibre-gl-js will work properly with Postgrest now.

Open source is great.

(Below, if anyone is curious)


The culprit is here: https://github.com/maplibre/maplibre-gl-js/blob/68569cf22655c53bc474504bf07893709723f7d6/src/util/ajax.ts#L154

    if (requestParameters.type === 'json') {
        request.headers.set('Accept', 'application/json');
    }

and then, here

https://github.com/maplibre/maplibre-gl-js/blob/68569cf22655c53bc474504bf07893709723f7d6/src/util/ajax.ts#L255

export const getJSON = <T>(requestParameters: RequestParameters, abortController: AbortController): Promise<{data: T} & ExpiryData> => {
    return makeRequest(extend(requestParameters, {type: 'json'}), abortController);
};

and finally, here: https://github.com/maplibre/maplibre-gl-js/blob/68569cf22655c53bc474504bf07893709723f7d6/src/source/geojson_worker_source.ts#L220

async loadGeoJSON(params: LoadGeoJSONParameters, abortController: AbortController): Promise<GeoJSON.GeoJSON> {
        const {promoteId} = params;
        if (params.request) {
            const response = await getJSON<GeoJSON.GeoJSON>(params.request, abortController);

So loadGeoJSON calls getJSON, which always sets type: 'json', which means our final request nukes whatever request headers we had set.