MapLibre React Native AddCustomheader («Authorization», «Носитель…») не прилагается к запросам векторной плитки в сборкаIOS

Программируем под IOS
Ответить
Anonymous
 MapLibre React Native AddCustomheader («Authorization», «Носитель…») не прилагается к запросам векторной плитки в сборка

Сообщение Anonymous »

Я работаю над приложением React Native и должен отобразить некоторые векторные плитки. Вот почему я использую библиотеку Map-Libre для Nate Native. It was working fine on iOS until now, but it suddenly stopped working, and I can't figure out why.
The only thing I can think of is that we recently changed the server's SSL certificate because the intermediate certificate was missing, and the vector tiles weren't working on Android because the system didn't trust the server.
Summary
On iOS, while developing locally (

Код: Выделить всё

npx expo run:ios
) Карта загружается правильно, и мой API получает авторизацию: Заголовок по всем запросам векторной плитки.

После распределения того же кода через Testflight (выпустить сборку), точно тот же стиль прекращает получение заголовка токена на стороне сервера и векторные Tiles Fail (401/403). Нет изменений в стиле/коде между Dev и Tf.
Это только влияет на запросы плитки (…/{z}/{x}/{y} .pbf запросы). Другие выборы, которые я делаю в приложении (Axios Prear), включают в себя штраф за заголовка. It looks like the header set via @maplibre/maplibre-react-native is either not attached or gets lost in release.
Environment
  • @maplibre/maplibre-react-native: 10.2.0
  • React Native: 0.81.4
  • expo : 54.0.10 (управляемый рабочий процесс, предварительно присутствует из -за выставки: ios ), построенный с eas
  • ios : 26 (воспроизводился на iPhone 14 Pro/ios 26)
    : 26 (воспроизводился на iPhone 14 Pro/ios Distribution : testflight (App Store Connect), выпуск сборки (без изменений кода с локального)
  • server : https (допустимый сертификат), Custom Koop/Arcgis Backend ожидание авторизации: Bearer

только -это пропущенный заголовок авторизации по запросам плитки в tf.

минимальный стиль (векторные источники)

Код: Выделить всё

{
"version": 8,
"sources": {
"countries": {
"type": "vector",
"tiles": [
"https://:8446/boundaries/rest/services/IPCERT/countries/VectorTileServer/{z}/{x}/{y}.pbf"
],
"minzoom": 0,
"maxzoom": 6
},
"provinces": {
"type": "vector",
"tiles": [
"https://:8446/boundaries/rest/services/IPCERT/provinces/VectorTileServer/{z}/{x}/{y}.pbf"
],
"minzoom": 4.5,
"maxzoom": 9
},
"municipalities": {
"type": "vector",
"tiles": [
"https://:8446/boundaries/rest/services/IPCERT/municipalities/VectorTileServer/{z}/{x}/{y}.pbf"
],
"minzoom": 7.5
}
},
"layers": [
{ "id": "countries", "type": "fill", "source": "countries" },
{ "id": "provinces", "type": "fill", "source": "provinces" },
{
"id": "municipalities",
"type": "fill",
"source": "municipalities"
}
]
}
< /code>
 код для установки заголовка (минимальный) < /h2>
// useMapAuthHeader.ts
import { useEffect, useState } from "react";
import { AppState } from "react-native";
import {
addCustomHeader,
removeCustomHeader,
} from "@maplibre/maplibre-react-native";
import { useAuth } from "@/Context/AuthContext";

const HEADER_NAME = "Authorization";

export function useMapAuthHeader() {
const { token } = useAuth();
const [isAuthReady, setIsAuthReady] = useState(false);
useEffect(() => {
try {
removeCustomHeader(HEADER_NAME);
if (token) {
addCustomHeader(HEADER_NAME, `Bearer ${token}`);
setIsAuthReady(true);
}
} catch {}
return () => {
try {
removeCustomHeader(HEADER_NAME);
} catch {}
};
}, [token]);

// Re-apply on foreground (iOS can recreate sessions)
useEffect(() => {
const sub = AppState.addEventListener("change", (s) => {
if (s === "active" && token) {
try {
removeCustomHeader(HEADER_NAME);
addCustomHeader(HEADER_NAME, `Bearer ${token}`);
} catch {}
}
});
return () => sub.remove();
}, [token]);
return { isAuthReady };
}
Guardse Guards Guards
i gate. На практике это задерживает любую сеть MapView до настройки заголовка Auth.

Код: Выделить всё

// Pseudocode of the guards I have around MapView mount
const { combinedMapStyle, isMapStyleReady } = useMapStyle();
const { isAuthReady } = useMapAuthHeader();
const { prewarmDone } = useKoopPrewarm(isMapStyleReady, combinedMapStyle);

if (!isMapStyleReady || !prewarmDone || !isAuthReady) {
return ; // avoid mounting MapView until ready
}
return ;
Even with these guards (and verifying the header was applied before mounting), TestFlight builds still produce tile requests without the Authorization header on the server side.
Prewarm behavior (works with header)
To reduce backend pressure I “prewarm” Koop by fetching one плитка на источник через axios с таким же токеном. These prewarm calls reach the server with Authorization: Bearer … both locally and in TestFlight, and succeed (200/204 no content).

Only MapLibre tile requests in TestFlight are missing the header.
Snippet (simplified):

Код: Выделить всё

await api.get(tileUrl, {
responseType: "arraybuffer",
transformResponse: [],
// axios has Authorization header through my API client interceptors
});
Переписывание стиля выполнения (параметры запросов)
В условиях выполнения I переписывает URL-адреса источников для добавления серверных фильтров (например,? Lspaisids = [123] ,? Это влияет только на строку запроса , а не хост.

Это переписывание не связано с задачей заголовка: локально (dev) Сервер по -прежнему видит авторизацию независимо от дополнительных параметров запроса; В TestFlight заголовок отсутствует, даже если я полностью отключаю переписывание. class = "Lang-Swift PrettyPrint-Override">

Код: Выделить всё

import Expo
import React
import ReactAppDependencyProvider

@UIApplicationMain
public class AppDelegate: ExpoAppDelegate {
var window: UIWindow?

var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
var reactNativeFactory: RCTReactNativeFactory?

public override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
let delegate = ReactNativeDelegate()
let factory = ExpoReactNativeFactory(delegate: delegate)
delegate.dependencyProvider = RCTAppDependencyProvider()

reactNativeDelegate = delegate
reactNativeFactory = factory
bindReactNativeFactory(factory)

#if os(iOS) || os(tvOS)
window = UIWindow(frame: UIScreen.main.bounds)
// Initialize MapLibre custom headers (restored)
MLRNCustomHeaders().initHeaders()
MLRNCustomHeaders().addHeader("sECrEt", forHeaderName: "Authorization")
factory.startReactNative(
withModuleName: "main",
in: window,
launchOptions: launchOptions)
#endif

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

// Linking API
public override func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
return super.application(app, open: url, options: options) || RCTLinkingManager.application(app, open: url, options: options)
}

// Universal Links
public override func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
}
}

class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
// Extension point for config-plugins

override func sourceURL(for bridge: RCTBridge) -> URL? {
// needed to return the correct URL for expo-dev-client.
bridge.bundleURL ?? bundleURL()
}

override func bundleURL() -> URL? {
#if DEBUG
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
#else
return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
}
}
< /code>
Специально эти строки предназначены для того, чтобы гарантировать, что пользовательские заголовки доступны в приложении: < /p>
MLRNCustomHeaders().initHeaders()
MLRNCustomHeaders().addHeader("sECrEt", forHeaderName: "Authorization")
i не импортируйте mlrncustomheaders в верхней части Appdelegate.swift , потому что он не смог компилироваться, если импортируется напрямую. Вместо этого я создал мостовой заголовок Globalipcert Bridging-header.h с:

Код: Выделить всё

//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "MLRNCustomHeaders.h"
С помощью этой настройки приложение скомпилировано и используется для работы ; Недавно, не изменяя этот собственный код, строительство TestFlight прекратила отправку запросов Authorization на Maplibre tile , пока локальный разработчик все еще работает. Альфа , но я даже не мог собрать, потому что вызовы:

Код: Выделить всё

MLRNCustomHeaders().initHeaders()
MLRNCustomHeaders().addHeader("sECrEt", forHeaderName: "Authorization")
< /code>
не были признаны в моем Swift AppDelegate. Я не был уверен, как заменить или перенести эту логику в V11, поэтому я остался на V10.2.0. или пример кода? Короткий фрагмент или ссылка DOCS поможет мне повторно испытать V11. < /P>
Эта проблема компиляции /миграции отделена от текущей проблемы:
отсутствующий заголовок авторизации в Testflight IOS происходит на V10.2.0 с кодом, который в противном случае работает нормально. Приложение локально с NPX Expo Run: ios 
(отладка/выпуск локально).

✅ tiles загружать и бэкэнд журналы Покажите авторизация: носитель… для All/ Stress> in ios> in ios> in ios> in ios> in ios> in ios> in ios> in ios> in ios> in ios> in ios> in ios> in ios> in in in in in refress maplibre. Builds.
[*] Любые известные различия между отладкой и выпуском, которые влияют на пользовательские заголовки для запросов плитки. iOS code headers are attached so I can open a PR.
[/list]
Workarounds
  • I can “prewarm” the Koop cache using Axios with auth to reduce load, but this doesn’t fix the missing header on MapLibre tile fetches themselves.
Дополнительные заметки < /h2>
  • Источники стиля иногда переписываются во время выполнения для добавления параметров запросов (например,? lspaisids = [123] < /code>). Это не меняется, появляется ли заголовок на стороне сервера; Только Testflight против локального составляет разницу.

    Код: Выделить всё

    addCustomHeader('Authorization', 'Bearer …')
    работает локально, но заголовок исчезает в ios testflight [/b] только для запросов на векторную плитку . Похоже, что заголовки, установленные через глобальный API, не применяются к выбросам плитки в выпуске.
    @maplibre/maplibre-react-national версия
    визу. Это происходит?

    Код: Выделить всё

    expo-env-info 2.0.7 environment info:
    System:
    OS: macOS 15.4.1
    Shell: 5.9 - /bin/zsh
    Binaries:
    Node: 22.18.0 - ~/.nvm/versions/node/v22.18.0/bin/node
    Yarn: 1.22.22 - /usr/local/bin/yarn
    npm: 10.9.3 - ~/.nvm/versions/node/v22.18.0/bin/npm
    Watchman: 2025.03.10.00 - /usr/local/bin/watchman
    Managers:
    CocoaPods: 1.16.2 - /usr/local/bin/pod
    SDKs:
    iOS SDK:
    Platforms: DriverKit 24.5, iOS 18.5, macOS 15.5, tvOS 18.5, visionOS 2.5, watchOS 11.5
    IDEs:
    Android Studio: 2024.3 AI-243.24978.46.2431.13208083
    Xcode: 16.4/16F6 - /usr/bin/xcodebuild
    npmPackages:
    expo: 54.0.10 => 54.0.10
    expo-router: ~6.0.8 => 6.0.8
    expo-updates: ~29.0.11 => 29.0.11
    react: 19.1.0 => 19.1.0
    react-dom: 19.1.0 => 19.1.0
    react-native: 0.81.4 => 0.81.4
    react-native-web: ^0.21.0 => 0.21.1
    npmGlobalPackages:
    eas-cli: 16.19.3
    expo-cli: 6.3.12
    Expo Workflow: bare
    
    Что вы попробовали?

    Код: Выделить всё

    addCustomHeader("Authorization", "Bearer ")
    (также попробовал ключ нижней части).
  • Удал и заново добавил заголовок на переднем плане приложения/фон через AppState .
  • Задержка монтажа До тех пор, пока заголовок Auth, Style и Prewarm не стали готовыми. retrought).
  • Отключенный URL -сигнал отключения URL -адреса выполнения (PARAMS PARMAS), чтобы исключить его. Mlrncustomheaders (). Initheaders () и .addheader (...) .
  • Создано и протестирован с точно таким же кодом локально (

    Код: Выделить всё

    npx expo run:ios
    ) и через Testflight (eas).
чего вы ожидали? и в создании выпуска Testflight.>

Подробнее здесь: https://stackoverflow.com/questions/797 ... not-attach
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»