Partilhar via


Quickstart: Construa uma aplicação web com o Microsoft Planetary Computer Pro

Neste quickstart, constrói uma aplicação web que apresenta imagens de satélite e dados geoespaciais do seu GeoCatálogo num mapa interativo. Autentica os utilizadores com o Microsoft Entra ID, consulta coleções STAC e renderiza blocos de mapas — tudo a partir do JavaScript do navegador.

O que aprende:

  • Autentique utilizadores e adquira tokens de acesso usando MSAL.js
  • Consulte a API STAC para descobrir coleções e itens
  • Mostrar blocos raster num mapa MapLibre GL com cabeçalhos de autorização
  • Crie camadas de mosaico sem costuras ao longo de coleções inteiras
  • Descarregue ativos brutos usando tokens SAS

Os padrões de código funcionam com qualquer framework JavaScript moderno (React, Vue, Angular) ou JavaScript simples. As APIs do GeoCatalog têm suporte total para CORS, por isso podê-las chamar diretamente de localhost durante o desenvolvimento — sem necessidade de proxy.

Pode descarregar e testar este código a partir do repositório público do Microsoft Planetary Computer Pro no GitHub.

Pré-requisitos

Visão geral da arquitetura

Uma aplicação web típica do GeoCatalog segue esta arquitetura:

Diagrama que mostra a arquitetura de uma aplicação web GeoCatalog com um cliente navegador ligado ao Microsoft Entra ID para autenticação e às APIs GeoCatalog para acesso a dados.

Registe a sua candidatura no Microsoft Entra ID

Antes de a sua aplicação web autenticar utilizadores, registe-a no Microsoft Entra ID. Este início rápido utiliza um registo de Aplicação de Página Única (SPA ), ideal para aplicações JavaScript do lado do cliente e desenvolvimento local. Os padrões de integração da API apresentados em etapas posteriores funcionam com qualquer tipo de aplicação.

Observação

Para aplicações de produção com servidor backend, considere escolher um tipo de registo diferente (Web, Nativo, etc.). Consulte Configurar autenticação de aplicações para orientações sobre como escolher a abordagem certa para o seu cenário.

Registar como uma aplicação de página única

  1. Vá ao Microsoft Entra ID no portal Azure.
  2. Selecione registos de aplicações no painel lateral.
  3. Selecione Novo registo.
  4. Insira um nome para a sua candidatura (por exemplo, "GeoCatalog Web App").
  5. Em Tipos de conta suportados, selecione Contas somente neste diretório organizacional.
  6. Em Redirecionar URI, selecione Aplicação de página única (SPA) e introduza o seu URL de desenvolvimento (por exemplo, http://localhost:5173).
  7. Selecione Register.

Após o registo, note os seguintes valores da página de Visão Geral :

  • ID do aplicativo (cliente)
  • ID da diretoria (tenant)

Para mais informações, consulte o registo na aplicação de início rápido.

Conceder permissões API

A sua aplicação precisa de permissão para chamar a API GeoCatalog em nome dos utilizadores com sessão iniciada:

  1. No registo da sua aplicação, selecione permissões API Adicionar>uma permissão.
  2. Seleciona as APIs que a minha organização usa e pesquisa por Azure Orbital Spatio.
  3. Selecione permissões delegadas e verifique user_impersonation.
  4. Selecione Adicionar permissões.
  5. Se for administrador, selecione Conceder consentimento de administrador em nome de todos os utilizadores do seu inquilino.

Configure a sua aplicação

A sua aplicação precisa dos seguintes valores de configuração. A forma como fornece estes valores depende das suas ferramentas de construção (variáveis de ambiente, ficheiros de configuração, e assim por diante):

Configuração Valor Description
URL do catálogo https://{name}.{region}.geocatalog.spatio.azure.com O seu endpoint GeoCatalog
ID do inquilino A partir do registo da aplicação O seu inquilino Microsoft Entra
ID do Cliente A partir do registo da aplicação ID de cliente da sua aplicação
Âmbito API https://geocatalog.spatio.azure.com/.default Use sempre este valor exato

Instalar dependências

Instale a Microsoft Authentication Library (MSAL) para aplicações de navegador e uma biblioteca de mapas:

npm install @azure/msal-browser maplibre-gl
  • @azure/msal-browser - Gere a autenticação OAuth 2.0 com a Microsoft Entra ID
  • maplibre-gl - Biblioteca de mapas open source para visualização de mosaicos

Sugestão

Estrutura do projeto: Os exemplos de código neste quickstart são funções autónomas que podes organizar como preferires. Um padrão comum:

  • auth.js: Configuração MSAL e funções de token
  • api.js: Funções de STAC API, Tiler API e SAS token
  • map.js: A inicialização do MapLibre e a gestão da camada de mosaicos
  • App.js ou main.js: Conecta tudo à tua interface de utilizador

Cada função recebe as suas dependências (tokens de acesso, URLs) como parâmetros, tornando-as fáceis de integrar em qualquer framework ou estrutura de projeto.

Implementar autenticação MSAL

Captura de ecrã que mostra o fluxo de autenticação numa aplicação web de exemplo.

Configure o MSAL para autenticação do navegador. O exemplo seguinte mostra a configuração da chave e o padrão de aquisição de tokens:

import { PublicClientApplication, InteractionRequiredAuthError } from '@azure/msal-browser';

// Configuration - replace with your values or load from environment/config
const msalConfig = {
  auth: {
    clientId: 'YOUR_CLIENT_ID',
    authority: 'https://login.microsoftonline.com/YOUR_TENANT_ID',
    redirectUri: window.location.origin,
  },
  cache: {
    cacheLocation: 'sessionStorage',
    storeAuthStateInCookie: false,
  },
};

// Create MSAL instance
const msalInstance = new PublicClientApplication(msalConfig);

// GeoCatalog API scope - always use this exact value
const scopes = ['https://geocatalog.spatio.azure.com/.default'];

/**
 * Acquire an access token for GeoCatalog API calls.
 * Tries silent acquisition first, falls back to popup if needed.
 */
async function getAccessToken() {
  const account = msalInstance.getActiveAccount() || msalInstance.getAllAccounts()[0];
  
  if (!account) {
    throw new Error('No authenticated account. Call login() first.');
  }

  try {
    // Try silent token acquisition (uses cached token)
    const result = await msalInstance.acquireTokenSilent({ account, scopes });
    return result.accessToken;
  } catch (error) {
    // If silent fails (token expired), fall back to popup
    if (error instanceof InteractionRequiredAuthError) {
      const result = await msalInstance.acquireTokenPopup({ scopes });
      return result.accessToken;
    }
    throw error;
  }
}

/**
 * Sign in the user via popup.
 */
async function login() {
  const result = await msalInstance.loginPopup({ scopes });
  msalInstance.setActiveAccount(result.account);
  return result.account;
}

/**
 * Sign out the user.
 */
function logout() {
  msalInstance.logoutPopup();
}

API STAC: Consultar coleções e itens

A API STAC do GeoCatalog fornece pontos finais para descobrir e consultar dados geoespaciais. Todos os pedidos requerem um Authorization cabeçalho com um token Bearer obtido através da Implementar a autenticação MSAL.

Listar coleções

Captura de ecrã que mostra a lista de coleções STAC numa aplicação web de exemplo.

const API_VERSION = '2025-04-30-preview';

async function listCollections(accessToken, catalogUrl) {
  const url = `${catalogUrl}/stac/collections?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
    },
  });
  
  if (!response.ok) {
    throw new Error(`Failed to list collections: ${response.statusText}`);
  }
  
  const data = await response.json();
  return data.collections; // Array of STAC Collection objects
}

Lista de itens numa coleção

Captura de ecrã que mostra a lista de itens STAC numa aplicação web de exemplo.

const API_VERSION = '2025-04-30-preview';

async function listItems(accessToken, catalogUrl, collectionId, limit = 10) {
  const url = `${catalogUrl}/stac/collections/${collectionId}/items?limit=${limit}&api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
    },
  });
  
  if (!response.ok) {
    throw new Error(`Failed to list items: ${response.statusText}`);
  }
  
  const data = await response.json();
  return data.features; // Array of STAC Item objects
}

Pesquisa em várias coleções

Captura de ecrã a mostrar como usar a pesquisa STAC para devolver itens de interesse.

const API_VERSION = '2025-04-30-preview';

async function searchItems(accessToken, catalogUrl, searchParams) {
  const url = `${catalogUrl}/stac/search?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(searchParams),
  });
  
  if (!response.ok) {
    throw new Error(`Search failed: ${response.statusText}`);
  }
  
  return await response.json();
}

// Example usage:
const results = await searchItems(token, catalogUrl, {
  collections: ['my-collection'],
  bbox: [-122.5, 37.5, -122.0, 38.0],  // [west, south, east, north]
  datetime: '2024-01-01/2024-12-31',
  limit: 20,
});

URLs de mosaico: Construir URLs para visualização de mapas

A API GeoCatalog Tiler serve dados raster como tiles de mapa. Construa URLs de tiles com o seguinte padrão:

Blocos de item único

Captura de ecrã a mostrar como exibir blocos para um único item.

{catalogUrl}/data/collections/{collectionId}/items/{itemId}/tiles/{z}/{x}/{y}@1x.png
  ?api-version=2025-04-30-preview
  &tileMatrixSetId=WebMercatorQuad
  &assets=visual

Função construtora de URL de telhas

const API_VERSION = '2025-04-30-preview';

/**
 * Build a tile URL template for a STAC item.
 * Returns a URL with {z}/{x}/{y} placeholders for use with map libraries.
 */
function buildTileUrl(catalogUrl, collectionId, itemId, options = {}) {
  const { assets = 'visual', colormap, rescale } = options;
  
  const base = `${catalogUrl}/data/collections/${collectionId}/items/${itemId}/tiles/{z}/{x}/{y}@1x.png`;
  
  const params = new URLSearchParams();
  params.set('api-version', API_VERSION);
  params.set('tileMatrixSetId', 'WebMercatorQuad');
  params.set('assets', assets);
  
  if (colormap) params.set('colormap_name', colormap);
  if (rescale) params.set('rescale', rescale);
  
  return `${base}?${params.toString()}`;
}

// Example usage:
const tileUrl = buildTileUrl(
  'https://mygeocatalog.northcentralus.geocatalog.spatio.azure.com',
  'aerial-imagery',
  'image-001',
  { assets: 'visual' }
);

Parâmetros chave do tile

Parâmetro Obrigatório Description
api-version Yes Versão API (2025-04-30-preview)
tileMatrixSetId Yes Utilizar WebMercatorQuad para mapas da web
assets Yes Nomes de ativos a renderizar (exemplo: visual, image)
colormap_name Não Colormap nomeado (exemplo: viridis, terrain)
rescale Não Intervalo de valores para escalonamento (exemplo: 0,255)
asset_bidx Não Índices de banda (exemplo: image\|1,2,3 para RGB)

Observação

Para coleções com imagens de quatro bandas (como NAIP com RGB + NIR), use asset_bidx=image|1,2,3 para selecionar apenas as bandas RGB. O tiler não consegue codificar quatro bandas como PNG.


Integração de mapas: Mostrar mosaicos com MapLibre GL

Bibliotecas de mapas como MapLibre GL, Leaflet e OpenLayers podem mostrar blocos raster. O principal desafio é adicionar cabeçalhos de autorização aos pedidos de tiles, uma vez que estas bibliotecas obtêm tiles diretamente.

Exemplo do MapLibre GL

O MapLibre GL oferece uma transformRequest opção para injetar cabeçalhos:

import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';

// Store the current access token
let currentAccessToken = null;

function initializeMap(containerId, accessToken) {
  currentAccessToken = accessToken;
  
  const map = new maplibregl.Map({
    container: containerId,
    style: {
      version: 8,
      sources: {
        osm: {
          type: 'raster',
          tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
          tileSize: 256,
          attribution: '© OpenStreetMap contributors',
        },
      },
      layers: [{ id: 'osm', type: 'raster', source: 'osm' }],
    },
    center: [0, 0],
    zoom: 2,
    // Add authorization header to tile requests
    transformRequest: (url, resourceType) => {
      // Only add auth for GeoCatalog tile requests
      if (url.includes('geocatalog.spatio.azure.com') && currentAccessToken) {
        return {
          url,
          headers: { 'Authorization': `Bearer ${currentAccessToken}` },
        };
      }
      return { url };
    },
  });
  
  return map;
}

function addTileLayer(map, tileUrl, bounds) {
  // Remove existing layer and source if present
  if (map.getLayer('data-layer')) {
    map.removeLayer('data-layer');
  }
  if (map.getSource('data-tiles')) {
    map.removeSource('data-tiles');
  }
  
  // Add tile source
  map.addSource('data-tiles', {
    type: 'raster',
    tiles: [tileUrl],
    tileSize: 256,
    minzoom: 10,  // Many aerial collections require zoom 10+
    maxzoom: 18,
  });
  
  // Add tile layer
  map.addLayer({
    id: 'data-layer',
    type: 'raster',
    source: 'data-tiles',
  });
  
  // Zoom to bounds [west, south, east, north]
  if (bounds) {
    map.fitBounds([[bounds[0], bounds[1]], [bounds[2], bounds[3]]], { padding: 50 });
  }
}

Importante

A função transformRequest é chamada para cada pedido de mosaico. Armazene o token de acesso numa variável que transformRequest possa aceder e atualize-o quando o token for atualizado.


Mosaicos: Exibir imagens de toda a coleção

Captura de ecrã a mostrar como exibir mosaicos para uma coleção.

Para visualizar todos os itens de uma coleção como uma camada uniforme, registe uma pesquisa em mosaico e utilize o ID de pesquisa devolvido.

const API_VERSION = '2025-04-30-preview';

/**
 * Register a mosaic search for a collection.
 * Returns a search ID that can be used to fetch mosaic tiles.
 */
async function registerMosaic(catalogUrl, collectionId, accessToken) {
  const url = `${catalogUrl}/data/mosaic/register?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      collections: [collectionId],
    }),
  });
  
  if (!response.ok) {
    throw new Error(`Failed to register mosaic: ${response.statusText}`);
  }
  
  const data = await response.json();
  // Note: API returns 'searchid' (lowercase), not 'searchId'
  return data.searchid;
}

/**
 * Build a mosaic tile URL template.
 */
function buildMosaicTileUrl(catalogUrl, searchId, collectionId, options = {}) {
  const { assets = 'visual' } = options;
  
  const base = `${catalogUrl}/data/mosaic/${searchId}/tiles/{z}/{x}/{y}@1x.png`;
  
  const params = new URLSearchParams();
  params.set('api-version', API_VERSION);
  params.set('tileMatrixSetId', 'WebMercatorQuad');
  params.set('collection', collectionId);
  params.set('assets', assets);
  
  return `${base}?${params.toString()}`;
}

Tokens SAS: Descarregar ativos brutos

A API SAS fornece tokens com limite de tempo para descarregar ficheiros brutos de ativos (GeoTIFFs, COGs e outros ficheiros) diretamente do Azure Blob Storage. Use esta opção quando precisar dos ficheiros fonte originais em vez de tiles renderizados.

Importante

Os tokens SAS permitem downloads apenas em aplicações de navegador. Devido às políticas CORS do Azure Blob Storage, os navegadores não conseguem ler dados de blob via JavaScript fetch(). Consulte a secção de limitações do navegador .

Captura de ecrã a mostrar como descarregar assets usando um token SAS.

Obtenha um token SAS

const API_VERSION = '2025-04-30-preview';

/**
 * Get a SAS token for accessing assets in a collection.
 * Returns a token string that can be appended to asset URLs.
 */
async function getCollectionSasToken(accessToken, catalogUrl, collectionId) {
  const url = `${catalogUrl}/sas/token/${collectionId}?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
    },
  });
  
  if (!response.ok) {
    throw new Error(`Failed to get SAS token: ${response.statusText}`);
  }
  
  const data = await response.json();
  return data.token; // SAS token string
}

Crie uma URL de download assinada

/**
 * Build a signed URL for downloading an asset.
 * Appends the SAS token to the asset's href.
 */
function buildSignedAssetUrl(assetHref, sasToken) {
  const separator = assetHref.includes('?') ? '&' : '?';
  return `${assetHref}${separator}${sasToken}`;
}

// Example usage:
const sasToken = await getCollectionSasToken(accessToken, catalogUrl, 'my-collection');
const assetHref = item.assets['visual'].href;
const signedUrl = buildSignedAssetUrl(assetHref, sasToken);

Desencadear o download de um ficheiro

/**
 * Trigger a browser download for an asset file.
 * Works by creating a temporary anchor element.
 */
function downloadAsset(signedUrl, filename) {
  const link = document.createElement('a');
  link.href = signedUrl;
  link.download = filename || 'download';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

// Example: Download an asset
downloadAsset(signedUrl, 'aerial-image.tif');

Limitações do navegador

Os tokens SAS funcionam de forma diferente nos navegadores em comparação com o código do lado do servidor:

Caso de uso Browser Server-side
Descarregar ficheiros (utilizador seleciona o link) ✅ Funciona ✅ Funciona
Ler dados de blob através de fetch() ❌ CORS bloqueado ✅ Funcionamento
Processar píxeis brutos em JavaScript ❌ Não é possível ✅ Funciona

Os downloads do navegador funcionam porque a navegação (clicar em links) contorna o CORS. No entanto, fetch() os pedidos para o Azure Blob Storage são bloqueados porque a conta de armazenamento não inclui a origem da sua aplicação na sua política CORS.

Se a sua aplicação precisar de ler e processar dados brutos de ativos no navegador, implemente um proxy do lado do servidor:

Observação

O código seguinte é um exemplo simplificado para ilustrar o padrão proxy. Para aplicações de produção, o seu endpoint proxy deve autenticar os pedidos (por exemplo, encaminhando o token Bearer do utilizador ou usando autenticação de sessão) e validar que o utilizador está autorizado a aceder aos recursos solicitados.

// ❌ Browser: This fails due to CORS
const response = await fetch(signedUrl);
const data = await response.arrayBuffer(); // Error!

// ✅ Browser: Call your backend instead
const response = await fetch('/api/proxy-asset', {
  method: 'POST',
  body: JSON.stringify({ collectionId, itemId, assetName })
});
const data = await response.json(); // Works!

O seu backend pode obter o blob usando o token SAS e devolver os resultados processados.


Considerações de desenvolvimento

Suporte CORS

As APIs do GeoCatalog incluem suporte total para CORS com Access-Control-Allow-Origin: *. Aplicações baseadas em navegador podem fazer pedidos diretos ao GeoCatalog a partir de qualquer origem, incluindo http://localhost durante o desenvolvimento. Não é necessário qualquer proxy ou solução alternativa.

A API permite o cabeçalho Authorization nos pedidos CORS, portanto, as chamadas autenticadas fetch() funcionam diretamente a partir do JavaScript do navegador.

Escolher o método certo de acesso a dados

Método Navegador fetch() Downloads do Navegador Server-side Melhor Para
Tiler API ✅ Totalmente suportado ✅ Sim ✅ Sim Visualização de mapas
SAS Tokens ❌ CORS bloqueado ✅ Sim ✅ Sim Downloads de ficheiros em bruto
  • API Tiler: Usada para exibir imagens em mapas. Devolve blocos PNG ou WebP renderizados com suporte total para CORS. Veja URLs de Tile e integração de mapas.

  • Tokens SAS: Usados para descarregar ficheiros fonte originais (GeoTIFFs, COGs). Os downloads do navegador funcionam, mas fetch() são bloqueados pelas políticas CORS do Azure Blob Storage. Consulte os tokens SAS para detalhes e soluções alternativas.

Atualização de token

Os tokens de acesso expiram, normalmente após uma hora. A sua candidatura deve:

  1. Trate dos erros 401 adquirindo um novo token.
  2. Use a aquisição silenciosa de tokens da MSAL, que atualiza automaticamente os tokens expirados.
  3. Atualize a referência do token utilizada pelo seu mapa no transformRequest.

Tratamento de erros

Lidar com cenários de erro comuns:

Estado HTTP Motivo Solução
401 Token expirado ou inválido Atualizar o token de acesso
404 Item ou coleção não encontrados Verificar se os IDs existem
424 Tile fora da extensão de dados Esperado - manuseio com elegância

Solução de problemas

Erro Motivo Solução
"AADSTS50011: URL de resposta incompatível" O URI de redirecionamento no código não coincide com o registo do Microsoft Entra ID Adicione o seu URL de desenvolvimento (por exemplo, http://localhost:3000) como um URI de redirecionamento SPA no registo da sua aplicação
Erro de âmbito inválido Usar URL do GeoCatálogo em vez do âmbito da API Utilize https://geocatalog.spatio.azure.com/.default como escopo
401 Não autorizado em pedidos de blocos de interface Biblioteca de mapas que não inclui cabeçalhos de autenticação Use transformRequest (MapLibre) para adicionar o token do Portador; certifique-se de que o token está atualizado
Os tiles não se alinham com o basemap Conjunto de blocos de matriz incorreto Utilização tileMatrixSetId=WebMercatorQuad para projeção Web Mercator (EPSG:3857)
"Não consegui decifrar a imagem" Nome de ativo errado, imagens multibanda ou extensão externa dos dados Verifique item_assets para nomes válidos; utilize asset_bidx=image\|1,2,3 para RGB; é esperado que 404/424 esteja fora da cobertura.

Próximos passos