Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Neste início rápido, você cria um aplicativo Web que exibe imagens de satélite e dados geoespaciais de seu GeoCatalog em um mapa interativo. Você autentica os usuários com a ID do Microsoft Entra, consulta coleções STAC e renderiza blocos de mapa— tudo do navegador JavaScript.
O que você aprende:
- Autenticar usuários e adquirir tokens de acesso usando MSAL.js
- Consultar a API stac para descobrir coleções e itens
- Exibir blocos de raster em um mapa do MapLibre GL com cabeçalhos de autorização
- Criar camadas contínuas de mosaico em coleções completas
- Baixar recursos brutos usando tokens SAS
Os padrões de código funcionam com qualquer estrutura JavaScript moderna (React, Vue, Angular) ou JavaScript puro. As APIs do GeoCatalog têm suporte completo do CORS, portanto, você pode chamá-las diretamente localhost durante o desenvolvimento, sem necessidade de proxy.
Você pode baixar e testar esse código no repositório GitHub público do Microsoft Planetary Computer Pro.
Pré-requisitos
- Uma conta do Azure com uma assinatura ativa. Crie uma conta gratuitamente.
- Um recurso geocatalog implantado com pelo menos uma coleção contendo itens.
- Sua identidade de usuário deve ter acesso do Leitor de GeoCatalog (ou superior) ao recurso GeoCatalog. Consulte Gerenciar o acesso a um recurso do GeoCatalog.
- Node.js versão 18 ou posterior.
Visão geral da arquitetura
Um aplicativo Web GeoCatalog típico segue esta arquitetura:
Registrar seu aplicativo na ID do Microsoft Entra
Antes que seu aplicativo Web possa autenticar usuários, registre-o na ID do Microsoft Entra. Este Início Rápido usa um registro SPA (Aplicativo de Página Única) que é ideal para aplicativos JavaScript do lado do cliente e desenvolvimento local. Os padrões de integração da API mostrados nas etapas posteriores funcionam com qualquer tipo de aplicativo.
Observação
Para aplicativos de produção com um servidor de back-end, considere escolher um tipo de registro diferente (Web, Nativo etc.). Consulte Configurar a autenticação de aplicativo para obter diretrizes sobre como escolher a abordagem certa para seu cenário.
Registre-se como um aplicativo de página única
- Acesse a ID do Microsoft Entra no portal do Azure.
- Selecione registros de aplicativo no painel lateral.
- Selecione Novo registro.
- Insira um nome para seu aplicativo (por exemplo, "GeoCatalog Web App").
- Em Tipos de contas com suporte, selecione Contas somente neste diretório organizacional.
- Em URI de Redirecionamento, selecione SPA (aplicativo de página única) e insira sua URL de desenvolvimento (por exemplo,
http://localhost:5173). - Selecione Registrar.
Após o registro, observe os seguintes valores na página Visão Geral :
- ID do aplicativo (cliente)
- ID do Diretório (locatário)
Para obter mais informações, consulte o registro de aplicativo de inicialização rápida.
Conceder permissões de API
Seu aplicativo precisa de permissão para chamar a API geocatalog em nome de usuários conectados:
- No registro do aplicativo, selecione permissões> de APIAdicionar uma permissão.
- Selecione APIs que minha organização usa e pesquise o Azure Orbital Spatio.
- Selecione permissões delegadas e marque user_impersonation.
- Selecione Adicionar permissões.
- Se você for um administrador, selecione Conceder consentimento do administrador para consentir em nome de todos os usuários em seu locatário.
Configurar seu aplicativo
Seu aplicativo precisa dos seguintes valores de configuração. A forma como você fornece esses valores depende das ferramentas de build (variáveis de ambiente, arquivos de configuração e assim por diante):
| Configuração | Value | Description |
|---|---|---|
| URL do catálogo | https://{name}.{region}.geocatalog.spatio.azure.com |
Seu ponto de extremidade GeoCatalog |
| ID do locatário | A partir do registro do aplicativo | Seu locatário do Microsoft Entra |
| ID do cliente | A partir do registro do aplicativo | ID do cliente do aplicativo |
| Escopo da API | https://geocatalog.spatio.azure.com/.default |
Sempre use esse valor exato |
Instalar dependências
Instale a MSAL (Biblioteca de Autenticação da Microsoft) para aplicativos de navegador e uma biblioteca de mapas:
npm install @azure/msal-browser maplibre-gl
- @azure/msal-browser – manipula a autenticação do OAuth 2.0 com a ID do Microsoft Entra
- maplibre-gl – biblioteca de mapas de software livre para visualização de blocos
Dica
Estrutura do projeto: Os exemplos de código neste início rápido são funções autônomas que você pode organizar como preferir. Um padrão comum:
-
auth.js: configuração MSAL e funções de token -
api.js: API STAC, API de Tiler e funções de token SAS -
map.js: Inicialização do MapLibre e gerenciamento de camada de tiles -
App.jsoumain.js: conecte tudo junto com sua interface do usuário
Cada função recebe suas dependências (tokens de acesso, URLs) como parâmetros, facilitando a integração em qualquer estrutura ou estrutura de projeto.
Implementar a autenticação MSAL
Configure a MSAL para autenticação do navegador. O exemplo a seguir mostra o padrão de configuração de chave e aquisição de token:
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: coleções e itens de consulta
O API STAC do GeoCatalog fornece endpoints para descobrir e consultar dados geoespaciais. Todas as solicitações exigem um Authorization cabeçalho com um token Bearer obtido da funcionalidade Implementar autenticação MSAL.
Listar coleções
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
}
Listar itens em uma coleção
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
}
Pesquisar entre coleções
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 bloco: Criar URLs para visualização de mapa
A API GeoCatalog Tiler serve dados raster como mosaicos de mapa. Construa URLs de tiles com o seguinte padrão:
Blocos de item único
{catalogUrl}/data/collections/{collectionId}/items/{itemId}/tiles/{z}/{x}/{y}@1x.png
?api-version=2025-04-30-preview
&tileMatrixSetId=WebMercatorQuad
&assets=visual
Função construtor de URL de bloco
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 de azulejo chave
| Parâmetro | Obrigatório | Description |
|---|---|---|
api-version |
Yes | Versão da API (2025-04-30-preview) |
tileMatrixSetId |
Yes | Usar WebMercatorQuad para mapas da Web |
assets |
Yes | Nomes de ativo a serem renderizados (exemplo: visual, image) |
colormap_name |
Não | Mapa de cores nomeado (exemplo: viridis, terrain) |
rescale |
Não | Intervalo de valor para dimensionamento (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 tileador não consegue codificar quatro bandas como PNG.
Integração de mapa: exibir blocos com o GL MapLibre
Bibliotecas de mapa como MapLibre GL, Leaflet e OpenLayers podem exibir blocos de raster. O principal desafio é adicionar cabeçalhos de autorização a solicitações de bloco, já que essas bibliotecas buscam blocos diretamente.
Exemplo de MAPLibre GL
MapLibre GL fornece 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 transformRequest função é chamada para cada solicitação de tile. Armazene o token de acesso em uma variável que transformRequest possa acessá-lo e atualize-o quando o token for atualizado.
Blocos de mosaico: exibir imagens em toda a coleção
Para exibir todos os itens de uma coleção como uma camada perfeita, registre uma pesquisa de mosaico e use a ID de pesquisa retornada:
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: baixar ativos brutos
A API SAS fornece tokens limitados de tempo para baixar arquivos de ativo bruto (GeoTIFFs, COGs e outros arquivos) diretamente do Armazenamento de Blobs do Azure. Use essa opção quando precisar dos arquivos de origem originais em vez de blocos renderizados.
Importante
Os tokens SAS habilitam somente downloads em aplicativos de navegador. Devido às políticas de CORS do Armazenamento de Blobs do Azure, os navegadores não podem ler dados de blob por meio do JavaScript fetch(). Consulte a seção Limitações do Navegador .
Obter 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
}
Criar 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);
Disparar um download de arquivo
/**
* 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 em navegadores versus código do lado do servidor:
| Caso de Uso | Navegador | Server-side |
|---|---|---|
| Baixar arquivos (o usuário seleciona o link) | ✅ Funciona | ✅ Funciona |
Ler dados de blob por meio de fetch() |
❌ CORS bloqueado | ✅ Funciona |
| Processar pixels brutos em JavaScript | ❌ Não é possível | ✅ Funciona |
Os downloads do navegador funcionam porque a navegação (clicando em links) ignora o CORS. No entanto, fetch() as solicitações para o Armazenamento de Blobs do Azure estão bloqueadas porque a conta de armazenamento não inclui a origem da sua aplicação em sua política de CORS.
Se o aplicativo precisar ler e processar dados brutos de ativos no navegador, implemente um proxy do lado do servidor:
Observação
O código a seguir é um exemplo simplificado para ilustrar o padrão de proxy. Para aplicativos de produção, seu endpoint de proxy deve autenticar solicitações (por exemplo, encaminhando o Bearer token do usuário ou usando a autenticação de sessão) e validar se o usuário está autorizado a acessar os 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!
Seu back-end pode buscar o blob usando o token SAS e retornar resultados processados.
Considerações sobre desenvolvimento
Suporte a CORS
As APIs do GeoCatalog incluem suporte completo ao CORS com Access-Control-Allow-Origin: *. Aplicativos baseados em navegador podem fazer solicitações diretas ao GeoCatalog de qualquer origem, inclusive http://localhost durante o desenvolvimento. Nenhum proxy ou solução alternativa é necessário.
A API permite o Authorization cabeçalho em solicitações CORS, para que as chamadas autenticadas fetch() funcionem diretamente no navegador JavaScript.
Escolhendo o método de acesso a dados correto
| Método | Navegador fetch() |
Downloads de Navegador | Server-side | Mais Adequado Para |
|---|---|---|---|---|
| Tiler API | ✅ Suporte completo | ✅ Sim | ✅ Sim | Visualização de mapa |
| SAS Tokens | ❌ CORS bloqueado | ✅ Sim | ✅ Sim | Downloads de arquivos não processados |
Tiler API: Use para exibir imagens em mapas. Retorna blocos PNG ou WebP renderizados com suporte completo do CORS. Consulte URLs de bloco e integração de mapa.
Tokens SAS: Usar para baixar arquivos de origem (GeoTIFFs, COGs). Os downloads do navegador funcionam, mas
fetch()é bloqueado pelas políticas de CORS do Armazenamento de Blobs do Azure. Consulte tokens SAS para obter detalhes e soluções alternativas.
Atualização de token
Os tokens de acesso expiram, normalmente após uma hora. Seu aplicativo deve:
- Lidar com erros 401 adquirindo um novo token.
- Use a aquisição de token silencioso da MSAL, que atualiza automaticamente tokens expirados.
- Atualize a referência de token usada no seu mapa
transformRequest.
Tratamento de erros
Lidar com cenários de erro comuns:
| Status HTTP | Motivo | Solução |
|---|---|---|
| 401 | Token expirado ou inválido | Atualizar o token de acesso |
| 404 | Item ou coleção não encontrado | Verificar se existem IDs |
| 424 | Bloco fora da extensão de dados | Esperado - lidar de forma elegante |
Resolução de problemas
| Erro | Motivo | Solução |
|---|---|---|
| "AADSTS50011: Incompatibilidade de URL de resposta" | A URI de redirecionamento no código não corresponde ao registro da ID do Microsoft Entra | Adicione a URL de desenvolvimento (por exemplo, http://localhost:3000) como um URI de redirecionamento do SPA no registro do aplicativo |
| Erro de "escopo inválido" | Usando a URL do GeoCatalog em vez do escopo da API | Use https://geocatalog.spatio.azure.com/.default como o escopo |
| 401 Não autorizado em solicitações de bloco | Biblioteca de mapas que não inclui cabeçalhos de autenticação | Usar transformRequest (MapLibre) para adicionar o token de portador; verifique se o token está atual |
| Os azulejos não se alinham com o mapa de base | Conjunto de matrizes de blocos incorreto | Uso tileMatrixSetId=WebMercatorQuad para projeção do Web Mercator (EPSG:3857) |
| "Não foi possível decodificar imagem" | Nome do ativo incorreto, imagens multiespectrais ou extensão de dados externa | Verifique se item_assets há nomes válidos; use asset_bidx=image\|1,2,3 para RGB; 404/424 cobertura externa é esperada |