Configurando Proxy no Vite para Resolver CORS e Simplificar Requisições

Ao desenvolver aplicações frontend, é comum enfrentar o problema de CORS (Cross-Origin Reosurce Sharing). O navegador bloqueia requisições para APIs quando há divergência no domínio, porta ou protocolo (HTTP/HTTPS) em relação à aplicação frontend. Além disso, os desenvolvedores frequentemente acabam repetindo o domínio base do backend em várias chamadas, como https://backend.example.com/api/v1/users e https://backend.example.com/api/v1/posts. Ambas as situações podem ser resolvidas de forma elegante utilizando a configuração de proxy.

Ferramentas de build e servidores de desenvolvimento, como Vite e Webpack, possuem suporte nativo para proxies. O proxy intercepta as requisições feitas para um determinado caminho e as redireciona para o endereço real da API. Para o navegador, a requisição parece ser feita para o mesmo domínio, porta e protocolo, eliminando assim os bloqueios de CORS e a necessidade de hardcodar URLs completas.

Abaixo, veremos como configurar o proxy no Vite. No arquivo vite.config.js, podemos definir regras de redirecionamento. Suponha que nossa aplicação frontend esteja rodando em http://localhost:5173 e queremos interceptar todas as requisições que começam com /services, encaminhando-as para um back end em http://localhost:8080. Além disso, assumiremos que o backend não espera o prefixo /services em suas rotas, portanto, precisamos removê-lo dinamicamente.

import { defineConfig } from 'vite';

export default defineConfig({
  server: {
    proxy: {
      '/services': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (route) => route.replace(/^\/services/, ''),
      },
    },
  },
});

Analisando a estrutura de configuração exportada pelo Vite:

  • O objeto server agrupa as configurações do servidor de desenvolvimento.
  • Dentro dele, a propriedade proxy recebe um objeto onde as chaves são os prefixos de URL a serem interceptados.
  • A chave '/services' indica que qualquer requisição iniciada com esse caminho será processada pelas regras definidas.

Dentro do objeto de configuração do proxy, temos as seguintes propriedades:

  • target: Define o endereço real do backend. O Vite concatena o caminho da requisição a este target. Por exemplo, /services/data seria inicialmente convertido para http://localhost:8080/services/data.
  • changeOrigin: Quando definido como true, altera o cabeçalho Origin da requisição para que corresponda à URL do target. Isso é crucial para evitar que o servidor de destino rejeite a requisição por CORS.
  • rewrite: Permite modificar o caminho da URL antes de enviá-la ao target. Como o backend não possui o prefixo /services, usamos uma função com uma expressão regular para substituir essa parte inicial por uma string vazia, transformando /services/data em /data.

Com essa configuração, o código frontend pode fazer chamadas de forma limpa, sem precisar especificar o protocolo, domínio ou porta do backend:

fetch('/services/users');

Entendendo a função de rewrite em cenários práticos

A função rewrite é extremamante útil para evitar redundância. Se o seu backend já possui uma base path como /api ou /services, você pode configurar o target para incluir esse prefixo e usar o rewrite para removê-lo da requisição original.

Por exemplo, se o backend está em http://www.api-exemplo.com/services e a rota real é /user/profile, você pode configurar o proxy da seguinte forma:

server: {
  proxy: {
    '/services': {
      target: 'http://www.api-exemplo.com/services',
      changeOrigin: true,
      rewrite: (route) => route.replace(/^\/services/, '')
    }
  }
}

Isso permite que você faça a requisição no frontend sem repetir o prefixo:

import axios from 'axios';

axios.post('/user/profile', {
  username: 'dev_user'
});

Por outro lado, se você optar por não utilizar a função rewrite, o target deve apontar apenas para o domínio raiz, e a requisição frontend deve incluir o prefixo completo:

server: {
  proxy: {
    '/services': {
      target: 'http://www.api-exemplo.com',
      changeOrigin: true
    }
  }
}

E a chamada no frontend seria:

import axios from 'axios';

axios.post('/services/user/profile', {
  username: 'dev_user'
});

Tags: Vite proxy CORS frontend javascript

Publicado em 8-19 11:28