Skip to content

transformRequest headers ignored for Model resources #13723

Description

@alihaider1998

mapbox-gl-js version

v3.29.0

Browser and version

All browsers (Chrome, Firefox, Safari) - tested on Chrome 151.0.7922.175

Expected behavior

The transformRequest callback should apply custom headers to Model (GLTF/GLB) resource requests, just like it does for all other resource types (tiles, images, sprites, glyphs, etc.).

When a user returns headers from transformRequest for a Model resource, those headers should be included in the HTTP request.

Actual behavior

The transformRequest callback IS called for Model resources, but the returned headers are completely ignored. Only the URL is used, and the request is made without any custom headers.

This is inconsistent with how all other resource types behave, where headers are correctly applied.

Link to the demonstration

N/A - Bug is in library internals (loadGLTF function). Code analysis and reproduction steps provided below.

Steps to trigger the unexpected behavior

  1. Create a map with a transformRequest callback that adds authentication headers:
const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/standard',
  transformRequest: (url, resourceType) => {
    console.log('Transform request:', resourceType, url);

    if (resourceType === 'Model') {
      return {
        url: url,
        headers: { 'Authorization': 'Bearer my-secret-token' }
      };
    }
    return { url };
  }
});
  1. Add a model layer that loads from a server requiring authentication:
map.on('style.load', () => {
  map.addSource('my-model', {
    type: 'model',
    models: {
      'my-model-id': 'https://my-server.com/model.glb'
    }
  });

  map.addLayer({
    id: 'model-layer',
    type: 'model',
    source: 'my-model',
    paint: { 'model-id': 'my-model-id' }
  });
});
  1. Check the network request in DevTools - the Authorization header will be missing despite being returned from transformRequest

Root Cause

Bug is in loadGLTFFromURI (line ~53548 in dist/mapbox-gl-dev.js):

async loadGLTFFromURI(uri, signal) {
  const request = await this.map._requestManager.transformRequest(uri, ResourceType.Model, signal);
  return loadGLTF(request.url, signal);  // Only passes URL, discards headers
}

And loadGLTF (line ~38356):

async function loadGLTF(url, signal) {
  const { data: buffer } = await getArrayBuffer({ url }, signal);  // Creates new object with only URL
  return decodeGLTF(buffer, 0, url, signal);
}

Compare with correct implementation for Images:

const request = await this._requestManager.transformRequest(url, ResourceType.Image);
const { data } = await getImage(request);  // Passes full request object with headers

Proposed Fix

async loadGLTFFromURI(uri, signal) {
  const request = await this.map._requestManager.transformRequest(uri, ResourceType.Model, signal);
  return loadGLTF(request, signal);  // Pass full request object
}

async function loadGLTF(requestParameters, signal) {
  const { data: buffer } = await getArrayBuffer(requestParameters, signal);  // Use full request
  return decodeGLTF(buffer, 0, requestParameters.url, signal);
}

Relevant log output

Console output shows transformRequest is called:
Transform request: Model https://my-server.com/model.glb

Network tab in DevTools shows the request is made WITHOUT the Authorization header:

Request URL: https://my-server.com/model.glb
Request Method: GET
Status: 401 Unauthorized (if server requires auth)

Expected header is missing:
Authorization: Bearer my-secret-token

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions