Configuración de Proxy en Vite e Interceptors de Axios para Autenticación en Vue

La integración de un servidor de desarrollo con Vite y un cliente HTTP centralizado requiere una gestión precisa de las rutas de API y los encabezados de autenticación. A continuación se expone la implementación de un proxy de desarrollo junto con una instancia de Axios configurada para inyectar tokens JWT y manejar respuestas no autorizadas.

Definición del Proxy y Alias en Vite

El archivo de configuración principle debe establecer las variables de entorno, los atajos de importación y las reglas de reenvío de solicitudes. Utilizando loadEnv, se capturan los valores específicos del modo de ejecución para dirigir el tráfico hacia el back end correspondiente.

import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import AutoImport from 'unplugin-auto-import/vite';

export default defineConfig(({ mode }) => {
  const environment = loadEnv(mode, process.cwd());
  const backendEndpoint = environment.VITE_API_BASE_URL || 'http://localhost:3000';

  return {
    plugins: [
      vue(),
      AutoImport({
        imports: ['vue', 'vue-router', 'pinia'],
        dts: 'src/auto-imports.d.ts',
        vueTemplate: true,
        eslintrc: { enabled: true }
      })
    ],
    resolve: {
      alias: {
        '@src': resolve(__dirname, 'src'),
        '@modules': resolve(__dirname, 'src/modules'),
        '@services': resolve(__dirname, 'src/services'),
        '@shared': resolve(__dirname, 'src/shared')
      }
    },
    server: {
      port: 5173,
      proxy: {
        '/v1': {
          target: backendEndpoint,
          changeOrigin: true,
          secure: false,
          rewrite: (route) => route.replace(/^\/v1/, '')
        }
      }
    }
  };
});

La sección server.proxy intercepta cualquier petición que inicie con /v1, modifica la ruta eliminando el prefijo mediante rewrite y la redirige al destino definido en VITE_API_BASE_URL. Esto elimina los bloqueos por CORS durante la fase de desarrollo.

Cliente HTTP con Interceptors de Autenticación

Para evitar la duplicación de lógica en cada llamada a la API, se genera un módulo independiente que exporta una instancia preconfigurada de Axios. Los interceptores se encargan de adjuntar credenciales y gestionar fallos de sesión.

import axios, { type AxiosInstance, type InternalAxiosRequestConfig, type AxiosResponse, type AxiosError } from 'axios';
import appRouter from '@/modules/navigation/router';

const SESSION_TOKEN_KEY = 'erp_access_jwt';
const API_PREFIX = '/v1';

const httpClient: AxiosInstance = axios.create({
  baseURL: API_PREFIX,
  timeout: 45000,
  headers: { 'Content-Type': 'application/json' }
});

httpClient.interceptors.request.use(
  (cfg: InternalAxiosRequestConfig) => {
    const jwt = localStorage.getItem(SESSION_TOKEN_KEY);
    if (jwt && cfg.headers) {
      cfg.headers.Authorization = `Bearer ${jwt}`;
    }
    return cfg;
  },
  (err) => Promise.reject(err)
);

httpClient.interceptors.response.use(
  (res: AxiosResponse) => res,
  (err: AxiosError) => {
    const statusCode = err.response?.status;
    if (statusCode === 401) {
      localStorage.removeItem(SESSION_TOKEN_KEY);
      appRouter.replace({ path: '/login' });
    }
    return Promise.reject(err);
  }
);

export default httpClient;

El interceptor de solicitud recupera el token almacenado y lo asigna al encabezado Authorization antes de que la petición salga del navegador. En caso de que el servidor responda con un estado 401, el interceptor de respuesta elimina la credencial expirada y fuerza la navegación hacia la ruta de autenticación, manteniendo la experiencia de usuario consistente.

Implementación de Módulos de API

Con el cliente HTTP exportado, los servicios de datos pueden consumirlo directamente. Esta estructura garantiza que todas las peticiones hereden automáticamente los tiempos de espera, la URL base y la gestión de tokens.

import httpClient from '@/shared/http/httpClient';
import type { ClientFilters, ClientDirectoryResponse } from '@/shared/types/clients';

export const fetchClientDirectory = (filters: ClientFilters) => {
  return httpClient.post<ClientDirectoryResponse>('/clients/directory', filters);
};

Etiquetas: Vite vue.js axios TypeScript JWT

Publicado el 8-23 08:05