2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-20 20:00:40 +03:00

feat: added initial ai based translations (#10705)

This commit is contained in:
Jay
2026-04-14 18:41:20 +02:00
committed by GitHub
parent 7a8bd9a881
commit 01a581a38d
103 changed files with 12280 additions and 102 deletions
+340 -102
View File
@@ -1,8 +1,313 @@
import { defineConfig } from 'vitepress';
// https://vitepress.dev/reference/site-config
// ─── English ─────────────────────────────────────────────────────────────────
const enNav = [
{ text: 'Guide', link: '/pages/getting-started/first-steps' },
{ text: 'API', link: '/pages/advanced/api-reference' },
{ text: 'Sponsors', link: '/pages/misc/sponsors' },
{ text: 'v1.x', link: '#' },
];
const enSidebar = [
{
text: 'Getting Started',
items: [
{ text: 'First steps', link: '/pages/getting-started/first-steps' },
{ text: 'Features', link: '/pages/getting-started/features' },
{
text: 'Examples',
items: [
{ text: 'JavaScript', link: '/pages/getting-started/examples/commonjs' },
{ text: 'TypeScript', link: '/pages/getting-started/examples/typescript' },
],
},
{ text: 'Upgrade guide v0.x -> v1.x', link: '/pages/getting-started/upgrade-guide' },
],
},
{
text: 'Advanced',
items: [
{ text: 'Public API', link: '/pages/advanced/api-reference' },
{ text: 'Request method aliases', link: '/pages/advanced/request-method-aliases' },
{ text: 'Creating an instance', link: '/pages/advanced/create-an-instance' },
{ text: 'Request config', link: '/pages/advanced/request-config' },
{ text: 'Adapters', link: '/pages/advanced/adapters' },
{ text: 'Response schema', link: '/pages/advanced/response-schema' },
{ text: 'Config defaults', link: '/pages/advanced/config-defaults' },
{ text: 'Interceptors', link: '/pages/advanced/interceptors' },
{ text: 'Error handling', link: '/pages/advanced/error-handling' },
{ text: 'Cancellation', link: '/pages/advanced/cancellation' },
{ text: 'Authentication', link: '/pages/advanced/authentication' },
{ text: 'Retry & error recovery', link: '/pages/advanced/retry' },
{ text: 'Testing', link: '/pages/advanced/testing' },
{
text: 'x-www-form-urlencoded format',
link: '/pages/advanced/x-www-form-urlencoded-format',
},
{ text: 'Multipart/form-data format', link: '/pages/advanced/multipart-form-data-format' },
{ text: 'File posting', link: '/pages/advanced/file-posting' },
{ text: 'HTML form processing 🔥', link: '/pages/advanced/html-form-processing' },
{ text: 'Progress capturing 🔥', link: '/pages/advanced/progress-capturing' },
{ text: 'Rate limiting 🔥', link: '/pages/advanced/rate-limiting' },
{
text: 'Headers 🔥',
items: [
{ text: 'General usage', link: '/pages/advanced/headers' },
{ text: 'Methods', link: '/pages/advanced/header-methods' },
],
},
{ text: 'Fetch adapter 🔥', link: '/pages/advanced/fetch-adapter' },
{ text: 'HTTP2 🔥', link: '/pages/advanced/http2' },
{ text: 'Promises', link: '/pages/advanced/promises' },
{ text: 'TypeScript', link: '/pages/advanced/type-script' },
],
},
{
text: 'Miscellaneous',
items: [
{ text: 'SemVer', link: '/pages/misc/semver' },
{ text: 'Security', link: '/pages/misc/security' },
],
},
];
// ─── Mandarin Chinese ─────────────────────────────────────────────────────────
const zhNav = [
{ text: '指南', link: '/zh/pages/getting-started/first-steps' },
{ text: 'API', link: '/zh/pages/advanced/api-reference' },
{ text: '赞助商', link: '/zh/pages/misc/sponsors' },
{ text: 'v1.x', link: '#' },
];
const zhSidebar = [
{
text: '入门指南',
items: [
{ text: '第一步', link: '/zh/pages/getting-started/first-steps' },
{ text: '功能特性', link: '/zh/pages/getting-started/features' },
{
text: '示例',
items: [
{ text: 'JavaScript', link: '/zh/pages/getting-started/examples/commonjs' },
{ text: 'TypeScript', link: '/zh/pages/getting-started/examples/typescript' },
],
},
{ text: '升级指南 v0.x -> v1.x', link: '/zh/pages/getting-started/upgrade-guide' },
],
},
{
text: '进阶',
items: [
{ text: '公共 API', link: '/zh/pages/advanced/api-reference' },
{ text: '请求方法别名', link: '/zh/pages/advanced/request-method-aliases' },
{ text: '创建实例', link: '/zh/pages/advanced/create-an-instance' },
{ text: '请求配置', link: '/zh/pages/advanced/request-config' },
{ text: '适配器', link: '/zh/pages/advanced/adapters' },
{ text: '响应结构', link: '/zh/pages/advanced/response-schema' },
{ text: '默认配置', link: '/zh/pages/advanced/config-defaults' },
{ text: '拦截器', link: '/zh/pages/advanced/interceptors' },
{ text: '错误处理', link: '/zh/pages/advanced/error-handling' },
{ text: '取消请求', link: '/zh/pages/advanced/cancellation' },
{ text: '身份验证', link: '/zh/pages/advanced/authentication' },
{ text: '重试与错误恢复', link: '/zh/pages/advanced/retry' },
{ text: '测试', link: '/zh/pages/advanced/testing' },
{
text: 'x-www-form-urlencoded 格式',
link: '/zh/pages/advanced/x-www-form-urlencoded-format',
},
{ text: 'Multipart/form-data 格式', link: '/zh/pages/advanced/multipart-form-data-format' },
{ text: '文件上传', link: '/zh/pages/advanced/file-posting' },
{ text: 'HTML 表单处理 🔥', link: '/zh/pages/advanced/html-form-processing' },
{ text: '进度捕获 🔥', link: '/zh/pages/advanced/progress-capturing' },
{ text: '速率限制 🔥', link: '/zh/pages/advanced/rate-limiting' },
{
text: '请求头 🔥',
items: [
{ text: '基本用法', link: '/zh/pages/advanced/headers' },
{ text: '方法', link: '/zh/pages/advanced/header-methods' },
],
},
{ text: 'Fetch 适配器 🔥', link: '/zh/pages/advanced/fetch-adapter' },
{ text: 'HTTP2 🔥', link: '/zh/pages/advanced/http2' },
{ text: 'Promises', link: '/zh/pages/advanced/promises' },
{ text: 'TypeScript', link: '/zh/pages/advanced/type-script' },
],
},
{
text: '其他',
items: [
{ text: '语义化版本', link: '/zh/pages/misc/semver' },
{ text: '安全', link: '/zh/pages/misc/security' },
],
},
];
// ─── Spanish ──────────────────────────────────────────────────────────────────
const esNav = [
{ text: 'Guía', link: '/es/pages/getting-started/first-steps' },
{ text: 'API', link: '/es/pages/advanced/api-reference' },
{ text: 'Patrocinadores', link: '/es/pages/misc/sponsors' },
{ text: 'v1.x', link: '#' },
];
const esSidebar = [
{
text: 'Primeros pasos',
items: [
{ text: 'Inicio', link: '/es/pages/getting-started/first-steps' },
{ text: 'Características', link: '/es/pages/getting-started/features' },
{
text: 'Ejemplos',
items: [
{ text: 'JavaScript', link: '/es/pages/getting-started/examples/commonjs' },
{ text: 'TypeScript', link: '/es/pages/getting-started/examples/typescript' },
],
},
{
text: 'Guía de actualización v0.x -> v1.x',
link: '/es/pages/getting-started/upgrade-guide',
},
],
},
{
text: 'Avanzado',
items: [
{ text: 'API pública', link: '/es/pages/advanced/api-reference' },
{ text: 'Alias de métodos de solicitud', link: '/es/pages/advanced/request-method-aliases' },
{ text: 'Crear una instancia', link: '/es/pages/advanced/create-an-instance' },
{ text: 'Configuración de solicitud', link: '/es/pages/advanced/request-config' },
{ text: 'Adaptadores', link: '/es/pages/advanced/adapters' },
{ text: 'Esquema de respuesta', link: '/es/pages/advanced/response-schema' },
{ text: 'Configuración predeterminada', link: '/es/pages/advanced/config-defaults' },
{ text: 'Interceptores', link: '/es/pages/advanced/interceptors' },
{ text: 'Manejo de errores', link: '/es/pages/advanced/error-handling' },
{ text: 'Cancelación', link: '/es/pages/advanced/cancellation' },
{ text: 'Autenticación', link: '/es/pages/advanced/authentication' },
{ text: 'Reintento y recuperación de errores', link: '/es/pages/advanced/retry' },
{ text: 'Pruebas', link: '/es/pages/advanced/testing' },
{
text: 'Formato x-www-form-urlencoded',
link: '/es/pages/advanced/x-www-form-urlencoded-format',
},
{
text: 'Formato Multipart/form-data',
link: '/es/pages/advanced/multipart-form-data-format',
},
{ text: 'Publicación de archivos', link: '/es/pages/advanced/file-posting' },
{
text: 'Procesamiento de formularios HTML 🔥',
link: '/es/pages/advanced/html-form-processing',
},
{ text: 'Captura de progreso 🔥', link: '/es/pages/advanced/progress-capturing' },
{ text: 'Limitación de velocidad 🔥', link: '/es/pages/advanced/rate-limiting' },
{
text: 'Cabeceras 🔥',
items: [
{ text: 'Uso general', link: '/es/pages/advanced/headers' },
{ text: 'Métodos', link: '/es/pages/advanced/header-methods' },
],
},
{ text: 'Adaptador Fetch 🔥', link: '/es/pages/advanced/fetch-adapter' },
{ text: 'HTTP2 🔥', link: '/es/pages/advanced/http2' },
{ text: 'Promesas', link: '/es/pages/advanced/promises' },
{ text: 'TypeScript', link: '/es/pages/advanced/type-script' },
],
},
{
text: 'Miscelánea',
items: [
{ text: 'SemVer', link: '/es/pages/misc/semver' },
{ text: 'Seguridad', link: '/es/pages/misc/security' },
],
},
];
// ─── French ───────────────────────────────────────────────────────────────────
const frNav = [
{ text: 'Guide', link: '/fr/pages/getting-started/first-steps' },
{ text: 'API', link: '/fr/pages/advanced/api-reference' },
{ text: 'Sponsors', link: '/fr/pages/misc/sponsors' },
{ text: 'v1.x', link: '#' },
];
const frSidebar = [
{
text: 'Démarrage',
items: [
{ text: 'Premiers pas', link: '/fr/pages/getting-started/first-steps' },
{ text: 'Fonctionnalités', link: '/fr/pages/getting-started/features' },
{
text: 'Exemples',
items: [
{ text: 'JavaScript', link: '/fr/pages/getting-started/examples/commonjs' },
{ text: 'TypeScript', link: '/fr/pages/getting-started/examples/typescript' },
],
},
{
text: 'Guide de mise à niveau v0.x -> v1.x',
link: '/fr/pages/getting-started/upgrade-guide',
},
],
},
{
text: 'Avancé',
items: [
{ text: 'API publique', link: '/fr/pages/advanced/api-reference' },
{ text: 'Alias des méthodes de requête', link: '/fr/pages/advanced/request-method-aliases' },
{ text: 'Créer une instance', link: '/fr/pages/advanced/create-an-instance' },
{ text: 'Configuration des requêtes', link: '/fr/pages/advanced/request-config' },
{ text: 'Adaptateurs', link: '/fr/pages/advanced/adapters' },
{ text: 'Schéma de réponse', link: '/fr/pages/advanced/response-schema' },
{ text: 'Configuration par défaut', link: '/fr/pages/advanced/config-defaults' },
{ text: 'Intercepteurs', link: '/fr/pages/advanced/interceptors' },
{ text: 'Gestion des erreurs', link: '/fr/pages/advanced/error-handling' },
{ text: 'Annulation', link: '/fr/pages/advanced/cancellation' },
{ text: 'Authentification', link: '/fr/pages/advanced/authentication' },
{ text: "Nouvelles tentatives et récupération d'erreurs", link: '/fr/pages/advanced/retry' },
{ text: 'Tests', link: '/fr/pages/advanced/testing' },
{
text: 'Format x-www-form-urlencoded',
link: '/fr/pages/advanced/x-www-form-urlencoded-format',
},
{ text: 'Format Multipart/form-data', link: '/fr/pages/advanced/multipart-form-data-format' },
{ text: 'Envoi de fichiers', link: '/fr/pages/advanced/file-posting' },
{
text: 'Traitement des formulaires HTML 🔥',
link: '/fr/pages/advanced/html-form-processing',
},
{ text: 'Capture de la progression 🔥', link: '/fr/pages/advanced/progress-capturing' },
{ text: 'Limitation du débit 🔥', link: '/fr/pages/advanced/rate-limiting' },
{
text: 'En-têtes 🔥',
items: [
{ text: 'Utilisation générale', link: '/fr/pages/advanced/headers' },
{ text: 'Méthodes', link: '/fr/pages/advanced/header-methods' },
],
},
{ text: 'Adaptateur Fetch 🔥', link: '/fr/pages/advanced/fetch-adapter' },
{ text: 'HTTP2 🔥', link: '/fr/pages/advanced/http2' },
{ text: 'Promesses', link: '/fr/pages/advanced/promises' },
{ text: 'TypeScript', link: '/fr/pages/advanced/type-script' },
],
},
{
text: 'Divers',
items: [
{ text: 'SemVer', link: '/fr/pages/misc/semver' },
{ text: 'Sécurité', link: '/fr/pages/misc/security' },
],
},
];
// ─── Config ───────────────────────────────────────────────────────────────────
export default defineConfig({
lang: 'en-US',
title: 'axios | Promise based HTTP client',
description: 'Documentation for the axios HTTP project',
head: [
@@ -12,113 +317,46 @@ export default defineConfig({
['link', { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' }],
['link', { rel: 'manifest', href: '/site.webmanifest' }],
],
locales: {
root: {
label: 'English',
lang: 'en-US',
themeConfig: {
nav: enNav,
sidebar: enSidebar,
},
},
zh: {
label: '中文',
lang: 'zh-CN',
themeConfig: {
nav: zhNav,
sidebar: zhSidebar,
},
},
es: {
label: 'Español',
lang: 'es-ES',
themeConfig: {
nav: esNav,
sidebar: esSidebar,
},
},
fr: {
label: 'Français',
lang: 'fr-FR',
themeConfig: {
nav: frNav,
sidebar: frSidebar,
},
},
},
themeConfig: {
logo: {
dark: '/words.svg',
light: '/words-light.svg',
},
siteTitle: false,
nav: [
{ text: 'Guide', link: '/pages/getting-started/first-steps' },
{ text: 'API', link: '/pages/advanced/api-reference' },
{ text: 'Sponsors', link: '/pages/misc/sponsors' },
{ text: 'v1.x', link: '#' },
],
sidebar: [
{
text: 'Getting Started',
items: [
{ text: 'First steps', link: '/pages/getting-started/first-steps' },
{ text: 'Features', link: '/pages/getting-started/features' },
{
text: 'Examples',
items: [
{
text: 'JavaScript',
link: '/pages/getting-started/examples/commonjs',
},
{
text: 'TypeScript',
link: '/pages/getting-started/examples/typescript',
},
],
},
{
text: 'Upgrade guide v0.x -> v1.x',
link: '/pages/getting-started/upgrade-guide',
},
],
},
{
text: 'Advanced',
items: [
{ text: 'Public API', link: '/pages/advanced/api-reference' },
{
text: 'Request method aliases',
link: '/pages/advanced/request-method-aliases',
},
{
text: 'Creating an instance',
link: '/pages/advanced/create-an-instance',
},
{ text: 'Request config', link: '/pages/advanced/request-config' },
{ text: 'Adapters', link: '/pages/advanced/adapters' },
{ text: 'Response schema', link: '/pages/advanced/response-schema' },
{ text: 'Config defaults', link: '/pages/advanced/config-defaults' },
{ text: 'Interceptors', link: '/pages/advanced/interceptors' },
{ text: 'Error handling', link: '/pages/advanced/error-handling' },
{ text: 'Cancellation', link: '/pages/advanced/cancellation' },
{ text: 'Authentication', link: '/pages/advanced/authentication' },
{ text: 'Retry & error recovery', link: '/pages/advanced/retry' },
{ text: 'Testing', link: '/pages/advanced/testing' },
{
text: 'x-www-form-urlencoded format',
link: '/pages/advanced/x-www-form-urlencoded-format',
},
{
text: 'Multipart/form-data format',
link: '/pages/advanced/multipart-form-data-format',
},
{ text: 'File posting', link: '/pages/advanced/file-posting' },
{
text: 'HTML form processing 🔥',
link: '/pages/advanced/html-form-processing',
},
{
text: 'Progress capturing 🔥',
link: '/pages/advanced/progress-capturing',
},
{ text: 'Rate limiting 🔥', link: '/pages/advanced/rate-limiting' },
{
text: 'Headers 🔥',
items: [
{
text: 'General usage',
link: '/pages/advanced/headers',
},
{
text: 'Methods',
link: '/pages/advanced/header-methods',
},
],
},
{
text: 'Fetch adapter 🔥',
link: '/pages/advanced/fetch-adapter',
},
{ text: 'HTTP2 🔥', link: '/pages/advanced/http2' },
{ text: 'Promises', link: '/pages/advanced/promises' },
{ text: 'TypeScript', link: '/pages/advanced/type-script' },
],
},
{
text: 'Miscellaneous',
items: [
{ text: 'SemVer', link: '/pages/misc/semver' },
{ text: 'Security', link: '/pages/misc/security' },
],
},
],
socialLinks: [{ icon: 'github', link: 'https://github.com/axios/axios' }],
footer: {
message: 'axios is provided under MIT license',
+329
View File
@@ -0,0 +1,329 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: 'axios docs'
text: 'axios es un cliente HTTP simple para el navegador y Node.js'
image:
dark: /logo.svg
light: /logo-light.svg
alt: axios
actions:
- theme: brand
text: Comenzar
link: /es/pages/getting-started/first-steps
- theme: alt
text: Referencia de API
link: /es/pages/advanced/api-reference
features:
- title: Implementación sencilla
details: Comenzar con axios es tan simple como una sola línea de código. Las solicitudes API básicas se pueden realizar en 2 líneas de código.
- title: Interceptores potentes
details: Nuestro innovador sistema de interceptores le permite controlar el ciclo de vida de solicitudes y respuestas. Puede modificar solicitudes, respuestas y errores.
- title: Soporte para TypeScript
details: axios declara tipos y tiene soporte completo para TypeScript. Esto significa que puede usar axios con confianza en sus proyectos TypeScript.
---
<script setup>
import Splide from '@splidejs/splide';
import { onMounted } from 'vue';
import allSponsors from '../data/sponsors.json';
onMounted(() => {
new Splide(
'.splide',
{
type: 'loop',
autoplay: true,
interval: 3000,
perPage: 5,
perMove: 1,
gap: 10,
snap: true,
pagination: false,
breakpoints: {
1200: {
perPage: 4,
},
960: {
perPage: 3,
},
640: {
perPage: 2,
},
480: {
perPage: 1,
},
},
}
).mount();
});
const activePlatinumSponsors = allSponsors.platinum.filter((sponsor) => sponsor.active);
const activeGoldSponsors = allSponsors.gold.filter((sponsor) => sponsor.active);
const activeSilverSponsors = allSponsors.silver.filter((sponsor) => sponsor.active);
const sponsors = [...activePlatinumSponsors, ...activeGoldSponsors, ...activeSilverSponsors];
const capitalizeFirstLetter = (word) => {
return String(word).charAt(0).toUpperCase() + String(word).slice(1);
};
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css">
<div style="margin: 0 auto; max-width: 1200px;">
<h3 style="line-height: 64px;font-size: 28px;letter-spacing: -0.4px;font-weight: 600;margin-top: 2rem;">Patrocinadores</h3>
</div>
<div v-if="sponsors.length > 0" :class="$style.container" class="splide">
<div class="splide__track">
<div role="list" class="splide__list">
<div v-for="(sponsor, key) in sponsors" :key="sponsor.name" :class="$style.cardWrapper" :style="key === 0 ? 'margin-left: 0.5rem' : key === sponsors.length - 1 ? 'margin-right: 0.5rem' : ''" class="splide__slide">
<div :class="$style.imgWrapper">
<img :class="$style.img" :src="sponsor.imageUrl" alt="" />
</div>
<div style="padding-left: 0.5rem; padding-right: 0.5rem; height: 100%;">
<p :class="$style.heading">{{ sponsor.name }}</p>
<dl :class="$style.cardDl">
<dd style="margin-top: 0.75rem; margin-inline-start: 0px;">
<span :class="$style[`tagSponsor${capitalizeFirstLetter(sponsor.tier)}`]">{{ capitalizeFirstLetter(sponsor.tier) }}</span>
</dd>
</dl>
</div>
<div>
<div :class="$style.linksWrapper">
<div :class="$style.link">
<a :href="sponsor.website" :class="$style.rightLink" target="_blank">
<div :class="$style.linkIcon">
<svg data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="m20.893 13.393-1.135-1.135a2.252 2.252 0 0 1-.421-.585l-1.08-2.16a.414.414 0 0 0-.663-.107.827.827 0 0 1-.812.21l-1.273-.363a.89.89 0 0 0-.738 1.595l.587.39c.59.395.674 1.23.172 1.732l-.2.2c-.212.212-.33.498-.33.796v.41c0 .409-.11.809-.32 1.158l-1.315 2.191a2.11 2.11 0 0 1-1.81 1.025 1.055 1.055 0 0 1-1.055-1.055v-1.172c0-.92-.56-1.747-1.414-2.089l-.655-.261a2.25 2.25 0 0 1-1.383-2.46l.007-.042a2.25 2.25 0 0 1 .29-.787l.09-.15a2.25 2.25 0 0 1 2.37-1.048l1.178.236a1.125 1.125 0 0 0 1.302-.795l.208-.73a1.125 1.125 0 0 0-.578-1.315l-.665-.332-.091.091a2.25 2.25 0 0 1-1.591.659h-.18c-.249 0-.487.1-.662.274a.931.931 0 0 1-1.458-1.137l1.411-2.353a2.25 2.25 0 0 0 .286-.76m11.928 9.869A9 9 0 0 0 8.965 3.525m11.928 9.868A9 9 0 1 1 8.965 3.525"></path>
</svg>
</div>
</a>
</div>
<div v-if="sponsor.twitter" :class="$style.link" style="margin-left: -1px;">
<a :href="sponsor.twitter" :class="$style.leftLink" target="_blank">
<div :class="$style.linkIcon">
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" fill="currentColor" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 462.799"><path fill-rule="nonzero" d="M403.229 0h78.506L310.219 196.04 512 462.799H354.002L230.261 301.007 88.669 462.799h-78.56l183.455-209.683L0 0h161.999l111.856 147.88L403.229 0zm-27.556 415.805h43.505L138.363 44.527h-46.68l283.99 371.278z"/></svg>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style module>
.container {
display: flex;
margin: 0 auto;
max-width: 1200px;
}
.cardWrapper {
display: flex;
flex-direction: column;
grid-column: span 1 / span 1;
border-radius: 0.5rem;
border: 1px solid var(--vp-c-gutter) !important;
text-align: center;
background-color: var(--card-background-color) !important;
width: 100%;
max-width: 11.5rem;
scroll-snap-align: center;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
flex-shrink: 0 !important;
margin-bottom: 0.5rem !important;
margin-top: 0.5rem !important;
margin-left: auto;
margin-right: auto;
}
.imgWrapper {
display: flex;
padding: 1.75rem;
padding-bottom: 0.75rem;
flex-direction: column;
flex: 1 1 0%;
align-items: center;
justify-content: center;
}
.img {
width: 8rem;
height: 8rem;
}
.heading {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 3rem;
margin-top: 1rem !important;
font-size: 1rem !important;
line-height: 1.5rem !important;
font-weight: 600 !important;
color: var(--vp-c-text-1) !important;
text-wrap-style: pretty;
display: -webkit-box;
}
.cardDl {
display: flex;
margin-top: 0.25rem;
flex-direction: column;
flex-grow: 1;
justify-content: space-between;
}
.tagSponsorPlatinum {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #000;
background-color: #E5E7EB;
}
.tagSponsorGold {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #F59E0B;
}
.tagSponsorSilver {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #9CA3AF;
}
.tagSponsorBronze {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #854D0E;
}
.tagSponsorBacker {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #2563EB;
}
.linksWrapper {
display: flex;
margin-top: -1px;
}
.link {
display: flex;
flex: 1 1 0%;
width: 0;
}
.rightLink {
display: inline-flex;
position: relative;
padding-top: 1rem;
padding-bottom: 1rem;
margin-right: -1px;
flex: 1 1 0%;
column-gap: 0.75rem;
justify-content: center;
align-items: center;
border-bottom-left-radius: 0.5rem;
border-top: 1px;
border-right: 1px;
border-left: 0px;
border-bottom: 0px;
border-style: solid;
border-color: var(--vp-c-gutter);
width: 0;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #111827;
}
.leftLink {
display: inline-flex;
position: relative;
padding-top: 1rem;
padding-bottom: 1rem;
flex: 1 1 0%;
column-gap: 0.75rem;
justify-content: center;
align-items: center;
border-bottom-right-radius: 0.5rem;
border-top: 1px;
border-left: 0px;
border-bottom: 0px;
border-right: 0px;
border-style: solid;
border-color: var(--vp-c-gutter);
width: 0;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #111827;
}
.linkIcon {
width: 1.25rem;
height: 1.25rem;
color: #9CA3AF;
}
</style>
+88
View File
@@ -0,0 +1,88 @@
# Adaptadores
Los adaptadores te permiten personalizar la forma en que axios maneja los datos de la solicitud. De forma predeterminada, axios usa una lista de prioridad ordenada de `['xhr', 'http', 'fetch']` y selecciona el primer adaptador que sea compatible con el entorno actual. En la práctica, esto significa que `xhr` se usa en los navegadores, `http` en Node.js y `fetch` en entornos donde ninguno de los dos está disponible (como Cloudflare Workers o Deno).
Escribir tu propio adaptador te permite controlar completamente cómo axios realiza una solicitud y procesa la respuesta — útil para pruebas, transportes personalizados o entornos no estándar.
## Adaptadores integrados
Puedes seleccionar un adaptador integrado por nombre usando la opción de configuración `adapter`:
```js
// Use the fetch adapter
const instance = axios.create({ adapter: "fetch" });
// Use the XHR adapter (browser default)
const instance = axios.create({ adapter: "xhr" });
// Use the HTTP adapter (Node.js default)
const instance = axios.create({ adapter: "http" });
```
También puedes pasar un arreglo de nombres de adaptadores. axios usará el primero que sea compatible con el entorno actual:
```js
const instance = axios.create({ adapter: ["fetch", "xhr", "http"] });
```
Para más detalles sobre el adaptador `fetch`, consulta la página del [Adaptador Fetch](/pages/advanced/fetch-adapter).
## Crear un adaptador personalizado
Para crear un adaptador personalizado, escribe una función que acepte un objeto `config` y devuelva una Promise que se resuelva en un objeto de respuesta de axios válido.
```js
import axios from "axios";
import { settle } from "axios/unsafe/core/settle.js";
function myAdapter(config) {
/**
* At this point:
* - config has been merged with defaults
* - request transformers have run
* - request interceptors have run
*
* The adapter is now responsible for making the request
* and returning a valid response object.
*/
return new Promise((resolve, reject) => {
// Perform your custom request logic here.
// This example uses the native fetch API as a starting point.
fetch(config.url, {
method: config.method?.toUpperCase() ?? "GET",
headers: config.headers?.toJSON() ?? {},
body: config.data,
signal: config.signal,
})
.then(async (fetchResponse) => {
const responseData = await fetchResponse.text();
const response = {
data: responseData,
status: fetchResponse.status,
statusText: fetchResponse.statusText,
headers: Object.fromEntries(fetchResponse.headers.entries()),
config,
request: null,
};
// settle resolves or rejects the promise based on the HTTP status
settle(resolve, reject, response);
/**
* After this point:
* - response transformers will run
* - response interceptors will run
*/
})
.catch(reject);
});
}
const instance = axios.create({ adapter: myAdapter });
```
::: tip
El helper `settle` resuelve la Promise para códigos de estado 2xx y la rechaza para todo lo demás, siguiendo el comportamiento predeterminado de axios. Si deseas una validación de estado personalizada, usa la opción de configuración `validateStatus`.
:::
+331
View File
@@ -0,0 +1,331 @@
# Referencia de la API
A continuación se presenta una lista de todas las funciones y clases disponibles en el paquete axios. Estas funciones pueden usarse e importarse en tu proyecto. Todas ellas están protegidas por nuestro renovado compromiso de seguir el versionado semántico. Esto significa que puedes confiar en que estas funciones y clases permanecerán estables y sin cambios en futuras versiones, salvo que se realice un cambio de versión mayor.
## Instancia
La instancia `axios` es el objeto principal que usarás para realizar solicitudes HTTP. Es una función de fábrica que crea una nueva instancia de la clase `Axios`. La instancia `axios` cuenta con una serie de métodos para hacer solicitudes HTTP, los cuales están documentados en la [sección de alias de solicitud](/pages/advanced/request-method-aliases) de la documentación.
## Clases
### `Axios`
La clase `Axios` es la clase principal que usarás para realizar solicitudes HTTP. Es una función de fábrica que crea una nueva instancia de la clase `Axios`. La clase `Axios` cuenta con una serie de métodos para hacer solicitudes HTTP, los cuales están documentados en la [sección de alias de solicitud](/pages/advanced/request-method-aliases) de la documentación.
#### `constructor`
Crea una nueva instancia de la clase `Axios`. El constructor acepta un objeto de configuración opcional como argumento.
```ts
constructor(instanceConfig?: AxiosRequestConfig);
```
#### `request`
Gestiona la invocación de la solicitud y la resolución de la respuesta. Este es el método principal que usarás para hacer solicitudes HTTP. Acepta un objeto de configuración como argumento y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
request(configOrUrl: string | AxiosRequestConfig<D>, config: AxiosRequestConfig<D>): Promise<AxiosResponse<T>>;
```
### `CancelToken` <Badge type="danger" text="Obsoleto en favor de AbortController" />
La clase `CancelToken` estaba basada en la propuesta `tc39/proposal-cancelable-promises`. Se usaba para crear un token que permitiera cancelar una solicitud HTTP. La clase `CancelToken` está ahora obsoleta en favor de la API `AbortController`.
A partir de la versión 0.22.0, la clase `CancelToken` está obsoleta y será eliminada en una versión futura. Se recomienda usar la API `AbortController` en su lugar.
La clase se exporta principalmente por compatibilidad con versiones anteriores y será eliminada en una versión futura. Desaconsejamos fuertemente su uso en proyectos nuevos, por lo que no documentamos su API.
## Funciones
### `AxiosError`
La clase `AxiosError` es una clase de error que se lanza cuando una solicitud HTTP falla. Extiende la clase `Error` y añade propiedades adicionales al objeto de error.
#### `constructor`
Crea una nueva instancia de la clase `AxiosError`. El constructor acepta opcionalmente un mensaje, un código, una configuración, una solicitud y una respuesta como argumentos.
```ts
constructor(message?: string, code?: string, config?: InternalAxiosRequestConfig<D>, request?: any, response?: AxiosResponse<T, D>);
```
#### `properties`
La clase `AxiosError` proporciona las siguientes propiedades:
```ts
// Instancia de configuración.
config?: InternalAxiosRequestConfig<D>;
// Código de error.
code?: string;
// Instancia de solicitud.
request?: any;
// Instancia de respuesta.
response?: AxiosResponse<T, D>;
// Booleano que indica si el error es un `AxiosError`.
isAxiosError: boolean;
// Código de estado HTTP del error.
status?: number;
// Método auxiliar para convertir el error a un objeto JSON.
toJSON: () => object;
// Causa del error.
cause?: Error;
```
### `AxiosHeaders`
La clase `AxiosHeaders` es una clase de utilidad que se usa para gestionar encabezados HTTP. Provee métodos para manipular encabezados, como añadir, eliminar y obtener encabezados.
Aquí solo se documentan los métodos principales. Para una lista completa de métodos, consulta el archivo de declaración de tipos.
#### `constructor`
Crea una nueva instancia de la clase `AxiosHeaders`. El constructor acepta opcionalmente un objeto de encabezados como argumento.
```ts
constructor(headers?: RawAxiosHeaders | AxiosHeaders | string);
```
#### `set`
Agrega un encabezado al objeto de encabezados.
```ts
set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;
set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;
```
#### `get`
Obtiene un encabezado del objeto de encabezados.
```ts
get(headerName: string, parser: RegExp): RegExpExecArray | null;
get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;
```
#### `has`
Verifica si un encabezado existe en el objeto de encabezados.
```ts
has(header: string, matcher?: AxiosHeaderMatcher): boolean;
```
#### `delete`
Elimina un encabezado del objeto de encabezados.
```ts
delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;
```
#### `clear`
Elimina todos los encabezados del objeto de encabezados.
```ts
clear(matcher?: AxiosHeaderMatcher): boolean;
```
#### `normalize`
Normaliza el objeto de encabezados.
```ts
normalize(format: boolean): AxiosHeaders;
```
#### `concat`
Concatena objetos de encabezados.
```ts
concat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;
```
#### `toJSON`
Convierte el objeto de encabezados a un objeto JSON.
```ts
toJSON(asStrings?: boolean): RawAxiosHeaders;
```
### `CanceledError` <Badge type="tip" text="Extiende AxiosError" />
La clase `CanceledError` es una clase de error que se lanza cuando se cancela una solicitud HTTP. Extiende la clase `AxiosError`.
### `Cancel` <Badge type="tip" text="Alias de CanceledError" />
La clase `Cancel` es un alias de la clase `CanceledError`. Se exporta por compatibilidad con versiones anteriores y será eliminada en una versión futura.
### `isCancel`
Una función que verifica si un error es un `CanceledError`. Es útil para distinguir cancelaciones intencionales de errores inesperados.
```ts
isCancel(value: any): boolean;
```
```js
import axios from "axios";
const controller = new AbortController();
axios.get("/api/data", { signal: controller.signal }).catch((error) => {
if (axios.isCancel(error)) {
console.log("Request was cancelled:", error.message);
} else {
console.error("Unexpected error:", error);
}
});
controller.abort("User navigated away");
```
### `isAxiosError`
Una función que verifica si un error es un `AxiosError`. Úsala en bloques `catch` para acceder de forma segura a las propiedades específicas de axios como `error.response` y `error.config`.
```ts
isAxiosError(value: any): value is AxiosError;
```
```js
import axios from "axios";
try {
await axios.get("/api/resource");
} catch (error) {
if (axios.isAxiosError(error)) {
// error.response, error.config, error.code are all available
console.error("HTTP error", error.response?.status, error.message);
} else {
// A non-axios error (e.g. a programming mistake)
throw error;
}
}
```
### `all` <Badge type="danger" text="Obsoleto en favor de Promise.all" />
La función `all` es una función de utilidad que acepta un arreglo de promises y devuelve una única Promise que se resuelve cuando todas las promises del arreglo se han resuelto. La función `all` está ahora obsoleta en favor del método `Promise.all`. Se recomienda usar el método `Promise.all` en su lugar.
A partir de la versión 0.22.0, la función `all` está obsoleta y será eliminada en una versión futura. Se recomienda usar el método `Promise.all` en su lugar.
### `spread`
La función `spread` es una función de utilidad que puede usarse para distribuir un arreglo de argumentos en una llamada a función. Es útil cuando tienes un arreglo de argumentos que deseas pasar a una función que acepta múltiples argumentos.
```ts
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
```
### `toFormData`
Convierte un objeto JavaScript plano (o anidado) a una instancia de `FormData`. Es útil cuando deseas construir datos de formulario multipart de forma programática a partir de un objeto.
```ts
toFormData(sourceObj: object, formData?: FormData, options?: FormSerializerOptions): FormData;
```
```js
import { toFormData } from "axios";
const data = { name: "Jay", avatar: fileBlob };
const form = toFormData(data);
// form is now a FormData instance ready to post
await axios.post("/api/users", form);
```
### `formToJSON`
Convierte una instancia de `FormData` de vuelta a un objeto JavaScript plano. Es útil para leer datos de formulario en un formato estructurado.
```ts
formToJSON(form: FormData): object;
```
```js
import { formToJSON } from "axios";
const form = new FormData();
form.append("name", "Jay");
form.append("role", "admin");
const obj = formToJSON(form);
console.log(obj); // { name: "Jay", role: "admin" }
```
### `getAdapter`
Resuelve y devuelve una función de adaptador por nombre o pasando un arreglo de nombres candidatos. axios usa esto internamente para seleccionar el mejor adaptador disponible para el entorno actual.
```ts
getAdapter(adapters: string | string[]): AxiosAdapter;
```
```js
import { getAdapter } from "axios";
// Get the fetch adapter explicitly
const fetchAdapter = getAdapter("fetch");
// Get the best available adapter from a priority list
const adapter = getAdapter(["fetch", "xhr", "http"]);
```
### `mergeConfig`
Combina dos objetos de configuración de axios, aplicando la misma estrategia de fusión profunda que axios usa internamente al combinar los valores predeterminados con las opciones por solicitud. Los valores posteriores tienen precedencia.
```ts
mergeConfig<T>(config1: AxiosRequestConfig<T>, config2: AxiosRequestConfig<T>): AxiosRequestConfig<T>;
```
```js
import { mergeConfig } from "axios";
const base = { baseURL: "https://api.example.com", timeout: 5000 };
const override = { timeout: 10000, headers: { "X-Custom": "value" } };
const merged = mergeConfig(base, override);
// { baseURL: "https://api.example.com", timeout: 10000, headers: { "X-Custom": "value" } }
```
## Constantes
### `HttpStatusCode`
Un objeto que contiene una lista de códigos de estado HTTP como constantes con nombre. Úsalo para escribir condicionales legibles en lugar de números directos.
```js
import axios, { HttpStatusCode } from "axios";
try {
const response = await axios.get("/api/resource");
} catch (error) {
if (axios.isAxiosError(error)) {
if (error.response?.status === HttpStatusCode.NotFound) {
console.error("Resource not found");
} else if (error.response?.status === HttpStatusCode.Unauthorized) {
console.error("Authentication required");
}
}
}
```
## Miscelánea
### `VERSION`
La versión actual del paquete `axios`. Es una cadena que representa el número de versión del paquete. Se actualiza con cada nueva versión del paquete.
+142
View File
@@ -0,0 +1,142 @@
# Autenticación
La mayoría de las APIs requieren alguna forma de autenticación. Esta página cubre los patrones más comunes para adjuntar credenciales a las solicitudes de axios.
## Tokens Bearer (JWT)
El enfoque más común es adjuntar un JWT en el encabezado `Authorization`. La forma más limpia de hacerlo es a través de un interceptor de solicitud en tu instancia de axios, de manera que el token se lea de nuevo en cada solicitud:
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
api.interceptors.request.use((config) => {
const token = localStorage.getItem("access_token");
if (token) {
config.headers.set("Authorization", `Bearer ${token}`);
}
return config;
});
```
## Autenticación HTTP Basic
Para APIs que usan autenticación HTTP Basic, pasa la opción `auth`. axios codificará las credenciales y establecerá el encabezado `Authorization` automáticamente:
```js
const response = await axios.get("https://api.example.com/data", {
auth: {
username: "myUser",
password: "myPassword",
},
});
```
::: tip
Para tokens Bearer y claves de API, usa un encabezado `Authorization` personalizado en lugar de la opción `auth``auth` es solo para HTTP Basic.
:::
## Claves de API
Las claves de API generalmente se pasan como un encabezado o como un parámetro de consulta, dependiendo de lo que espere la API:
```js
// As a header
const api = axios.create({
baseURL: "https://api.example.com",
headers: { "X-API-Key": "your-api-key-here" },
});
// As a query parameter
const response = await axios.get("https://api.example.com/data", {
params: { apiKey: "your-api-key-here" },
});
```
## Renovación de token
Cuando los tokens de acceso expiran, es necesario renovarlos de forma silenciosa y reintentar la solicitud fallida. Un interceptor de respuesta es el lugar adecuado para implementar esto:
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
// Track whether a refresh is already in progress to avoid parallel refresh calls
let isRefreshing = false;
let failedQueue = [];
const processQueue = (error, token = null) => {
failedQueue.forEach((prom) => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});
failedQueue = [];
};
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
if (isRefreshing) {
// Queue the request until the refresh completes
return new Promise((resolve, reject) => {
failedQueue.push({ resolve, reject });
})
.then((token) => {
originalRequest.headers["Authorization"] = `Bearer ${token}`;
return api(originalRequest);
})
.catch((err) => Promise.reject(err));
}
originalRequest._retry = true;
isRefreshing = true;
try {
const { data } = await axios.post("/auth/refresh", {
refreshToken: localStorage.getItem("refresh_token"),
});
const newToken = data.access_token;
localStorage.setItem("access_token", newToken);
api.defaults.headers.common["Authorization"] = `Bearer ${newToken}`;
processQueue(null, newToken);
return api(originalRequest);
} catch (refreshError) {
processQueue(refreshError, null);
// Redirect to login or emit an event
localStorage.removeItem("access_token");
window.location.href = "/login";
return Promise.reject(refreshError);
} finally {
isRefreshing = false;
}
}
return Promise.reject(error);
}
);
```
## Autenticación basada en cookies
Para APIs basadas en sesiones que dependen de cookies, establece `withCredentials: true` para incluir cookies en solicitudes de origen cruzado:
```js
const api = axios.create({
baseURL: "https://api.example.com",
withCredentials: true, // send cookies with every request
});
```
::: warning
`withCredentials: true` requiere que el servidor responda con `Access-Control-Allow-Credentials: true` y un valor específico (no comodín) en `Access-Control-Allow-Origin`.
:::
+70
View File
@@ -0,0 +1,70 @@
# Cancelación
A partir de la versión v0.22.0, Axios es compatible con AbortController para cancelar solicitudes de forma limpia. Esta característica está disponible en el navegador y en Node.js cuando se usa una versión de Axios que admite AbortController. Para cancelar una solicitud, debes crear una instancia de `AbortController` y pasar su `signal` a la opción `signal` de la solicitud.
```js
const controller = new AbortController();
axios
.get("/foo/bar", {
signal: controller.signal,
})
.then(function (response) {
//...
});
// cancel the request
controller.abort();
```
## CancelToken <Badge type="danger" text="Obsoleto" />
También puedes usar la API `CancelToken` para cancelar solicitudes. Esta API está obsoleta y será eliminada en la próxima versión mayor. Se recomienda usar `AbortController` en su lugar. Puedes crear un token de cancelación usando la fábrica `CancelToken.source` como se muestra a continuación:
```js
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios
.get("/user/12345", {
cancelToken: source.token,
})
.catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log("Request canceled", thrown.message);
} else {
// handle error
}
});
axios.post(
"/user/12345",
{
name: "new name",
},
{
cancelToken: source.token,
}
);
// cancel the request (the message parameter is optional)
source.cancel("Operation canceled by the user.");
```
También puedes crear un token de cancelación pasando una función ejecutora al constructor de `CancelToken`:
```js
const CancelToken = axios.CancelToken;
let cancel;
axios.get("/user/12345", {
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
}),
});
// cancel the request
cancel();
```
Puedes cancelar varias solicitudes con el mismo token de cancelación o controlador de cancelación. Si un token de cancelación ya fue cancelado en el momento en que se inicia una solicitud de Axios, la solicitud se cancela inmediatamente, sin intentar realizar ninguna solicitud real.
+48
View File
@@ -0,0 +1,48 @@
# Valores predeterminados de configuración
axios te permite especificar valores predeterminados de configuración que se aplicarán a cada solicitud. Puedes definir valores predeterminados para `baseURL`, `headers`, `timeout` y otras propiedades. A continuación se muestra un ejemplo de cómo usar los valores predeterminados de configuración:
```js
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/posts";
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN;
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
```
## Valores predeterminados personalizados por instancia
Las instancias de axios se declaran con sus propios valores predeterminados al ser creadas. Estos valores pueden sobreescribirse estableciendo la propiedad `defaults` en la instancia. A continuación se muestra un ejemplo de cómo usar valores predeterminados personalizados por instancia:
```js
var instance = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/posts",
timeout: 1000,
headers: { Authorization: "foobar" },
});
instance.defaults.headers.common["Authorization"] = AUTH_TOKEN;
```
## Orden de precedencia de la configuración
La configuración se combinará con un orden de precedencia. El orden es el siguiente: primero se establecen los valores predeterminados de la librería, luego las propiedades predeterminadas de la instancia y, finalmente, el argumento de configuración de la solicitud. A continuación se muestra un ejemplo del orden de precedencia.
Primero, vamos a crear una instancia con los valores predeterminados que proporciona la librería. En este punto, el valor de configuración de timeout es `0`, que es el valor predeterminado de la librería.
```js
const instance = axios.create();
```
Ahora sobreescribiremos el timeout predeterminado de la instancia a `2500` milisegundos. A partir de ahora, todas las solicitudes que usen esta instancia esperarán 2.5 segundos antes de expirar.
```js
instance.defaults.timeout = 2500;
```
Finalmente, haremos una solicitud con un timeout de `5000` milisegundos. Esta solicitud esperará 5 segundos antes de expirar.
```js
instance.get("/longRequest", {
timeout: 5000,
});
```
@@ -0,0 +1,87 @@
# Crear una instancia
`axios.create()` te permite crear una instancia de axios preconfigurada. La instancia comparte la misma API de solicitud y respuesta que el objeto `axios` predeterminado, pero utiliza la configuración que proporciones como base para cada solicitud. Esta es la forma recomendada de usar axios en cualquier aplicación que conste de más de un solo archivo.
```ts
import axios from "axios";
const instance = axios.create({
baseURL: "https://api.example.com",
timeout: 5000,
headers: { "X-Custom-Header": "foobar" },
});
```
El método `create` acepta el objeto completo de [Configuración de solicitud](/pages/advanced/request-config). Luego puedes usar la instancia igual que el objeto axios predeterminado:
```js
const response = await instance.get("/users/1");
```
## ¿Por qué usar una instancia?
### URL base por servicio
En la mayoría de las aplicaciones se interactúa con más de una API. Crear una instancia separada por servicio evita repetir la URL base en cada llamada:
```js
const githubApi = axios.create({ baseURL: "https://api.github.com" });
const internalApi = axios.create({ baseURL: "https://api.internal.example.com" });
const { data: repos } = await githubApi.get("/users/axios/repos");
const { data: users } = await internalApi.get("/users");
```
### Encabezados de autenticación compartidos
Adjunta un token de autenticación a cada solicitud de una instancia sin afectar a las demás:
```js
const authApi = axios.create({
baseURL: "https://api.example.com",
headers: {
Authorization: `Bearer ${getToken()}`,
},
});
```
### Tiempos de espera y reintentos por servicio
Los distintos servicios tienen características de fiabilidad diferentes. Define un tiempo de espera corto para servicios en tiempo real y uno más largo para trabajos por lotes:
```js
const realtimeApi = axios.create({ baseURL: "https://realtime.example.com", timeout: 2000 });
const batchApi = axios.create({ baseURL: "https://batch.example.com", timeout: 60000 });
```
### Interceptores aislados
Los interceptores añadidos a una instancia solo se aplican a esa instancia, manteniendo tus responsabilidades separadas:
```js
const loggingApi = axios.create({ baseURL: "https://api.example.com" });
loggingApi.interceptors.request.use((config) => {
console.log(`${config.method?.toUpperCase()} ${config.url}`);
return config;
});
```
## Sobreescribir los valores predeterminados por solicitud
La configuración pasada en el momento de la solicitud siempre tiene prioridad sobre los valores predeterminados de la instancia:
```js
const api = axios.create({ timeout: 5000 });
// This specific request uses a 30-second timeout instead
await api.get("/slow-endpoint", { timeout: 30000 });
```
::: tip
Los valores predeterminados de la instancia también pueden cambiarse después de su creación escribiendo en `instance.defaults`:
```js
instance.defaults.headers.common["Authorization"] = `Bearer ${newToken}`;
```
:::
+72
View File
@@ -0,0 +1,72 @@
# Manejo de errores
axios puede lanzar muchos tipos diferentes de errores. Algunos de estos errores son causados por el propio axios, mientras que otros son causados por el servidor o el cliente. La siguiente tabla lista la estructura general del error lanzado:
| Propiedad | Definición |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| message | Un resumen rápido del mensaje de error y el estado con el que falló. |
| name | Define el origen del error. Para axios, siempre será un `AxiosError`. |
| stack | Proporciona el seguimiento de la pila (stack trace) del error. |
| config | Un objeto de configuración de axios con configuraciones específicas de la instancia definidas por el usuario al momento de realizar la solicitud. |
| code | Representa un error identificado por axios. La tabla a continuación lista definiciones específicas para errores internos de axios. |
| status | Código de estado HTTP de la respuesta. Consulta [aquí](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) para conocer los significados comunes de los códigos de estado HTTP. |
A continuación se lista una relación de posibles errores identificados por axios:
| Código | Definición |
| ------------------------- | --------------------------------------------------------------------------------------------- |
| ERR_BAD_OPTION_VALUE | Valor inválido o no compatible proporcionado en la configuración de axios. |
| ERR_BAD_OPTION | Opción inválida proporcionada en la configuración de axios. |
| ECONNABORTED | Generalmente indica que la solicitud ha expirado (salvo que `transitional.clarifyTimeoutError` esté activado) o fue abortada por el navegador o un complemento del mismo. |
| ETIMEDOUT | La solicitud expiró al superar el límite de tiempo predeterminado de axios. Se debe activar `transitional.clarifyTimeoutError` en `true`, de lo contrario se lanzará un error genérico `ECONNABORTED`. |
| ERR_NETWORK | Problema relacionado con la red. En el navegador, este error también puede ser causado por una violación de la política [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) o [Mixed Content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content). El navegador no permite que el código JS aclare la razón real del error por motivos de seguridad; por eso, revisa la consola. |
| ERR_FR_TOO_MANY_REDIRECTS | La solicitud fue redirigida demasiadas veces; supera el número máximo de redirecciones especificado en la configuración de axios. |
| ERR_DEPRECATED | Se usó una característica o método obsoleto en axios. |
| ERR_BAD_RESPONSE | La respuesta no puede ser analizada correctamente o tiene un formato inesperado. Generalmente relacionado con una respuesta con código de estado `5xx`. |
| ERR_BAD_REQUEST | La solicitud tiene un formato inesperado o le faltan parámetros requeridos. Generalmente relacionado con una respuesta con código de estado `4xx`. |
| ERR_CANCELED | La característica o método fue cancelado explícitamente por el usuario usando un AbortSignal (o un CancelToken). |
| ERR_NOT_SUPPORT | Característica o método no compatible en el entorno actual de axios. |
| ERR_INVALID_URL | URL inválida proporcionada para la solicitud de axios. |
## Manejo de errores
El comportamiento predeterminado de axios es rechazar la Promise si la solicitud falla. Sin embargo, también puedes capturar el error y manejarlo según lo consideres apropiado. A continuación se muestra un ejemplo de cómo capturar un error:
```js
axios.get("/user/12345").catch(function (error) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log("Error", error.message);
}
console.log(error.config);
});
```
Usando la opción de configuración `validateStatus`, puedes sobreescribir la condición predeterminada (status >= 200 && status < 300) y definir los códigos HTTP que deben lanzar un error.
```js
axios.get("/user/12345", {
validateStatus: function (status) {
return status < 500; // Resolve only if the status code is less than 500
},
});
```
Usando el método `toJSON`, puedes obtener un objeto con más información sobre el error.
```js
axios.get("/user/12345").catch(function (error) {
console.log(error.toJSON());
});
```
+81
View File
@@ -0,0 +1,81 @@
# Adaptador Fetch <Badge type="tip" text="Nuevo" />
El adaptador `fetch` es un nuevo adaptador que introdujimos a partir de la versión 1.7.0. Proporciona una forma de usar axios con la API `fetch`, dándote lo mejor de ambos mundos. De forma predeterminada, `fetch` se usará si los adaptadores `xhr` y `http` no están disponibles en la compilación o no son compatibles con el entorno. Para usarlo de forma predeterminada, debe seleccionarse explícitamente estableciendo la opción `adapter` en `fetch` al crear una instancia de axios.
```js
import axios from 'axios';
const instance = axios.create({
adapter: 'fetch',
});
```
El adaptador admite la misma funcionalidad que el adaptador `xhr`, incluyendo la captura del progreso de carga y descarga. También admite tipos de respuesta adicionales como `stream` y `formdata` (si el entorno lo soporta).
## Fetch personalizado <Badge type="tip" text="v1.12.0+" />
A partir de `v1.12.0`, puedes personalizar el adaptador fetch para que use una función `fetch` personalizada en lugar de la global del entorno. Puedes pasar una función `fetch` personalizada, y los constructores `Request` y `Response` a través de la opción de configuración `env`. Esto es útil cuando trabajas con entornos personalizados o frameworks de aplicación que proporcionan su propia implementación de `fetch`.
::: info
Al usar una función `fetch` personalizada, es posible que también necesites proporcionar constructores `Request` y `Response` correspondientes. Si los omites, se usarán los constructores globales. Si tu `fetch` personalizado es incompatible con los globales, pasa `null` para deshabilitarlos.
**Nota:** Establecer `Request` y `Response` en `null` hará imposible que el adaptador fetch capture el progreso de carga y descarga.
:::
### Ejemplo básico
```js
import customFetchFunction from 'customFetchModule';
const instance = axios.create({
adapter: 'fetch',
onDownloadProgress(e) {
console.log('downloadProgress', e);
},
env: {
fetch: customFetchFunction,
Request: null, // null -> disable the constructor
Response: null,
},
});
```
### Usando con Tauri
[Tauri](https://tauri.app/plugin/http-client/) proporciona una función `fetch` de plataforma que omite las restricciones CORS del navegador para las solicitudes realizadas desde la capa nativa. El ejemplo a continuación muestra una configuración mínima para usar axios dentro de una aplicación Tauri con ese fetch personalizado.
```js
import { fetch } from '@tauri-apps/plugin-http';
import axios from 'axios';
const instance = axios.create({
adapter: 'fetch',
onDownloadProgress(e) {
console.log('downloadProgress', e);
},
env: {
fetch,
},
});
const { data } = await instance.get('https://google.com');
```
### Usando con SvelteKit
[SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) proporciona una implementación personalizada de `fetch` para las funciones `load` del lado del servidor que gestiona el reenvío de cookies y URLs relativas. Dado que su `fetch` es incompatible con la API estándar de `URL`, axios debe configurarse para usarlo explícitamente, y los constructores globales `Request` y `Response` deben deshabilitarse.
```js
export async function load({ fetch }) {
const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', {
adapter: 'fetch',
env: {
fetch,
Request: null,
Response: null,
},
});
return { post };
}
```
+99
View File
@@ -0,0 +1,99 @@
# Publicación de archivos
axios facilita la subida de archivos. Usa `postForm` o `FormData` cuando necesites subidas en formato `multipart/form-data`.
## Archivo único (navegador)
Pasa un objeto `File` directamente como valor de campo — axios lo detectará y usará automáticamente el tipo de contenido correcto:
```js
await axios.postForm("https://httpbin.org/post", {
description: "My profile photo",
file: document.querySelector("#fileInput").files[0],
});
```
## Múltiples archivos (navegador)
Pasa un `FileList` para subir todos los archivos seleccionados a la vez. Todos se enviarán bajo el mismo nombre de campo (`files[]`):
```js
await axios.postForm(
"https://httpbin.org/post",
document.querySelector("#fileInput").files
);
```
Para usar nombres de campo distintos para cada archivo, construye un objeto `FormData` manualmente:
```js
const formData = new FormData();
formData.append("avatar", avatarFile);
formData.append("cover", coverFile);
await axios.post("https://httpbin.org/post", formData);
```
## Seguimiento del progreso de la carga (navegador)
Usa el callback `onUploadProgress` para mostrar una barra de progreso o un porcentaje a tus usuarios:
```js
await axios.postForm("https://httpbin.org/post", {
file: document.querySelector("#fileInput").files[0],
}, {
onUploadProgress: (progressEvent) => {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`Upload progress: ${percent}%`);
},
});
```
Consulta [Captura de progreso](/pages/advanced/progress-capturing) para ver la lista completa de campos disponibles en el evento de progreso.
## Archivos en Node.js
En Node.js, usa `fs.createReadStream` para subir un archivo desde el sistema de archivos sin cargarlo completamente en memoria:
```js
import fs from "fs";
import FormData from "form-data";
import axios from "axios";
const form = new FormData();
form.append("file", fs.createReadStream("/path/to/file.jpg"));
form.append("description", "My uploaded file");
await axios.post("https://httpbin.org/post", form);
```
::: tip
El paquete npm `form-data` es necesario en entornos Node.js para crear objetos `FormData`. En versiones modernas de Node.js (v18+), el `FormData` global está disponible de forma nativa.
:::
## Subir un Buffer (Node.js)
También puedes subir un `Buffer` en memoria directamente:
```js
const buffer = Buffer.from("Hello, world!");
const form = new FormData();
form.append("file", buffer, {
filename: "hello.txt",
contentType: "text/plain",
knownLength: buffer.length,
});
await axios.post("https://httpbin.org/post", form);
```
::: warning
La captura del progreso de carga de `FormData` no está disponible actualmente en entornos Node.js.
:::
::: danger
Al subir un stream legible en Node.js, establece `maxRedirects: 0` para evitar que el paquete `follow-redirects` almacene todo el stream en memoria RAM.
:::
+188
View File
@@ -0,0 +1,188 @@
# Métodos de encabezados <Badge type="tip" text="Nuevo" />
Con la introducción de la nueva clase `AxiosHeaders`, Axios ofrece un conjunto de métodos para manipular encabezados. Estos métodos se usan para establecer, obtener y eliminar encabezados de una forma más conveniente que manipular directamente el objeto de encabezados.
## Constructor `new AxiosHeaders(headers?)`
El constructor de la clase `AxiosHeaders` acepta un objeto opcional con encabezados para inicializar la instancia. El objeto de encabezados puede contener cualquier número de encabezados, y las claves son insensibles a mayúsculas y minúsculas.
```js
constructor(headers?: RawAxiosHeaders | AxiosHeaders | string);
```
Por conveniencia, puedes pasar una cadena de texto con encabezados separados por un carácter de nueva línea. Los encabezados se analizan y se añaden a la instancia.
```js
const headers = new AxiosHeaders(`
Host: www.bing.com
User-Agent: curl/7.54.0
Accept: */*`);
console.log(headers);
// Object [AxiosHeaders] {
// host: 'www.bing.com',
// 'user-agent': 'curl/7.54.0',
// accept: '*/*'
// }
```
## Set (Establecer)
El método `set` se usa para establecer encabezados en la instancia de `AxiosHeaders`. El método puede ser llamado con un nombre de encabezado y un valor únicos, un objeto con múltiples encabezados, o una cadena de texto con encabezados separados por una nueva línea. El método también acepta un parámetro opcional `rewrite` que controla el comportamiento al establecer el encabezado.
```js
set(headerName, value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher);
set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string) => boolean);
set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean);
```
El argumento `rewrite` controla el comportamiento de sobreescritura:
- `false` - no sobreescribir si el valor del encabezado ya está definido (es decir, no es `undefined`)
- `undefined` (predeterminado) - sobreescribir el encabezado a menos que su valor esté establecido en `false`
- `true` - sobreescribir siempre
La opción también puede aceptar una función definida por el usuario que determina si el valor debe ser sobreescrito o no. La función recibe el valor actual, el nombre del encabezado y el objeto de encabezados como argumentos.
`AxiosHeaders` conserva el formato de la primera clave coincidente que encuentra. Puedes usar esto para preservar el formato específico de un encabezado inicializando una clave con `undefined` y luego estableciendo los valores posteriormente. Consulta [Preservar el formato de un encabezado específico](/pages/advanced/headers#preserving-a-specific-header-case).
## Get (Obtener)
El método `get` se usa para recuperar el valor de un encabezado. El método puede ser llamado con un nombre de encabezado único, un matcher opcional o un parser. El matcher tiene valor predeterminado `true`. El parser puede ser una expresión regular que se usa para extraer el valor del encabezado.
```js
get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;
get(headerName: string, parser: RegExp): RegExpExecArray | null;
```
A continuación se muestra un ejemplo de algunos de los posibles usos del método `get`:
```js
const headers = new AxiosHeaders({
'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h',
});
console.log(headers.get('Content-Type'));
// multipart/form-data; boundary=Asrf456BGe4h
console.log(headers.get('Content-Type', true)); // parse key-value pairs from a string separated with \s,;= delimiters:
// [Object: null prototype] {
// 'multipart/form-data': undefined,
// boundary: 'Asrf456BGe4h'
// }
console.log(
headers.get('Content-Type', (value, name, headers) => {
return String(value).replace(/a/g, 'ZZZ');
})
);
// multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h
console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]);
// boundary=Asrf456BGe4h
```
## Has (Verificar existencia)
El método `has` se usa para verificar si un encabezado existe en la instancia de `AxiosHeaders`. El método puede ser llamado con un nombre de encabezado único y un matcher opcional.
```js
has(header: string, matcher?: AxiosHeaderMatcher): boolean;
```
::: info
Devuelve `true` si el encabezado está definido (tiene un valor que no es `undefined`).
:::
## Delete (Eliminar)
El método `delete` se usa para eliminar un encabezado de la instancia de `AxiosHeaders`. El método puede ser llamado con un nombre de encabezado único y un matcher opcional.
```js
delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;
```
::: info
Devuelve `true` si al menos un encabezado fue eliminado.
:::
## Clear (Limpiar)
El método `clear` se usa para eliminar todos los encabezados de la instancia de `AxiosHeaders` si no se pasa ningún argumento. Si se pasa un matcher, solo se eliminan los encabezados que coincidan con él; en este caso, el matcher se compara contra el nombre del encabezado en lugar del valor.
```js
clear(matcher?: AxiosHeaderMatcher): boolean;
```
::: info
Devuelve `true` si al menos un encabezado fue eliminado.
:::
## Normalize (Normalizar)
Si el objeto de encabezados fue modificado directamente, puede generar duplicados con el mismo nombre pero en diferentes formatos. Este método normaliza el objeto de encabezados combinando claves duplicadas en una sola. Axios usa este método internamente después de llamar a cada interceptor. Establece `format` en `true` para convertir los nombres de los encabezados a minúsculas y capitalizar las letras iniciales (`cOntEnt-type` => `Content-Type`) o en `false` para mantener el formato original.
```js
const headers = new AxiosHeaders({
foo: '1',
});
headers.Foo = '2';
headers.FOO = '3';
console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' }
console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' }
console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' }
```
::: info
Devuelve `this` para encadenamiento.
:::
## Concat (Concatenar)
Combina la instancia con los objetivos en una nueva instancia de `AxiosHeaders`. Si el objetivo es una cadena de texto, se analizará como encabezados HTTP en formato RAW. Si el objetivo es una instancia de `AxiosHeaders`, se combinará con la instancia actual.
Esto es útil para formatos predefinidos de mayúsculas/minúsculas al componer encabezados. Por ejemplo:
```js
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
```
```js
concat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;
```
::: info
Devuelve una nueva instancia de `AxiosHeaders`.
:::
## toJSON
Resuelve todos los valores de encabezados internos en un nuevo objeto de prototipo nulo. Establece `asStrings` en `true` para resolver los arreglos como una cadena que contiene todos los elementos, separados por comas.
```js
toJSON(asStrings?: boolean): RawAxiosHeaders;
```
## From (Desde)
Devuelve una nueva instancia de `AxiosHeaders` creada a partir de los encabezados en bruto pasados, o simplemente devuelve el objeto de encabezados dado si ya es una instancia de `AxiosHeaders`.
```js
from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;
```
## Atajos
Los siguientes atajos están disponibles:
- `setContentType`, `getContentType`, `hasContentType`
- `setContentLength`, `getContentLength`, `hasContentLength`
- `setAccept`, `getAccept`, `hasAccept`
- `setUserAgent`, `getUserAgent`, `hasUserAgent`
- `setContentEncoding`, `getContentEncoding`, `hasContentEncoding`
+153
View File
@@ -0,0 +1,153 @@
# Encabezados <Badge type="tip" text="Nuevo" />
Axios expone su propia clase `AxiosHeaders` para manipular encabezados usando una API similar a Map que garantiza claves insensibles a mayúsculas y minúsculas. Esta clase es usada internamente por Axios para gestionar encabezados, pero también está disponible para el usuario por conveniencia. Aunque los encabezados HTTP no son sensibles a mayúsculas y minúsculas, Axios conservará el formato original del encabezado por razones estéticas y como solución alternativa cuando los servidores consideran erróneamente el caso del encabezado. La forma antigua de manipular directamente el objeto de encabezados sigue disponible, pero está obsoleta y no se recomienda para uso futuro.
## Trabajar con encabezados
La instancia del objeto `AxiosHeaders` puede contener diferentes tipos de valores internos que controlan la lógica de configuración y combinación. El objeto de encabezados final es obtenido por Axios mediante la llamada al método `toJSON`. El objeto `AxiosHeaders` también es iterable, por lo que puedes usarlo en bucles o convertirlo en un arreglo u objeto.
Los valores de los encabezados pueden ser de los siguientes tipos:
- `string` - valor de cadena de texto normal que se enviará al servidor
- `null` - omitir el encabezado al convertir a JSON
- `false` - omitir el encabezado al convertir a JSON; indica además que el método `set` debe ser llamado con la opción `rewrite` en `true` para sobreescribir este valor (Axios usa esto internamente para permitir que los usuarios opten por no instalar ciertos encabezados como `User-Agent` o `Content-Type`)
- `undefined` - el valor no está definido
::: warning
El valor del encabezado se considera definido si no es `undefined`.
:::
El objeto de encabezados siempre se inicializa dentro de los interceptores y transformadores, como se muestra en el siguiente ejemplo:
```js
axios.interceptors.request.use((request: InternalAxiosRequestConfig) => {
request.headers.set("My-header", "value");
request.headers.set({
"My-set-header1": "my-set-value1",
"My-set-header2": "my-set-value2",
});
// Disable subsequent setting of this header by Axios
request.headers.set("User-Agent", false);
request.headers.setContentType("text/plain");
// Direct access like this is deprecated
request.headers["My-set-header2"] = "newValue";
return request;
});
```
Puedes iterar sobre un `AxiosHeaders` usando cualquier método iterable, como un bucle for-of, forEach o el operador spread:
```js
const headers = new AxiosHeaders({
foo: '1',
bar: '2',
baz: '3',
});
for (const [header, value] of headers) {
console.log(header, value);
}
// foo 1
// bar 2
// baz 3
```
## Establecer encabezados en una solicitud
El lugar más común para establecer encabezados es la opción `headers` en la configuración de tu solicitud o en la configuración de la instancia:
```js
// On a single request
await axios.get('/api/data', {
headers: {
'Accept-Language': 'en-US',
'X-Request-ID': 'abc123',
},
});
// On an instance (applied to every request)
const api = axios.create({
headers: {
'X-App-Version': '2.0.0',
},
});
```
## Preservar el formato de un encabezado específico
Los nombres de encabezados de Axios son insensibles a mayúsculas y minúsculas, pero `AxiosHeaders` conserva el formato de la primera clave coincidente que encuentra. Si necesitas un formato específico para un servidor con comportamiento sensible a mayúsculas y minúsculas no estándar, define un formato predeterminado en `defaults` y luego establece los valores normalmente.
```js
const api = axios.create();
api.defaults.headers.common = {
'content-type': undefined,
accept: undefined,
};
await api.put(url, data, {
headers: {
'Content-Type': 'application/octet-stream',
Accept: 'application/json',
},
});
```
También puedes hacerlo directamente con `AxiosHeaders` al componer encabezados:
```js
import axios, { AxiosHeaders } from 'axios';
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
await axios.put(url, data, { headers });
```
## Establecer encabezados en un interceptor
Los interceptores son el lugar adecuado para adjuntar encabezados dinámicos como tokens de autenticación, ya que el token puede no estar disponible cuando la instancia se crea por primera vez:
```js
api.interceptors.request.use((config) => {
const token = getAuthToken(); // read at request time
config.headers.set('Authorization', `Bearer ${token}`);
return config;
});
```
## Leer encabezados de respuesta
Los encabezados de respuesta están disponibles en `response.headers` como una instancia de `AxiosHeaders`. Todos los nombres de encabezados están en minúsculas:
```js
const response = await axios.get('/api/data');
console.log(response.headers['content-type']);
// application/json; charset=utf-8
console.log(response.headers.get('x-request-id'));
// abc123
```
## Eliminar un encabezado predeterminado
Para optar por no incluir un encabezado que axios establece por defecto (como `Content-Type` o `User-Agent`), establece su valor en `false`:
```js
await axios.post('/api/data', payload, {
headers: {
'Content-Type': false, // let the browser set it automatically (e.g. for FormData)
},
});
```
Para más detalles sobre la API completa de métodos de `AxiosHeaders`, consulta la página de [Métodos de encabezados](/pages/advanced/header-methods).
@@ -0,0 +1,57 @@
# Envío de formularios HTML (navegador) <Badge type="tip" text="Nuevo" />
También puedes enviar un formulario directamente desde un elemento de formulario HTML. Esto es útil cuando tienes un formulario en tu página y deseas enviarlo sin escribir código JavaScript adicional.
```js
await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm'));
```
Los objetos `FormData` y `HTMLForm` también pueden enviarse como `JSON` estableciendo explícitamente el encabezado `Content-Type` en `application/json`:
```js
await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), {
headers: {
'Content-Type': 'application/json',
},
});
```
Un ejemplo de un formulario válido que puede ser enviado con el código anterior es:
```html
<form id="htmlForm">
<input type="text" name="foo" value="1" />
<input type="text" name="deep.prop" value="2" />
<input type="text" name="deep prop spaced" value="3" />
<input type="text" name="baz" value="4" />
<input type="text" name="baz" value="5" />
<select name="user.age">
<option value="value1">Value 1</option>
<option value="value2" selected>Value 2</option>
<option value="value3">Value 3</option>
</select>
<input type="submit" value="Save" />
</form>
```
El formulario anterior se enviará como:
```json
{
"foo": "1",
"deep": {
"prop": "2",
"prop spaced": "3"
},
"baz": ["4", "5"],
"user": {
"age": "value2"
}
}
```
::: warning
Actualmente no se admite el envío de Blobs/Files como JSON (base64).
:::
+72
View File
@@ -0,0 +1,72 @@
# HTTP2 <Badge type="warning" text="Experimental" /> <Badge type="tip" text="v1.13.0+" />
El soporte experimental de HTTP/2 fue añadido al adaptador `http` en la versión `1.13.0`. Solo está disponible en entornos Node.js.
## Uso básico
Usa la opción `httpVersion` para seleccionar la versión del protocolo para una solicitud. Establecerla en `2` habilita HTTP/2.
```js
const { data, headers, status } = await axios.post(
"https://httpbin.org/post",
form,
{
httpVersion: 2,
},
);
```
## `http2Options`
Las opciones nativas adicionales para la llamada interna `session.request()` pueden pasarse a través del objeto de configuración `http2Options`. Esto también incluye el parámetro personalizado `sessionTimeout`, que controla cuánto tiempo (en milisegundos) una sesión HTTP/2 inactiva se mantiene viva antes de cerrarse. Su valor predeterminado es `1000ms`.
```js
{
httpVersion: 2,
http2Options: {
rejectUnauthorized: false, // accept self-signed certificates (dev only)
sessionTimeout: 5000, // keep idle session alive for 5 seconds
},
}
```
::: warning
El soporte de HTTP/2 es actualmente experimental. La API puede cambiar en futuras versiones menores o de parche.
:::
## Ejemplo completo
El ejemplo a continuación envía una solicitud POST con `multipart/form-data` sobre HTTP/2 y rastrea tanto el progreso de carga como el de descarga.
```js
const form = new FormData();
form.append("foo", "123");
const { data, headers, status } = await axios.post(
"https://httpbin.org/post",
form,
{
httpVersion: 2,
http2Options: {
// rejectUnauthorized: false,
// sessionTimeout: 1000
},
onUploadProgress(e) {
console.log("upload progress", e);
},
onDownloadProgress(e) {
console.log("download progress", e);
},
responseType: "arraybuffer",
},
);
```
## Referencia de configuración
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
| `httpVersion` | `number` | `1` | Versión del protocolo HTTP a usar. Establece en `2` para habilitar HTTP/2. |
| `http2Options.sessionTimeout` | `number` | `1000` | Tiempo en milisegundos antes de que una sesión HTTP/2 inactiva se cierre. |
Todas las demás opciones nativas de `session.request()` compatibles con el módulo `http2` integrado de Node.js también pueden pasarse dentro de `http2Options`.
+116
View File
@@ -0,0 +1,116 @@
# Interceptores
Los interceptores son un mecanismo poderoso que puede usarse para interceptar y modificar solicitudes y respuestas HTTP. Son muy similares al middleware en Express.js. Un interceptor es una función que se ejecuta antes de enviar una solicitud y antes de recibir una respuesta. Los interceptores son útiles para una variedad de tareas como el registro de eventos (logging), la modificación de encabezados de solicitud y la modificación de la respuesta.
El uso básico de los interceptores es el siguiente:
```js
// Add a request interceptor
axios.interceptors.request.use(
function (config) {
// Do something before request is sent
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
// Add a response interceptor
axios.interceptors.response.use(
function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
},
function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
}
);
```
## Eliminar interceptores
Puedes eliminar cualquier interceptor usando el método `eject` sobre el interceptor que deseas eliminar. También puedes eliminar todos los interceptores llamando al método `clear` sobre el objeto `axios.interceptors`. A continuación se muestra un ejemplo de cómo eliminar un interceptor:
```js
// Eject the request interceptor
const myInterceptor = axios.interceptors.request.use(function () {
/*...*/
});
axios.interceptors.request.eject(myInterceptor);
// Eject the response interceptor
const myInterceptor = axios.interceptors.response.use(function () {
/*...*/
});
axios.interceptors.response.eject(myInterceptor);
```
A continuación se muestra un ejemplo de cómo eliminar todos los interceptores:
```js
const instance = axios.create();
instance.interceptors.request.use(function () {
/*...*/
});
instance.interceptors.request.clear(); // Removes interceptors from requests
instance.interceptors.response.use(function () {
/*...*/
});
instance.interceptors.response.clear(); // Removes interceptors from responses
```
## Comportamiento predeterminado de los interceptores
Cuando añades interceptores de solicitud, se asume que son asíncronos de forma predeterminada. Esto puede causar un retraso en la ejecución de tu solicitud axios cuando el hilo principal está bloqueado (se crea una Promise internamente para el interceptor y tu solicitud queda al final de la pila de llamadas). Si tus interceptores de solicitud son síncronos, puedes añadir un indicador al objeto de opciones que le indicará a axios que ejecute el código de forma síncrona y evite cualquier retraso en la ejecución de la solicitud.
```js
axios.interceptors.request.use(
function (config) {
config.headers.test = "I am only a header!";
return config;
},
null,
{ synchronous: true }
);
```
## Interceptores usando `runWhen`
Si deseas ejecutar un interceptor particular basándote en una verificación en tiempo de ejecución, puedes añadir una función `runWhen` al objeto de opciones. El interceptor no se ejecutará si y solo si el retorno de `runWhen` es `false`. La función se llamará con el objeto de configuración (recuerda que también puedes vincularle tus propios argumentos). Esto puede ser útil cuando tienes un interceptor de solicitud asíncrono que solo necesita ejecutarse en ciertos momentos.
```js
function onGetCall(config) {
return config.method === "get";
}
axios.interceptors.request.use(
function (config) {
config.headers.test = "special get headers";
return config;
},
null,
{ runWhen: onGetCall }
);
```
## Múltiples interceptores
Puedes añadir múltiples interceptores a la misma solicitud o respuesta. Lo siguiente aplica para múltiples interceptores en la misma cadena, en el orden indicado a continuación:
- Cada interceptor se ejecuta
- Los interceptores de solicitud se ejecutan en orden inverso (LIFO).
- Los interceptores de respuesta se ejecutan en el orden en que fueron añadidos (FIFO).
- Solo se devuelve el resultado del último interceptor
- Cada interceptor recibe el resultado de su predecesor
- Cuando el interceptor de cumplimiento lanza una excepción:
- El siguiente interceptor de cumplimiento no es llamado
- El siguiente interceptor de rechazo es llamado
- Una vez capturado, el siguiente interceptor de cumplimiento es llamado nuevamente (igual que en una cadena de promises).
::: tip
Para obtener una comprensión profunda de cómo funcionan los interceptores, puedes leer los casos de prueba [aquí](https://github.com/axios/axios/blob/v1.x/test/specs/interceptors.spec.js).
:::
@@ -0,0 +1,120 @@
# Formato multipart-form-data
axios puede enviar solicitudes en el formato `multipart/form-data`. Este formato se usa comúnmente al subir archivos. Para enviar una solicitud en este formato, debes crear un objeto `FormData` y agregarle los datos. Luego puedes pasar el objeto `FormData` a la propiedad `data` de la configuración de solicitud de axios.
```js
const formData = new FormData();
formData.append("foo", "bar");
axios.post("https://httpbin.org/post", formData);
```
En Node.js, puedes usar la librería `form-data` de la siguiente manera:
```js
const FormData = require("form-data");
const form = new FormData();
form.append("my_field", "my value");
form.append("my_buffer", Buffer.alloc(10));
form.append("my_file", fs.createReadStream("/foo/bar.jpg"));
axios.post("https://example.com", form);
```
## Serialización automática a FormData <Badge type="tip" text="Nuevo" />
A partir de la versión v0.27.0, Axios admite la serialización automática de objetos a un objeto FormData si el encabezado `Content-Type` de la solicitud está establecido en `multipart/form-data`. Esto significa que puedes pasar un objeto JavaScript directamente a la propiedad `data` de la configuración de solicitud de axios. Por ejemplo, al pasar datos a una solicitud POST:
```js
import axios from "axios";
axios
.post(
"https://httpbin.org/post",
{ x: 1 },
{
headers: {
"Content-Type": "multipart/form-data",
},
}
)
.then(({ data }) => console.log(data));
```
En el entorno de Node.js, el polyfill ([`form-data`](https://github.com/form-data/form-data)) se usa de forma predeterminada. Puedes sobrescribir la clase FormData estableciendo la variable de configuración `env.FormData`, aunque en la mayoría de los casos no lo necesitarás:
```js
const axios = require("axios");
var FormData = require("form-data");
axios
.post(
"https://httpbin.org/post",
{ x: 1, buf: Buffer.alloc(10) },
{
headers: {
"Content-Type": "multipart/form-data",
},
}
)
.then(({ data }) => console.log(data));
```
## Terminaciones admitidas
El serializador de FormData de Axios admite algunas terminaciones especiales para realizar las siguientes operaciones:
- `{}` - serializa el valor con JSON.stringify
- `[]` - desenvuelve el objeto tipo arreglo como campos separados con la misma clave
::: warning
Nota: la operación de desenvolvimiento/expansión se usará de forma predeterminada en arreglos y objetos FileList.
:::
## Configurar el serializador de FormData
El serializador de FormData admite opciones adicionales a través de la propiedad de objeto `config.formSerializer` para manejar casos especiales:
- `visitor: Function` - función de visitante definida por el usuario que se llamará de forma recursiva para serializar el objeto de datos a un objeto FormData siguiendo reglas personalizadas.
- `dots: boolean = false` - usa notación de punto en lugar de corchetes para serializar arreglos y objetos;
- `metaTokens: boolean = true` - añade la terminación especial (por ejemplo, `user{}: '{"name": "John"}'`) en la clave de FormData. El analizador de cuerpo del backend podría usar esta meta-información para analizar automáticamente el valor como JSON.
- `indexes: null|false|true = false` - controla cómo se añadirán los índices a las claves desenvueltas de objetos planos tipo arreglo:
- `null` - no añadir corchetes (`arr: 1`, `arr: 2`, `arr: 3`)
- `false` (predeterminado) - añadir corchetes vacíos (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)
- `true` - añadir corchetes con índices (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)
Por ejemplo, si tenemos un objeto como este:
```js
const obj = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: "Peter", surname: "Griffin" },
{ name: "Thomas", surname: "Anderson" },
],
"obj2{}": [{ x: 1 }],
};
```
El serializador de Axios ejecutará internamente los siguientes pasos:
```js
const formData = new FormData();
formData.append("x", "1");
formData.append("arr[]", "1");
formData.append("arr[]", "2");
formData.append("arr[]", "3");
formData.append("arr2[0]", "1");
formData.append("arr2[1][0]", "2");
formData.append("arr2[2]", "3");
formData.append("users[0][name]", "Peter");
formData.append("users[0][surname]", "Griffin");
formData.append("users[1][name]", "Thomas");
formData.append("users[1][surname]", "Anderson");
formData.append("obj2{}", '[{"x":1}]');
```
Axios admite los siguientes métodos abreviados: `postForm`, `putForm`, `patchForm`, que son simplemente los métodos HTTP correspondientes con el encabezado `Content-Type` preestablecido en `multipart/form-data`.
@@ -0,0 +1,55 @@
# Captura de progreso <Badge type="tip" text="Nuevo" />
Axios admite la captura del progreso de carga y descarga en entornos de navegador y Node.js. La frecuencia de los eventos de progreso está limitada a 3 veces por segundo para evitar saturar el navegador con eventos de progreso. A continuación se muestra un ejemplo de cómo capturar eventos de progreso:
```js
await axios.post(url, data, {
onUploadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number; // in range [0..1]
bytes: number; // how many bytes have been transferred since the last trigger (delta)
estimated?: number; // estimated time in seconds
rate?: number; // upload speed in bytes
upload: true; // upload sign
}*/
},
onDownloadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number;
bytes: number;
estimated?: number;
rate?: number; // download speed in bytes
download: true; // download sign
}*/
},
});
```
También puedes transmitir los eventos de progreso de carga y descarga a un stream legible en Node.js. Esto es útil cuando deseas mostrar el progreso de una forma personalizada. A continuación se muestra un ejemplo de cómo transmitir eventos de progreso:
```js
const { data } = await axios.post(SERVER_URL, readableStream, {
onUploadProgress: ({ progress }) => {
console.log((progress * 100).toFixed(2));
},
headers: {
"Content-Length": contentLength,
},
maxRedirects: 0, // avoid buffering the entire stream
});
```
::: warning
La captura del progreso de carga de FormData no está disponible actualmente en entornos Node.js.
:::
::: danger
Se recomienda deshabilitar las redirecciones estableciendo `maxRedirects: 0` para subir el stream en el entorno Node.js, ya que el paquete `follow-redirects` almacenará todo el stream en memoria RAM sin seguir el algoritmo de "backpressure".
:::
+81
View File
@@ -0,0 +1,81 @@
# Promises
axios está construido sobre la API nativa de Promise de ES6. Cada solicitud de axios devuelve una Promise que se resuelve en un objeto de respuesta o se rechaza con un error. Si tu entorno no admite Promises de ES6, necesitarás añadir un polyfill — por ejemplo con [es6-promise](https://github.com/stefanpenner/es6-promise).
## then / catch / finally
Dado que axios devuelve una Promise estándar, puedes usar `.then()`, `.catch()` y `.finally()` para manejar el resultado:
```js
axios.get("/api/users")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error("Request failed:", error.message);
})
.finally(() => {
console.log("Request finished");
});
```
## async / await
El enfoque recomendado para la mayoría de las bases de código es `async/await`, que hace que el código asíncrono se lea como código síncrono:
```js
async function fetchUser(id) {
try {
const response = await axios.get(`/api/users/${id}`);
return response.data;
} catch (error) {
console.error("Failed to fetch user:", error.message);
throw error;
}
}
```
## Solicitudes en paralelo
Dado que axios devuelve una Promise estándar, puedes usar `Promise.all` para hacer múltiples solicitudes al mismo tiempo y esperar a que todas se completen:
```js
const [users, posts] = await Promise.all([
axios.get("/api/users"),
axios.get("/api/posts"),
]);
console.log(users.data, posts.data);
```
::: tip
`Promise.all` se rechazará tan pronto como cualquiera de las solicitudes falle. Si deseas manejar fallos parciales, usa `Promise.allSettled` en su lugar.
:::
```js
const results = await Promise.allSettled([
axios.get("/api/users"),
axios.get("/api/posts"),
]);
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log(result.value.data);
} else {
console.error("Request failed:", result.reason.message);
}
});
```
## Encadenar solicitudes
Puedes encadenar llamadas `.then()` para ejecutar solicitudes secuencialmente, pasando datos de una a la siguiente:
```js
axios.get("/api/user/1")
.then(({ data: user }) => axios.get(`/api/posts?userId=${user.id}`))
.then(({ data: posts }) => {
console.log("Posts for user:", posts);
})
.catch(console.error);
```
+62
View File
@@ -0,0 +1,62 @@
# Limitación de velocidad <Badge type="tip" text="Nuevo" />
axios admite la limitación del ancho de banda en el entorno Node.js a través del adaptador HTTP. Esto te permite controlar la velocidad de carga o descarga de datos, lo que es útil para operaciones masivas, trabajos en segundo plano o scraping educado que no debe saturar una conexión.
## `maxRate`
La opción `maxRate` acepta un número (bytes por segundo) o un arreglo donde el primer valor es el límite de carga y el segundo es el límite de descarga. Usa `[uploadRate]` para limitar solo la carga, o `[uploadRate, downloadRate]` para limitar ambas direcciones. Cuando se pasa un número único, el mismo límite se aplica tanto a la carga como a la descarga.
```js
// Limit both upload and download to 100 KB/s
await axios.get(URL, { maxRate: 100 * 1024 });
// Limit upload to 100 KB/s, download to 500 KB/s
await axios.get(URL, { maxRate: [100 * 1024, 500 * 1024] });
```
::: warning
`maxRate` solo es compatible con el adaptador HTTP de Node.js. No tiene efecto en entornos de navegador.
:::
## Limitación de velocidad de carga
Limita la velocidad de carga y registra el progreso al mismo tiempo:
```js
const { data } = await axios.post(SERVER_URL, myBuffer, {
onUploadProgress: ({ progress, rate }) => {
const percent = (progress * 100).toFixed(1);
const kbps = (rate / 1024).toFixed(1);
console.log(`Upload [${percent}%] at ${kbps} KB/s`);
},
maxRate: [100 * 1024], // cap upload at 100 KB/s
});
```
## Limitación de velocidad de descarga
Limita la velocidad de descarga para respuestas de gran tamaño:
```js
const { data } = await axios.get(FILE_URL, {
onDownloadProgress: ({ progress, rate }) => {
const percent = (progress * 100).toFixed(1);
const kbps = (rate / 1024).toFixed(1);
console.log(`Download [${percent}%] at ${kbps} KB/s`);
},
maxRate: [Infinity, 200 * 1024], // no upload limit, 200 KB/s download limit
responseType: "arraybuffer",
});
```
## Limitación combinada de carga y descarga
Pasa ambos límites como un arreglo para controlar ambas direcciones simultáneamente:
```js
await axios.post(SERVER_URL, largeBuffer, {
maxRate: [50 * 1024, 500 * 1024], // 50 KB/s up, 500 KB/s down
});
```
+350
View File
@@ -0,0 +1,350 @@
# Configuración de solicitud
La configuración de solicitud se usa para configurar la solicitud. Existe una amplia gama de opciones disponibles, pero la única opción requerida es `url`. Si el objeto de configuración no contiene un campo `method`, el método predeterminado es `GET`.
### `url`
La `url` es la URL a la que se realiza la solicitud. Puede ser una cadena de texto o una instancia de `URL`.
### `method`
El `method` es el método HTTP a usar para la solicitud. El método predeterminado es `GET`.
### `baseURL`
La `baseURL` es la URL base que se antepondrá a la `url` a menos que la `url` sea una URL absoluta. Es útil para hacer solicitudes al mismo dominio sin tener que repetir el nombre de dominio, ni ningún prefijo de API o versión.
### `allowAbsoluteUrls`
`allowAbsoluteUrls` determina si las URLs absolutas sobrescribirán un `baseUrl` configurado. Cuando se establece en `true` (valor predeterminado), los valores absolutos para `url` sobrescribirán `baseUrl`. Cuando se establece en `false`, los valores absolutos para `url` siempre serán antepuestos por `baseUrl`.
### `transformRequest`
La función `transformRequest` te permite modificar los datos de la solicitud antes de enviarlos al servidor. Esta función se llama con los datos de la solicitud como único argumento. Solo aplica para los métodos de solicitud `PUT`, `POST`, `PATCH` y `DELETE`. La última función del arreglo debe devolver una cadena de texto o una instancia de Buffer, ArrayBuffer, FormData o Stream.
### `transformResponse`
La función `transformResponse` te permite modificar los datos de la respuesta antes de que sean pasados a las funciones `then` o `catch`. Esta función se llama con los datos de la respuesta como único argumento.
### `headers`
Los `headers` son los encabezados HTTP que se enviarán con la solicitud. El encabezado `Content-Type` se establece en `application/json` de forma predeterminada.
### `params`
Los `params` son los parámetros de URL que se enviarán con la solicitud. Debe ser un objeto plano o un objeto URLSearchParams. Si la `url` contiene parámetros de consulta, se combinarán con el objeto `params`.
### `paramsSerializer`
La función `paramsSerializer` te permite serializar el objeto `params` antes de enviarlo al servidor. Hay varias opciones disponibles para esta función; consulta el ejemplo completo de configuración de solicitud al final de esta página.
### `data`
El `data` son los datos que se enviarán como cuerpo de la solicitud. Puede ser una cadena de texto, un objeto plano, un Buffer, ArrayBuffer, FormData, Stream o URLSearchParams. Solo aplica para los métodos de solicitud `PUT`, `POST`, `DELETE` y `PATCH`. Cuando no se establece `transformRequest`, debe ser de uno de los siguientes tipos:
- cadena de texto, objeto plano, ArrayBuffer, ArrayBufferView, URLSearchParams
- Solo en el navegador: FormData, File, Blob
- Solo en Node.js: Stream, Buffer, FormData (paquete form-data)
### `timeout`
El `timeout` es el número de milisegundos antes de que la solicitud expire. Si la solicitud tarda más que `timeout`, se abortará.
### `withCredentials`
La propiedad `withCredentials` indica si las solicitudes de Access-Control entre sitios deben hacerse usando credenciales como cookies, encabezados de autorización o certificados de cliente TLS. Establecer `withCredentials` no tiene efecto en solicitudes del mismo sitio.
### `adapter`
`adapter` permite el manejo personalizado de solicitudes, lo que facilita las pruebas. Devuelve una Promise y proporciona una respuesta válida; consulta los [adaptadores](/pages/advanced/adapters) para más información. También proporcionamos una serie de adaptadores integrados. El adaptador predeterminado es `http` para Node.js y `xhr` para navegadores. La lista completa de adaptadores integrados es la siguiente:
- fetch
- http
- xhr
También puedes pasar un arreglo de adaptadores. axios usará el primero que sea compatible con el entorno.
### `auth`
`auth` indica que se debe usar autenticación HTTP Basic y proporciona las credenciales. Esto establecerá un encabezado `Authorization`, sobrescribiendo cualquier encabezado `Authorization` personalizado que hayas definido usando `headers`. Ten en cuenta que solo la autenticación HTTP Basic es configurable a través de este parámetro. Para tokens Bearer y similares, usa encabezados `Authorization` personalizados.
### `responseType`
El `responseType` indica el tipo de datos con el que el servidor responderá. Puede ser uno de los siguientes:
- arraybuffer
- document
- json
- text
- stream
- blob (solo en el navegador)
- formdata (solo con el adaptador fetch)
### `responseEncoding` <Badge type="warning" text="Solo en Node.js" />
El `responseEncoding` indica la codificación a usar para decodificar las respuestas. Se admiten las siguientes opciones:
- ascii
- ASCII
- ansi
- ANSI
- binary
- BINARY
- base64
- BASE64
- base64url
- BASE64URL
- hex
- HEX
- latin1
- LATIN1
- ucs-2
- UCS-2
- ucs2
- UCS2
- utf-8
- UTF-8
- utf8
- UTF8
- utf16le
- UTF16LE
::: tip
Nota: Se ignora para `responseType` de tipo `stream` o solicitudes del lado del cliente.
:::
### `xsrfCookieName`
`xsrfCookieName` es el nombre de la cookie que se usará como valor para el token `XSRF`.
### `xsrfHeaderName`
`xsrfHeaderName` es el nombre del encabezado que se usará como valor para el token `XSRF`.
### `withXSRFToken`
La propiedad `withXSRFToken` indica si se debe enviar el token `XSRF` con la solicitud. Solo aplica para solicitudes del lado del cliente. El valor predeterminado es `undefined`.
### `onUploadProgress`
La función `onUploadProgress` te permite escuchar el progreso de una carga.
### `onDownloadProgress`
La función `onDownloadProgress` te permite escuchar el progreso de una descarga.
### `maxContentLength` <Badge type="warning" text="Solo en Node.js" />
La propiedad `maxContentLength` define el número máximo de bytes que el servidor aceptará en la respuesta.
### `maxBodyLength` <Badge type="warning" text="Solo en Node.js" />
La propiedad `maxBodyLength` define el número máximo de bytes que el servidor aceptará en la solicitud.
### `validateStatus`
La función `validateStatus` te permite sobreescribir la validación predeterminada del código de estado. Por defecto, axios rechazará la Promise si el código de estado no está en el rango 200-299. Puedes sobreescribir este comportamiento proporcionando una función `validateStatus` personalizada. La función debe devolver `true` si el código de estado está dentro del rango que deseas aceptar.
### `maxRedirects` <Badge type="warning" text="Solo en Node.js" />
La propiedad `maxRedirects` define el número máximo de redirecciones a seguir. Si se establece en 0, no se seguirá ninguna redirección.
### `beforeRedirect`
La función `beforeRedirect` te permite modificar la solicitud antes de que sea redirigida. Úsala para ajustar las opciones de la solicitud al redirigir, para inspeccionar los últimos encabezados de respuesta, o para cancelar la solicitud lanzando un error. Si `maxRedirects` se establece en 0, `beforeRedirect` no se usa.
### `socketPath` <Badge type="warning" text="Solo en Node.js" />
La propiedad `socketPath` define un socket UNIX que se usará en lugar de una conexión TCP. Por ejemplo, `/var/run/docker.sock` para enviar solicitudes al daemon de Docker. Solo se puede especificar `socketPath` o `proxy`. Si ambos se especifican, se usa `socketPath`.
### `transport`
La propiedad `transport` define el transporte a usar para la solicitud. Es útil para hacer solicitudes sobre un protocolo diferente, como `http2`.
### `httpAgent` y `httpsAgent`
`httpAgent` y `httpsAgent` definen un agente personalizado para usar al realizar solicitudes http y https respectivamente en Node.js. Esto permite añadir opciones como `keepAlive` que no están habilitadas por defecto.
### `proxy`
`proxy` define el nombre de host, puerto y protocolo del servidor proxy que deseas usar. También puedes definir tu proxy usando las variables de entorno convencionales `http_proxy` y `https_proxy`.
Si usas variables de entorno para tu configuración de proxy, también puedes definir una variable de entorno `no_proxy` como una lista separada por comas de dominios que no deben ser enviados a través del proxy.
Usa `false` para deshabilitar los proxies, ignorando las variables de entorno. `auth` indica que se debe usar autenticación HTTP Basic para conectarse al proxy, y proporciona las credenciales. Esto establecerá un encabezado `Proxy-Authorization`, sobrescribiendo cualquier encabezado `Proxy-Authorization` personalizado que hayas definido usando `headers`. Si el servidor proxy usa HTTPS, debes establecer el protocolo en `https`.
```js
proxy: {
protocol: "https",
host: "127.0.0.1",
hostname: "localhost", // Takes precedence over "host" if both are defined
port: 9000,
auth: {
username: "mikeymike",
password: "rapunz3l"
}
},
```
### `cancelToken`
La propiedad `cancelToken` te permite crear un token de cancelación que puede usarse para cancelar la solicitud. Para más información, consulta la documentación de [cancelación](/pages/advanced/cancellation).
### `signal`
La propiedad `signal` te permite pasar una instancia de `AbortSignal` a la solicitud. Esto te permite cancelar la solicitud usando la API `AbortController`.
### `decompress` <Badge type="warning" text="Solo en Node.js" />
La propiedad `decompress` indica si los datos de la respuesta deben descomprimirse automáticamente. El valor predeterminado es `true`.
### `insecureHTTPParser`
Indica si se debe usar un parser HTTP inseguro que acepta encabezados HTTP inválidos. Esto puede permitir la interoperabilidad con implementaciones HTTP no conformes. Se debe evitar el uso del parser inseguro.
Ten en cuenta que la opción `insecureHTTPParser` solo está disponible en Node.js 12.10.0 y versiones posteriores. Consulta la [documentación de Node.js](https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none) para más información. Consulta el conjunto completo de opciones [aquí](https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback).
### `transitional`
La propiedad `transitional` te permite habilitar o deshabilitar ciertas características de transición. Las siguientes opciones están disponibles:
- `silentJSONParsing`: Si se establece en `true`, axios no registrará una advertencia cuando encuentre respuestas JSON inválidas, estableciendo el valor de retorno en null. Es útil cuando trabajas con APIs que devuelven JSON inválido.
- `forcedJSONParsing`: Fuerza a axios a analizar las respuestas JSON como JSON, incluso si la respuesta no es JSON válido. Es útil cuando trabajas con APIs que devuelven JSON inválido.
- `clarifyTimeoutError`: Clarifica el mensaje de error cuando una solicitud expira. Es útil cuando depuras problemas de timeout.
- `legacyInterceptorReqResOrdering`: Cuando se establece en `true`, se usará el orden de solicitud/respuesta de interceptores heredado.
### `env`
La propiedad `env` te permite establecer algunas opciones de configuración. Por ejemplo, la clase FormData que se usa para serializar automáticamente el payload en un objeto FormData.
- FormData: window?.FormData || global?.FormData
### `formSerializer`
La función `formSerializer` te permite serializar el objeto `data` antes de enviarlo al servidor. Hay varias opciones disponibles para esta función; consulta el ejemplo completo de configuración de solicitud al final de esta página.
### `maxRate` <Badge type="warning" text="Solo en Node.js" />
La propiedad `maxRate` define el **ancho de banda** máximo (en bytes por segundo) para la carga y/o descarga. Acepta un número único (aplicado a ambas direcciones) o un arreglo de dos elementos `[uploadRate, downloadRate]` donde cada elemento es un límite en bytes por segundo. Por ejemplo, `100 * 1024` significa 100 KB/s. Consulta [Limitación de velocidad](/pages/advanced/rate-limiting) para ver ejemplos.
## Ejemplo completo de configuración de solicitud
```js
{
url: "/posts",
method: "get",
baseURL: "https://jsonplaceholder.typicode.com",
allowAbsoluteUrls: true,
transformRequest: [function (data, headers) {
return data;
}],
transformResponse: [function (data) {
return data;
}],
headers: {"X-Requested-With": "XMLHttpRequest"},
params: {
postId: 5
},
paramsSerializer: {
// Custom encoder function which sends key/value pairs in an iterative fashion.
encode?: (param: string): string => { /* Do custom operations here and return transformed string */ },
// Custom serializer function for the entire parameter. Allows user to mimic pre 1.x behaviour.
serialize?: (params: Record<string, any>, options?: ParamsSerializerOptions ),
// Configuration for formatting array indexes in the params.
// Three available options:
// (1) indexes: null (leads to no brackets)
// (2) (default) indexes: false (leads to empty brackets)
// (3) indexes: true (leads to brackets with indexes).
indexes: false
},
data: {
firstName: "Fred"
},
// Syntax alternative to send data into the body method post only the value is sent, not the key
data: "Country=Brasil&City=Belo Horizonte",
timeout: 1000,
withCredentials: false,
adapter: function (config) {
// Do whatever you want
},
adapter: "xhr",
auth: {
username: "janedoe",
password: "s00pers3cret"
},
responseType: "json",
responseEncoding: "utf8",
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined),
onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) {
// Do whatever you want with the Axios progress event
},
onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) {
// Do whatever you want with the Axios progress event
},
maxContentLength: 2000,
maxBodyLength: 2000,
validateStatus: function (status) {
return status >= 200 && status < 300;
},
maxRedirects: 21,
beforeRedirect: (options, { headers }) => {
if (options.hostname === "typicode.com") {
options.auth = "user:password";
}
},
socketPath: null,
transport: undefined,
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
proxy: {
protocol: "https",
host: "127.0.0.1",
// hostname: "127.0.0.1" // Takes precedence over "host" if both are defined
port: 9000,
auth: {
username: "mikeymike",
password: "rapunz3l"
}
},
cancelToken: new CancelToken(function (cancel) {
cancel("Operation has been canceled.");
}),
signal: new AbortController().signal,
decompress: true,
insecureHTTPParser: undefined,
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false,
legacyInterceptorReqResOrdering: true,
},
env: {
FormData: window?.FormData || global?.FormData
},
formSerializer: {
// Custom visitor function to serialize form values
visitor: (value, key, path, helpers) => {};
// Use dots instead of brackets format
dots: boolean;
// Keep special endings like {} in parameter key
metaTokens: boolean;
// Use array indexes format:
// null - no brackets
// false - empty brackets
// true - brackets with indexes
indexes: boolean;
},
maxRate: [
100 * 1024, // 100KB/s upload limit,
100 * 1024 // 100KB/s download limit
]
}
```
@@ -0,0 +1,130 @@
# Alias de solicitud
axios proporciona un conjunto de alias para realizar solicitudes HTTP. Estos alias son atajos para hacer solicitudes usando el método `request`. Están diseñados para ser fáciles de usar y ofrecer una forma más conveniente de hacer solicitudes.
axios se esfuerza por seguir las RFC 7231 y RFC 5789 de la manera más fiel posible. Los alias están diseñados para ser consistentes con los métodos HTTP definidos en dichas RFC.
### `axios`
axios puede usarse para hacer una solicitud HTTP pasando únicamente el objeto de configuración. El objeto de configuración completo está documentado [aquí](/pages/advanced/request-config).
```ts
axios(url: string | AxiosRequestConfig, config?: AxiosRequestConfig);
```
## Alias de método
Los siguientes alias están disponibles para hacer solicitudes:
### `request`
El método `request` es el método principal que usarás para hacer solicitudes HTTP. Acepta un objeto de configuración como argumento y devuelve una Promise que se resuelve en el objeto de respuesta. Es un método genérico que puede usarse para cualquier tipo de solicitud HTTP.
```ts
axios.request(config: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `get`
El método `get` se usa para hacer una solicitud GET. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
axios.get(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `delete`
El método `delete` se usa para hacer una solicitud DELETE. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
axios.delete(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `head`
El método `head` se usa para hacer una solicitud HEAD. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
axios.head(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `options`
El método `options` se usa para hacer una solicitud OPTIONS. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
axios.options(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `post`
El método `post` se usa para hacer una solicitud POST. Acepta una URL, un objeto de datos opcional y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
axios.post(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `put`
El método `put` se usa para hacer una solicitud PUT. Acepta una URL, un objeto de datos opcional y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
axios.put(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `patch`
El método `patch` se usa para hacer una solicitud PATCH. Acepta una URL, un objeto de datos opcional y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta.
```ts
axios.patch(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
## Métodos abreviados para datos de formulario
Estos métodos son equivalentes a sus contrapartes anteriores, pero predefinen `Content-Type` como `multipart/form-data`. Son la forma recomendada de subir archivos o enviar formularios HTML.
### `postForm`
```ts
axios.postForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// Upload a file from a browser file input
await axios.postForm("/api/upload", {
file: document.querySelector("#fileInput").files[0],
description: "Profile photo",
});
```
### `putForm`
```ts
axios.putForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// Replace a resource with form data
await axios.putForm("/api/users/1/avatar", {
avatar: document.querySelector("#avatarInput").files[0],
});
```
### `patchForm`
```ts
axios.patchForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// Update specific fields using form data
await axios.patchForm("/api/users/1", {
displayName: "New Name",
avatar: document.querySelector("#avatarInput").files[0],
});
```
::: tip
`postForm`, `putForm` y `patchForm` aceptan los mismos tipos de datos que sus métodos base: objetos planos, `FormData`, `FileList` y `HTMLFormElement`. Consulta [Publicación de archivos](/pages/advanced/file-posting) para más ejemplos.
:::
+64
View File
@@ -0,0 +1,64 @@
# Esquema de respuesta
Cada solicitud de axios se resuelve en un objeto de respuesta con la siguiente estructura. El esquema es consistente tanto en el entorno del navegador como en Node.js.
```js
{
// Los datos de respuesta proporcionados por el servidor.
// Al usar `transformResponse`, este será el resultado de la última transformación.
data: {},
// El código de estado HTTP de la respuesta del servidor (por ejemplo: 200, 404, 500).
status: 200,
// El mensaje de estado HTTP correspondiente al código de estado (por ejemplo: "OK", "Not Found").
statusText: "OK",
// Los encabezados de respuesta enviados por el servidor.
// Los nombres de los encabezados están en minúsculas. Puedes acceder a ellos con notación de corchetes o de punto.
headers: {},
// La configuración de axios que se usó para esta solicitud, incluyendo baseURL,
// headers, timeout, params y cualquier otra opción que hayas proporcionado.
config: {},
// El objeto de solicitud subyacente.
// En Node.js: la última instancia de `http.ClientRequest` (después de cualquier redirección).
// En el navegador: la instancia de `XMLHttpRequest`.
request: {},
}
```
## Acceder a los campos de la respuesta
En la práctica, generalmente desestructurarás solo las partes que necesites:
```js
const { data, status, headers } = await axios.get("/api/users/1");
console.log(status); // 200
console.log(headers["content-type"]); // "application/json; charset=utf-8"
console.log(data); // { id: 1, name: "Jay", email: "jay@example.com" }
```
## Verificar el código de estado
axios resuelve la Promise para cualquier respuesta 2xx y la rechaza para cualquier cosa fuera de ese rango de forma predeterminada. Puedes personalizar esto con la opción de configuración `validateStatus`:
```js
const response = await axios.get("/api/resource", {
validateStatus: (status) => status < 500, // resolve for anything below 500
});
```
## Acceder a los encabezados de respuesta
Todos los nombres de encabezados de respuesta están en minúsculas, independientemente de cómo los haya enviado el servidor:
```js
const response = await axios.get("/api/resource");
// These are equivalent
const contentType = response.headers["content-type"];
const contentType2 = response.headers.get("content-type");
```
+130
View File
@@ -0,0 +1,130 @@
# Reintentos y recuperación de errores
Las solicitudes de red pueden fallar por razones transitorias — una falla momentánea del servidor, una breve interrupción de la red o una respuesta de límite de tasa. Implementar una estrategia de reintento en un interceptor te permite manejar estos fallos de forma transparente, sin ensuciar el código de tu aplicación.
## Reintento básico con un interceptor de respuesta
El enfoque más sencillo es capturar códigos de estado de error específicos y reenviar inmediatamente la solicitud original un número limitado de veces:
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
const MAX_RETRIES = 3;
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
// Only retry on network errors or 5xx server errors
const shouldRetry =
!error.response || (error.response.status >= 500 && error.response.status < 600);
if (!shouldRetry) {
return Promise.reject(error);
}
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= MAX_RETRIES) {
return Promise.reject(error);
}
config._retryCount += 1;
return api(config);
}
);
```
## Retroceso exponencial
Reintentar inmediatamente después de un fallo puede sobrecargar a un servidor que ya tiene dificultades. El retroceso exponencial espera progresivamente más tiempo entre cada intento:
```js
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
const shouldRetry =
!error.response || (error.response.status >= 500 && error.response.status < 600);
if (!shouldRetry) return Promise.reject(error);
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= 3) return Promise.reject(error);
config._retryCount += 1;
// Wait 200ms, 400ms, 800ms, ... before each retry
const backoff = 100 * 2 ** config._retryCount;
await delay(backoff);
return api(config);
}
);
```
## Reintento en 429 (límite de tasa) con Retry-After
Cuando el servidor responde con `429 Too Many Requests`, a menudo incluye un encabezado `Retry-After` que indica exactamente cuánto tiempo esperar:
```js
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
if (error.response?.status !== 429) return Promise.reject(error);
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= 3) return Promise.reject(error);
config._retryCount += 1;
const retryAfterHeader = error.response.headers["retry-after"];
const waitMs = retryAfterHeader
? parseFloat(retryAfterHeader) * 1000 // header is in seconds
: 1000; // default to 1 second
await new Promise((resolve) => setTimeout(resolve, waitMs));
return api(config);
}
);
```
## Desactivar reintentos por solicitud
Si algunas solicitudes nunca deben reintentarse (por ejemplo, mutaciones no idempotentes que no deseas duplicar), añade un indicador a la configuración de la solicitud:
```js
// Add this to your interceptor before the retry logic:
if (config._noRetry) return Promise.reject(error);
// Then opt out on specific calls:
await api.post("/payments/charge", body, { _noRetry: true });
```
## Combinar reintentos con cancelación
Usa un `AbortController` para cancelar una solicitud que está esperando un retardo de retroceso:
```js
const controller = new AbortController();
try {
await api.get("/api/data", { signal: controller.signal });
} catch (error) {
if (axios.isCancel(error)) {
console.log("Request aborted by user");
}
}
// Cancel the request (and any pending retry delay) from elsewhere:
controller.abort();
```
+145
View File
@@ -0,0 +1,145 @@
# Pruebas
Probar código que realiza solicitudes HTTP con axios es sencillo. El enfoque recomendado es simular (mock) axios directamente, de modo que las pruebas se ejecuten sin acceder a la red real, dándote control total sobre las respuestas que recibe tu código.
## Simulación con Vitest o Jest
Tanto Vitest como Jest admiten la simulación de módulos con `vi.mock` / `jest.mock`. Puedes simular todo el módulo de axios y controlar lo que devuelve cada método:
```js
// user-service.js
import axios from "axios";
export async function getUser(id) {
const { data } = await axios.get(`/api/users/${id}`);
return data;
}
```
```js
// user-service.test.js
import { describe, it, expect, vi } from "vitest";
import axios from "axios";
import { getUser } from "./user-service";
vi.mock("axios");
describe("getUser", () => {
it("returns user data on success", async () => {
const mockUser = { id: 1, name: "Jay" };
// Make axios.get resolve with our fake response
axios.get.mockResolvedValueOnce({ data: mockUser });
const result = await getUser(1);
expect(result).toEqual(mockUser);
expect(axios.get).toHaveBeenCalledWith("/api/users/1");
});
it("throws when the request fails", async () => {
axios.get.mockRejectedValueOnce(new Error("Network error"));
await expect(getUser(1)).rejects.toThrow("Network error");
});
});
```
## Simular un AxiosError
Para probar rutas de manejo de errores que inspeccionan `error.response`, crea una instancia de `AxiosError` directamente:
```js
import axios, { AxiosError } from "axios";
import { vi } from "vitest";
const mockError = new AxiosError(
"Not Found",
"ERR_BAD_REQUEST",
{}, // config
{}, // request
{ // response
status: 404,
statusText: "Not Found",
data: { message: "User not found" },
headers: {},
config: {},
}
);
axios.get.mockRejectedValueOnce(mockError);
```
## Usando axios-mock-adapter
[axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) es una librería que instala un adaptador personalizado en tu instancia de axios, interceptando las solicitudes a nivel del adaptador. Esto significa que tus interceptores siguen ejecutándose, lo que la hace más adecuada para pruebas de integración.
```bash
npm install --save-dev axios-mock-adapter
```
```js
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
const mock = new MockAdapter(axios);
// Mock a GET request
mock.onGet("/api/users/1").reply(200, { id: 1, name: "Jay" });
// Mock a POST request
mock.onPost("/api/users").reply(201, { id: 2, name: "New User" });
// Mock a network error
mock.onGet("/api/failing").networkError();
// Mock a timeout
mock.onGet("/api/slow").timeout();
```
Reinicia los mocks entre pruebas:
```js
afterEach(() => {
mock.reset(); // clear all registered handlers
});
```
## Probar interceptores
Para probar interceptores de forma aislada, crea una nueva instancia de axios en tu prueba:
```js
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
describe("auth interceptor", () => {
it("attaches a Bearer token to every request", async () => {
const instance = axios.create();
const mock = new MockAdapter(instance);
// Add your interceptor
instance.interceptors.request.use((config) => {
config.headers.set("Authorization", "Bearer test-token");
return config;
});
// Capture the request config by inspecting what mock received
let capturedConfig;
mock.onGet("/api/data").reply((config) => {
capturedConfig = config;
return [200, {}];
});
await instance.get("/api/data");
expect(capturedConfig.headers["Authorization"]).toBe("Bearer test-token");
});
});
```
## Consejos
- Siempre simula a nivel de módulo (o usa `MockAdapter`) — evita simular métodos individuales en una instancia compartida, ya que el estado puede filtrarse entre pruebas.
- Usa `mockResolvedValueOnce` / `mockRejectedValueOnce` en lugar de `mockResolvedValue` para que las pruebas estén aisladas y no se afecten entre sí.
- Al probar lógica de reintento, usa `MockAdapter` para que el interceptor bajo prueba realmente se ejecute en cada intento.
+8
View File
@@ -0,0 +1,8 @@
# TypeScript
`axios` incluye definiciones de tipos para TypeScript. Estas se encuentran en el paquete npm de `axios` mediante el archivo `index.d.ts`. Dado que axios publica de forma dual con una exportación por defecto ESM y un `module.exports` CJS, existen algunas consideraciones a tener en cuenta:
- La configuración recomendada es usar `"moduleResolution": "node16"` (esto es implícito en `"module": "node16"`). Ten en cuenta que esto requiere TypeScript 4.7 o superior.
- Si usas ESM, tu configuración debería estar bien.
- Si compilas TypeScript a CJS y no puedes usar `"moduleResolution": "node16"`, debes habilitar `esModuleInterop`.
- Si usas TypeScript para verificar tipos en código JavaScript CJS, tu única opción es usar `"moduleResolution": "node16"`.
@@ -0,0 +1,78 @@
# Formato x-www-form-urlencoded
## URLSearchParams
De forma predeterminada, axios serializa los objetos JavaScript a `JSON`. Para enviar datos en el formato [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) en su lugar, puedes usar la API [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams), que es [compatible](http://www.caniuse.com/#feat=urlsearchparams) con la gran mayoría de los navegadores, y con [Node.js](https://nodejs.org/api/url.html#url_class_urlsearchparams) a partir de la versión v10 (lanzada en 2018).
```js
const params = new URLSearchParams({ foo: 'bar' });
params.append('extraparam', 'value');
axios.post('/foo', params);
```
## Cadena de consulta <Badge type="danger" text="Muy antiguo" />
Para navegadores más antiguos o entornos sin `URLSearchParams`, puedes usar la librería [`qs`](https://github.com/ljharb/qs) para serializar objetos al formato `application/x-www-form-urlencoded`.
```js
const qs = require('qs');
axios.post('/foo', qs.stringify({ bar: 123 }));
```
En versiones muy antiguas de Node.js, puedes usar el módulo integrado `querystring` que viene con Node.js. Ten en cuenta que este módulo fue marcado como obsoleto en Node.js v16 — prefiere `URLSearchParams` o `qs` para código nuevo.
```js
const querystring = require('querystring');
axios.post('https://something.com/', querystring.stringify({ foo: 'bar' }));
```
## Serialización automática a URLSearchParams <Badge type="tip" text="Nuevo" />
A partir de la versión v0.21.0, axios serializa automáticamente los objetos JavaScript a `URLSearchParams` si el encabezado `Content-Type` está establecido en `application/x-www-form-urlencoded`. Esto significa que puedes pasar un objeto JavaScript directamente a la propiedad `data` de la configuración de solicitud de axios. Por ejemplo, al pasar datos a una solicitud `POST`:
```js
const data = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: 'Peter', surname: 'Griffin' },
{ name: 'Thomas', surname: 'Anderson' },
],
};
await axios.postForm('https://postman-echo.com/post', data, {
headers: { 'content-type': 'application/x-www-form-urlencoded' },
});
```
El objeto `data` será serializado automáticamente a `URLSearchParams` y enviado en el formato `application/x-www-form-urlencoded`. El servidor recibirá los siguientes datos:
```json
{
"x": "1",
"arr[]": ["1", "2", "3"],
"arr2[0]": "1",
"arr2[1][0]": "2",
"arr2[2]": "3",
"users[0][name]": "Peter",
"users[0][surname]": "Griffin",
"users[1][name]": "Thomas",
"users[1][surname]": "Anderson"
}
```
Si el analizador de cuerpo de tu backend (como `body-parser` de `express.js`) admite la decodificación de objetos anidados, recibirás el mismo objeto en el lado del servidor automáticamente.
```js
var app = express();
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.post('/', function (req, res, next) {
// echo body as JSON
res.send(JSON.stringify(req.body));
});
server = app.listen(3000);
```
@@ -0,0 +1,226 @@
# Ejemplos en JavaScript
## Importar la librería
Para importar la librería en un entorno CommonJS, puedes usar la función `require`, o la declaración `import` si estás usando un empaquetador como Webpack o Rollup.
#### Sin empaquetador
```js
const axios = require("axios");
```
#### Con empaquetador (webpack, rollup, vite, etc)
```js
import axios from "axios";
```
## Usando then/catch/finally
Dado que axios devuelve una Promise en su núcleo, puedes optar por usar callbacks con `then`, `catch` y `finally` para manejar los datos de la respuesta, los errores y la finalización.
### Solicitud Get
```js
axios
.get("https://jsonplaceholder.typicode.com/posts", {
params: {
postId: 5,
},
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Solicitud Post
```js
axios
.post("https://jsonplaceholder.typicode.com/posts", {
title: "foo",
body: "bar",
userId: 1,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Solicitud Put
```js
axios
.put("https://jsonplaceholder.typicode.com/posts/1", {
title: "foo",
body: "bar",
userId: 1,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Solicitud Patch
```js
axios
.patch("https://jsonplaceholder.typicode.com/posts/1", {
title: "foo",
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Solicitud Delete
```js
axios
.delete("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
## Usando async/await
Otra forma de manejar promises es mediante `async` y `await`. Esto te permite usar bloques try/catch/finally para manejar errores y la finalización. Esto puede hacer tu código más legible y fácil de entender, y también ayuda a evitar el llamado "callback hell".
::: tip
Nota: async/await forma parte de ECMAScript 2017 y no está disponible en Internet Explorer ni en navegadores más antiguos, así que úsalo con precaución.
:::
### Solicitud Get
```js
const getPosts = async () => {
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts",
{
params: {
postId: 5,
},
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Solicitud Post
```js
const createPost = async () => {
try {
const response = await axios.post(
"https://jsonplaceholder.typicode.com/posts",
{
title: "foo",
body: "bar",
userId: 1,
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Solicitud Put
```js
const updatePost = async () => {
try {
const response = await axios.put(
"https://jsonplaceholder.typicode.com/posts/1",
{
title: "foo",
body: "bar",
userId: 1,
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Solicitud Patch
```js
const updatePost = async () => {
try {
const response = await axios.patch(
"https://jsonplaceholder.typicode.com/posts/1",
{
title: "foo",
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Solicitud Delete
```js
const deletePost = async () => {
try {
const response = await axios.delete(
"https://jsonplaceholder.typicode.com/posts/1"
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
@@ -0,0 +1,139 @@
# Ejemplo en TypeScript
## Importar tipos
axios incluye definiciones de TypeScript de forma nativa. Puedes importar los tipos que necesites directamente desde `"axios"`:
```ts
import axios from "axios";
import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
```
## Tipar una solicitud
Usa un parámetro de tipo genérico en la respuesta para indicarle a TypeScript la forma que tendrán tus datos:
```ts
import axios from "axios";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
const response = await axios.get<Post>("https://jsonplaceholder.typicode.com/posts/1");
console.log(response.data.title); // TypeScript knows this is a string
```
## Tipar una función
Envuelve las solicitudes en funciones con tipos de retorno explícitos para maximizar la seguridad de tipos:
```ts
import axios, { AxiosResponse } from "axios";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
const getPost = async (id: number): Promise<Post> => {
const response = await axios.get<Post>(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
return response.data;
};
```
## Tipar una solicitud POST
Puedes tipar tanto el cuerpo de la solicitud como la respuesta esperada:
```ts
type CreatePostBody = {
title: string;
body: string;
userId: number;
};
type CreatePostResponse = CreatePostBody & { id: number };
const createPost = async (data: CreatePostBody): Promise<CreatePostResponse> => {
const response = await axios.post<CreatePostResponse>(
"https://jsonplaceholder.typicode.com/posts",
data
);
return response.data;
};
```
## Instancia de axios tipada
Crea una instancia tipada para que la URL base y los encabezados queden definidos desde el inicio:
```ts
import axios from "axios";
import type { AxiosInstance } from "axios";
const api: AxiosInstance = axios.create({
baseURL: "https://api.example.com",
timeout: 5000,
});
```
## Interceptores tipados
Usa `InternalAxiosRequestConfig` (no `AxiosRequestConfig`) para los interceptores de solicitud en v1.x:
```ts
import axios from "axios";
import type { InternalAxiosRequestConfig, AxiosResponse } from "axios";
api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
config.headers.set("Authorization", `Bearer ${getToken()}`);
return config;
});
api.interceptors.response.use(
(response: AxiosResponse) => response,
(error) => Promise.reject(error)
);
```
## Tipar errores
Usa `axios.isAxiosError()` para acotar el tipo de un error capturado:
```ts
import axios, { AxiosError } from "axios";
type ApiError = {
message: string;
code: number;
};
try {
await axios.get("/api/protected-resource");
} catch (error) {
if (axios.isAxiosError<ApiError>(error)) {
// error.response?.data is typed as ApiError
console.error(error.response?.data.message);
console.error(error.response?.status);
} else {
throw error;
}
}
```
## Notas sobre la configuración de TypeScript
Dado que axios publica tanto en formato ESM como CJS, hay algunas consideraciones según tu configuración:
- La configuración recomendada es `"moduleResolution": "node16"` (implícita en `"module": "node16"`). Esto requiere TypeScript 4.7 o superior.
- Si compilas TypeScript a CJS y no puedes usar `"moduleResolution": "node16"`, habilita `"esModuleInterop": true`.
- Si usas TypeScript para verificar tipos en código JavaScript CJS, tu única opción es `"moduleResolution": "node16"`.
+42
View File
@@ -0,0 +1,42 @@
# Características
axios es un potente cliente HTTP que proporciona una API simple y fácil de usar para realizar solicitudes HTTP. Es compatible con todos los navegadores modernos y es ampliamente utilizado en la comunidad JavaScript. A continuación se presentan algunas de las características que hacen de axios una excelente opción para tu próximo proyecto.
## Isomórfico
axios es un cliente HTTP universal que puede usarse tanto en el navegador como en Node.js. Esto significa que puedes utilizar axios para hacer solicitudes a APIs desde tu código frontend y también desde tu código backend. Esto convierte a axios en una gran opción para construir progressive web apps, aplicaciones de una sola página (SPA) y aplicaciones con renderizado del lado del servidor.
axios también es una excelente opción para equipos que trabajan tanto en frontend como en backend. Al usar axios en ambos lados, puedes contar con una API consistente para realizar solicitudes HTTP, lo que ayuda a reducir la complejidad de tu base de código.
## Soporte para Fetch <Badge type="tip" text="Nuevo" />
axios ofrece soporte de primera clase para la Fetch API, que es un reemplazo moderno de la API XHR. El adaptador es opcional y puede habilitarse mediante configuración. Se mantiene la misma API tanto para el adaptador XHR como para el adaptador Fetch, lo que facilita adoptar la Fetch API en tu base de código sin necesidad de modificar el código existente.
## Soporte de navegadores
axios es compatible con todos los navegadores modernos y algunos más antiguos, incluyendo Chrome, Firefox, Safari y Edge. axios es una excelente opción para construir aplicaciones web que necesiten soportar una amplia variedad de navegadores.
## Soporte de Node.js
axios también es compatible con una amplia gama de versiones de Node.js, con compatibilidad probada hasta la versión v12.x, lo que lo convierte en una buena opción en entornos donde actualizar a la última versión de Node.js puede no ser posible o práctico.
Además de Node.js, axios cuenta con pruebas de humo para Bun y Deno que validan comportamientos clave en tiempo de ejecución y mejoran la confianza en la compatibilidad entre distintos entornos.
## Características adicionales
- Compatible con la API de Promise
- Interceptar solicitudes y respuestas
- Transformar datos de solicitudes y respuestas
- Controlador de cancelación (Abort controller)
- Tiempos de espera (timeouts)
- Serialización de parámetros de consulta con soporte para entradas anidadas
- Serialización automática del cuerpo de la solicitud a:
- JSON (application/json)
- Multipart / FormData (multipart/form-data)
- Formulario codificado en URL (application/x-www-form-urlencoded)
- Envío de formularios HTML como JSON
- Manejo automático de datos JSON en la respuesta
- Captura de progreso para navegadores y Node.js con información adicional (velocidad de transferencia, tiempo restante)
- Configuración de límites de ancho de banda para Node.js
- Compatible con FormData y Blob conformes a la especificación (incluyendo Node.js)
- Soporte del lado del cliente para protección contra XSRF
@@ -0,0 +1,73 @@
# Primeros pasos
¡Bienvenido a la documentación de axios! Esta guía te ayudará a comenzar con axios y a realizar tu primera solicitud a una API. Si eres nuevo en axios, te recomendamos empezar aquí.
## Instalación
Puedes usar axios en tu proyecto de varias formas. La más común es instalarlo desde npm e incluirlo en tu proyecto. También ofrecemos soporte para jsDelivr, unpkg y más.
#### Usando npm
```bash
npm install axios
```
#### Usando pnpm
```bash
pnpm install axios
```
#### Usando yarn
```bash
yarn add axios
```
#### Usando bun
```bash
bun add axios
```
#### Usando deno
```bash
deno install npm:axios
```
#### Usando jsDelivr
Al usar jsDelivr, recomendamos utilizar la versión minificada y fijar el número de versión para evitar cambios inesperados. Si deseas usar la última versión, puedes hacerlo omitiendo el número de versión. Esto está fuertemente desaconsejado para uso en producción, ya que puede ocasionar cambios inesperados en tu aplicación.
```html
<script src="https://cdn.jsdelivr.net/npm/axios@<x.x.x>/dist/axios.min.js"></script>
```
#### Usando unpkg
Al usar unpkg, recomendamos utilizar la versión minificada y fijar el número de versión para evitar cambios inesperados. Si deseas usar la última versión, puedes hacerlo omitiendo el número de versión. Esto está fuertemente desaconsejado para uso en producción, ya que puede ocasionar cambios inesperados en tu aplicación.
```html
<script src="https://unpkg.com/axios@<x.x.x>/dist/axios.min.js"></script>
```
## Tu primera solicitud
Una solicitud con axios puede realizarse en tan solo dos líneas de código. Hacer tu primera solicitud con axios es muy sencillo. Puedes hacer una solicitud a cualquier API indicando la URL y el método. Por ejemplo, para hacer una solicitud GET a la API de JSONPlaceholder, puedes usar el siguiente código:
```js
import axios from "axios";
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts/1"
);
console.log(response.data);
```
axios ofrece una API sencilla para realizar solicitudes. Puedes usar el método `axios.get` para hacer una solicitud GET, el método `axios.post` para hacer una solicitud POST, y así sucesivamente. También puedes usar el método `axios.request` para hacer una solicitud con cualquier método.
## Próximos pasos
Ahora que has realizado tu primera solicitud con axios, estás listo para explorar el resto de la documentación. Puedes aprender más sobre cómo hacer solicitudes, manejar respuestas y usar axios en tus proyectos. Consulta el resto de la documentación para saber más.
@@ -0,0 +1,92 @@
# Guía de actualización
Esta guía tiene como objetivo ayudarte a actualizar tu proyecto de una versión del framework a otra. Se recomienda leer las notas de la versión de cada versión mayor desde la que estás migrando, ya que pueden contener información importante sobre cambios que rompen la compatibilidad.
## Actualización de v0.x a v1.x
### Cambios en la declaración de importación
En v1.x, la declaración de importación fue modificada para usar la exportación `default`. Esto significa que deberás actualizar tus importaciones para usar la exportación `default`.
```diff
- import { axios } from "axios";
+ import axios from "axios";
```
### Cambios en el sistema de interceptores
En v1.x debes usar el tipo `InternalAxiosRequestConfig` para tipar el parámetro `config` en el interceptor de `request`. Esto se debe a que el parámetro `config` ahora es del tipo `InternalAxiosRequestConfig` en lugar del tipo público `AxiosRequestConfig`.
```diff
- axios.interceptors.request.use((config: AxiosRequestConfig) => {
+ axios.interceptors.request.use((config: InternalAxiosRequestConfig) => {
return config;
});
```
### Cambios en la estructura de los encabezados de solicitud
En v1.x, la estructura de los encabezados de solicitud fue modificada para eliminar la propiedad `common`. Esto significa que deberás actualizar tu código para usar la nueva estructura de encabezados de solicitud de la siguiente manera:
```diff
- if (request.headers?.common?.Authorization) {
- request.headers.common.Authorization = ...
+ if (request.headers?.Authorization) {
+ request.headers.Authorization = ...
```
Los encabezados predeterminados que antes estaban bajo `common`, `get`, `post`, etc., ahora se definen directamente en `axios.defaults.headers`:
```diff
- axios.defaults.headers.common["Accept"] = "application/json";
+ axios.defaults.headers["Accept"] = "application/json";
```
### Datos multipart en formularios
Si una solicitud incluye un payload de tipo `FormData`, el encabezado `Content-Type: multipart/form-data` ahora se establece automáticamente. Elimina cualquier encabezado manual para evitar duplicados:
```diff
- axios.post("/upload", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
+ axios.post("/upload", formData);
```
Si defines explícitamente `Content-Type: application/json`, axios ahora serializará automáticamente los datos a JSON.
### Serialización de parámetros
v1.x introdujo varios cambios que rompen la compatibilidad en la forma en que se serializan los parámetros de URL. Los más importantes son:
**Los `params` ahora se codifican por porcentaje (percent-encoded) de forma predeterminada.** Si tu backend esperaba corchetes sin codificar al estilo qs, puede que necesites configurar un serializador personalizado:
```js
import qs from 'qs';
axios.create({
paramsSerializer: {
serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' }),
},
});
```
**Los objetos anidados en `params` ahora se serializan con notación de corchetes** (`foo[bar]=1`) en lugar de notación de punto. Si tu backend esperaba notación de punto, usa un serializador personalizado.
**Los parámetros con valor `null` o `undefined`** ahora se manejan de forma consistente: los valores `null` se serializan como cadenas vacías, mientras que los valores `undefined` se omiten completamente.
Para ver todas las opciones de configuración de serialización de parámetros, consulta la página de [Configuración de solicitud](/pages/advanced/request-config).
### Los internos ya no se exportan
Hemos decidido dejar de exportar los internos de axios. Esto significa que deberás actualizar tu código para usar únicamente la API pública de axios. Este cambio se realizó para simplificar la API y reducir la superficie expuesta de axios, permitiéndonos modificar los internos sin declararlos como cambios que rompen la compatibilidad.
Consulta la [Referencia de la API](/pages/advanced/api-reference) en este sitio para obtener la información más actualizada sobre la API pública de axios.
### Configuración de solicitud
Hemos realizado cambios en el objeto de configuración de solicitud. Consulta la [referencia de configuración](/pages/advanced/request-config) en este sitio para obtener la información más actualizada.
### Cambios que rompen la compatibilidad no cubiertos
Esta guía no es exhaustiva y puede no cubrir todos los cambios que rompen la compatibilidad. Si encuentras algún problema, por favor abre un issue en el [repositorio GitHub de la documentación](https://github.com/axios/docs) con la etiqueta `breaking change`.
+24
View File
@@ -0,0 +1,24 @@
# Política de seguridad
## Reportar una vulnerabilidad
Si crees haber encontrado una vulnerabilidad de seguridad en el proyecto, por favor repórtanosla como se describe a continuación. Tomamos todas las vulnerabilidades de seguridad con seriedad. Si has encontrado una vulnerabilidad en una librería de terceros, por favor repórtala a los responsables de esa librería.
## Proceso de reporte
Por favor, no reportes vulnerabilidades de seguridad a través de los issues públicos de GitHub. Usa el canal oficial de seguridad en GitHub enviando un [aviso de seguridad](https://github.com/axios/axios/security).
## Política de divulgación
Cuando recibamos un reporte de vulnerabilidad de seguridad, asignaremos un responsable principal. Esta persona se encargará del reporte de la vulnerabilidad. El responsable confirmará el problema y determinará las versiones afectadas. Luego evaluará el problema y determinará la gravedad del mismo. El responsable desarrollará una solución para el problema y preparará una versión. El responsable notificará al reportante cuando la solución esté lista para ser anunciada.
## Actualizaciones de seguridad
Las actualizaciones de seguridad se publicarán tan pronto como sea posible después de que el parche haya sido desarrollado y probado. Notificaremos a los usuarios de la versión a través del repositorio GitHub del proyecto. También publicaremos las notas de la versión y los avisos de seguridad en la página de versiones de GitHub del proyecto. Además, marcaremos como obsoletas todas las versiones que contengan la vulnerabilidad de seguridad.
## Colaboradores y reconocimientos de seguridad
Nos gustaría agradecer a los siguientes investigadores de seguridad por trabajar con nosotros para ayudar a que el proyecto sea seguro para todos:
- [Socket Dev](https://socket.dev/)
- [GitHub Security Lab](https://securitylab.github.com/)
+44
View File
@@ -0,0 +1,44 @@
# Versionado semántico
El versionado semántico es un esquema de versionado que se usa para comunicar la naturaleza de los cambios en un paquete de software. Es un conjunto simple de reglas y requisitos que dictan cómo se asignan e incrementan los números de versión.
## Versionado de axios
axios sigue el esquema de versionado semántico. Esto significa que cada versión de axios se asigna con un número de versión compuesto por tres partes: mayor, menor y parche. El número de versión se incrementa según la naturaleza de los cambios en la versión.
En el pasado, axios puede que no haya seguido estrictamente el versionado semántico en todo momento; sin embargo, de aquí en adelante se adoptará una adherencia mucho más estricta al esquema de versionado semántico para garantizar que los usuarios puedan confiar en los números de versión para comunicar la naturaleza de los cambios en la librería.
A continuación se proporciona un breve resumen del esquema de versionado.
## Formato de versión
Un número de versión semántico consta de tres partes:
1. Versión mayor
2. Versión menor
3. Versión de parche
El número de versión se escribe como `MAYOR.MENOR.PARCHE`. Cada parte del número de versión tiene un significado específico:
- **Versión mayor**: Se incrementa cuando se realizan cambios incompatibles en la API.
- **Versión menor**: Se incrementa cuando se añade funcionalidad de manera retrocompatible.
- **Versión de parche**: Se incrementa cuando se realizan correcciones de errores retrocompatibles.
## Versiones de prelanzamiento
Además de las tres partes del número de versión, puedes añadir una versión de prelanzamiento. Esto se hace añadiendo un guion y una serie de identificadores separados por puntos inmediatamente después de la versión de parche. Por ejemplo, `1.0.0-alpha.1`.
Las versiones de prelanzamiento se usan para indicar que una versión es inestable y puede no satisfacer los requisitos de compatibilidad indicados por el número de versión. Las versiones de prelanzamiento se ordenan según el orden de los identificadores. Por ejemplo, `1.0.0-alpha.1` viene antes de `1.0.0-alpha.2`.
## Rangos de versiones
Cuando especificas un rango de versiones para un paquete, puedes usar una variedad de operadores para indicar el rango de versiones aceptables. Los siguientes operadores están disponibles:
- `>`: Mayor que
- `<`: Menor que
- `>=`: Mayor o igual que
- `<=`: Menor o igual que
- `~`: Aproximadamente igual a
- `^`: Compatible con
Por ejemplo, `^1.0.0` significa que cualquier versión mayor o igual a `1.0.0` y menor que `2.0.0` es aceptable.
+185
View File
@@ -0,0 +1,185 @@
---
layout: page
---
<script setup>
import allSponsors from '../../../data/sponsors.json';
const sponsors = [...allSponsors.platinum, ...allSponsors.gold, ...allSponsors.silver, ...allSponsors.bronze, ...allSponsors.backer];
const capitalizeFirstLetter = (word) => {
return String(word).charAt(0).toUpperCase() + String(word).slice(1);
};
</script>
<div style="margin: 1rem 7rem; max-width: 1200px;">
<h1 style="line-height: 64px; font-size: 32px; letter-spacing: -0.4px; font-weight: 600; margin-top: 2rem;">Patrocinadores</h1>
<p>Axios cuenta con el apoyo de las siguientes organizaciones. Si deseas patrocinar Axios, visita nuestra <a href="https://opencollective.com/axios" target="_blank" style="color: #007bff;">página de Open Collective</a> para más información.</p>
<div :class="$style.sponsorCloudWrapper">
<div :class="$style.sponsorCloudContainer">
<div :class="$style.sponsorCloudGrid">
<div :class="$style.sponsorCloudImageWrapper" v-for="(sponsor, key) in sponsors" :key="sponsor.name">
<img :src="sponsor.imageUrl" :alt="sponsor.name" style="max-height: 72px; width: 100%; object-fit: contain;" />
<dl>
<dd :class="$style.sponsorTag">
<span :class="$style[`tagSponsor${capitalizeFirstLetter(sponsor.tier)}`]">{{ capitalizeFirstLetter(sponsor.tier) }}</span>
</dd>
</dl>
<a :href="sponsor.website" rel="noopener noreferrer" target="_blank" :class="$style.sponsorName">{{ sponsor.name }}</a>
</div>
</div>
</div>
</div>
</div>
<style module>
.sponsorCloudWrapper {
margin-top: 2rem;
margin-bottom: 2rem;
}
.sponsorCloudContainer {
max-width: 80rem;
}
.sponsorCloudGrid {
display: grid;
overflow: hidden;
margin-left: -1.5rem;
margin-right: -1.5rem;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.125rem;
}
.sponsorCloudImageWrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem;
background-color: rgb(156 163 175 / 0.05);
}
.sponsorTag {
margin-top: 0.75rem;
margin-inline-start: 0px;
}
.sponsorName {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 3rem;
margin-top: 1rem !important;
font-size: 0.875rem !important;
line-height: 1.25rem !important;
font-weight: 600 !important;
color: var(--vp-c-text-1) !important;
text-wrap-style: pretty;
display: -webkit-box;
text-align: center;
}
.tagSponsorPlatinum {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #000;
background-color: #E5E7EB;
}
.tagSponsorGold {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #F59E0B;
}
.tagSponsorSilver {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #9CA3AF;
}
.tagSponsorBronze {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #854D0E;
}
.tagSponsorBacker {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #2563EB;
}
@media (min-width: 640px) {
.sponsorCloudGrid {
margin-left: 0;
margin-right: 0;
border-radius: 1rem;
}
.sponsorCloudImageWrapper {
padding: 2.5rem;
}
}
@media (min-width: 768px) {
.sponsorCloudGrid {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
</style>
+329
View File
@@ -0,0 +1,329 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: 'axios docs'
text: 'axios est un client HTTP simple pour le navigateur et Node.js'
image:
dark: /logo.svg
light: /logo-light.svg
alt: axios
actions:
- theme: brand
text: Démarrer
link: /fr/pages/getting-started/first-steps
- theme: alt
text: Référence API
link: /fr/pages/advanced/api-reference
features:
- title: Implémentation simple
details: Démarrer avec axios est aussi simple qu'une seule ligne de code. Les requêtes API basiques peuvent être effectuées en 2 lignes de code.
- title: Intercepteurs puissants
details: Notre système d'intercepteurs innovant vous permet de contrôler le cycle de vie des requêtes et des réponses. Vous pouvez modifier les requêtes, les réponses et les erreurs.
- title: Support TypeScript
details: axios déclare des types et supporte pleinement TypeScript. Vous pouvez utiliser axios en toute confiance dans vos projets TypeScript.
---
<script setup>
import Splide from '@splidejs/splide';
import { onMounted } from 'vue';
import allSponsors from '../data/sponsors.json';
onMounted(() => {
new Splide(
'.splide',
{
type: 'loop',
autoplay: true,
interval: 3000,
perPage: 5,
perMove: 1,
gap: 10,
snap: true,
pagination: false,
breakpoints: {
1200: {
perPage: 4,
},
960: {
perPage: 3,
},
640: {
perPage: 2,
},
480: {
perPage: 1,
},
},
}
).mount();
});
const activePlatinumSponsors = allSponsors.platinum.filter((sponsor) => sponsor.active);
const activeGoldSponsors = allSponsors.gold.filter((sponsor) => sponsor.active);
const activeSilverSponsors = allSponsors.silver.filter((sponsor) => sponsor.active);
const sponsors = [...activePlatinumSponsors, ...activeGoldSponsors, ...activeSilverSponsors];
const capitalizeFirstLetter = (word) => {
return String(word).charAt(0).toUpperCase() + String(word).slice(1);
};
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css">
<div style="margin: 0 auto; max-width: 1200px;">
<h3 style="line-height: 64px;font-size: 28px;letter-spacing: -0.4px;font-weight: 600;margin-top: 2rem;">Sponsors</h3>
</div>
<div v-if="sponsors.length > 0" :class="$style.container" class="splide">
<div class="splide__track">
<div role="list" class="splide__list">
<div v-for="(sponsor, key) in sponsors" :key="sponsor.name" :class="$style.cardWrapper" :style="key === 0 ? 'margin-left: 0.5rem' : key === sponsors.length - 1 ? 'margin-right: 0.5rem' : ''" class="splide__slide">
<div :class="$style.imgWrapper">
<img :class="$style.img" :src="sponsor.imageUrl" alt="" />
</div>
<div style="padding-left: 0.5rem; padding-right: 0.5rem; height: 100%;">
<p :class="$style.heading">{{ sponsor.name }}</p>
<dl :class="$style.cardDl">
<dd style="margin-top: 0.75rem; margin-inline-start: 0px;">
<span :class="$style[`tagSponsor${capitalizeFirstLetter(sponsor.tier)}`]">{{ capitalizeFirstLetter(sponsor.tier) }}</span>
</dd>
</dl>
</div>
<div>
<div :class="$style.linksWrapper">
<div :class="$style.link">
<a :href="sponsor.website" :class="$style.rightLink" target="_blank">
<div :class="$style.linkIcon">
<svg data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="m20.893 13.393-1.135-1.135a2.252 2.252 0 0 1-.421-.585l-1.08-2.16a.414.414 0 0 0-.663-.107.827.827 0 0 1-.812.21l-1.273-.363a.89.89 0 0 0-.738 1.595l.587.39c.59.395.674 1.23.172 1.732l-.2.2c-.212.212-.33.498-.33.796v.41c0 .409-.11.809-.32 1.158l-1.315 2.191a2.11 2.11 0 0 1-1.81 1.025 1.055 1.055 0 0 1-1.055-1.055v-1.172c0-.92-.56-1.747-1.414-2.089l-.655-.261a2.25 2.25 0 0 1-1.383-2.46l.007-.042a2.25 2.25 0 0 1 .29-.787l.09-.15a2.25 2.25 0 0 1 2.37-1.048l1.178.236a1.125 1.125 0 0 0 1.302-.795l.208-.73a1.125 1.125 0 0 0-.578-1.315l-.665-.332-.091.091a2.25 2.25 0 0 1-1.591.659h-.18c-.249 0-.487.1-.662.274a.931.931 0 0 1-1.458-1.137l1.411-2.353a2.25 2.25 0 0 0 .286-.76m11.928 9.869A9 9 0 0 0 8.965 3.525m11.928 9.868A9 9 0 1 1 8.965 3.525"></path>
</svg>
</div>
</a>
</div>
<div v-if="sponsor.twitter" :class="$style.link" style="margin-left: -1px;">
<a :href="sponsor.twitter" :class="$style.leftLink" target="_blank">
<div :class="$style.linkIcon">
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" fill="currentColor" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 462.799"><path fill-rule="nonzero" d="M403.229 0h78.506L310.219 196.04 512 462.799H354.002L230.261 301.007 88.669 462.799h-78.56l183.455-209.683L0 0h161.999l111.856 147.88L403.229 0zm-27.556 415.805h43.505L138.363 44.527h-46.68l283.99 371.278z"/></svg>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style module>
.container {
display: flex;
margin: 0 auto;
max-width: 1200px;
}
.cardWrapper {
display: flex;
flex-direction: column;
grid-column: span 1 / span 1;
border-radius: 0.5rem;
border: 1px solid var(--vp-c-gutter) !important;
text-align: center;
background-color: var(--card-background-color) !important;
width: 100%;
max-width: 11.5rem;
scroll-snap-align: center;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
flex-shrink: 0 !important;
margin-bottom: 0.5rem !important;
margin-top: 0.5rem !important;
margin-left: auto;
margin-right: auto;
}
.imgWrapper {
display: flex;
padding: 1.75rem;
padding-bottom: 0.75rem;
flex-direction: column;
flex: 1 1 0%;
align-items: center;
justify-content: center;
}
.img {
width: 8rem;
height: 8rem;
}
.heading {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 3rem;
margin-top: 1rem !important;
font-size: 1rem !important;
line-height: 1.5rem !important;
font-weight: 600 !important;
color: var(--vp-c-text-1) !important;
text-wrap-style: pretty;
display: -webkit-box;
}
.cardDl {
display: flex;
margin-top: 0.25rem;
flex-direction: column;
flex-grow: 1;
justify-content: space-between;
}
.tagSponsorPlatinum {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #000;
background-color: #E5E7EB;
}
.tagSponsorGold {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #F59E0B;
}
.tagSponsorSilver {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #9CA3AF;
}
.tagSponsorBronze {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #854D0E;
}
.tagSponsorBacker {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #2563EB;
}
.linksWrapper {
display: flex;
margin-top: -1px;
}
.link {
display: flex;
flex: 1 1 0%;
width: 0;
}
.rightLink {
display: inline-flex;
position: relative;
padding-top: 1rem;
padding-bottom: 1rem;
margin-right: -1px;
flex: 1 1 0%;
column-gap: 0.75rem;
justify-content: center;
align-items: center;
border-bottom-left-radius: 0.5rem;
border-top: 1px;
border-right: 1px;
border-left: 0px;
border-bottom: 0px;
border-style: solid;
border-color: var(--vp-c-gutter);
width: 0;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #111827;
}
.leftLink {
display: inline-flex;
position: relative;
padding-top: 1rem;
padding-bottom: 1rem;
flex: 1 1 0%;
column-gap: 0.75rem;
justify-content: center;
align-items: center;
border-bottom-right-radius: 0.5rem;
border-top: 1px;
border-left: 0px;
border-bottom: 0px;
border-right: 0px;
border-style: solid;
border-color: var(--vp-c-gutter);
width: 0;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #111827;
}
.linkIcon {
width: 1.25rem;
height: 1.25rem;
color: #9CA3AF;
}
</style>
+88
View File
@@ -0,0 +1,88 @@
# Adaptateurs
Les adaptateurs vous permettent de personnaliser la façon dont axios gère les données de la requête. Par défaut, axios utilise une liste de priorité ordonnée `['xhr', 'http', 'fetch']` et sélectionne le premier adaptateur pris en charge par l'environnement actuel. En pratique, cela signifie que `xhr` est utilisé dans les navigateurs, `http` dans Node.js, et `fetch` dans les environnements où ni l'un ni l'autre n'est disponible (comme Cloudflare Workers ou Deno).
Écrire votre propre adaptateur vous donne un contrôle total sur la façon dont axios effectue une requête et traite la réponse — utile pour les tests, les transports personnalisés ou les environnements non standard.
## Adaptateurs intégrés
Vous pouvez sélectionner un adaptateur intégré par nom en utilisant l'option de configuration `adapter` :
```js
// Utiliser l'adaptateur fetch
const instance = axios.create({ adapter: "fetch" });
// Utiliser l'adaptateur XHR (par défaut dans les navigateurs)
const instance = axios.create({ adapter: "xhr" });
// Utiliser l'adaptateur HTTP (par défaut dans Node.js)
const instance = axios.create({ adapter: "http" });
```
Vous pouvez également passer un tableau de noms d'adaptateurs. axios utilisera le premier pris en charge par l'environnement actuel :
```js
const instance = axios.create({ adapter: ["fetch", "xhr", "http"] });
```
Pour plus de détails sur l'adaptateur `fetch`, consultez la page [Adaptateur Fetch](/pages/advanced/fetch-adapter).
## Créer un adaptateur personnalisé
Pour créer un adaptateur personnalisé, écrivez une fonction qui accepte un objet `config` et retourne une Promise qui se résout vers un objet de réponse axios valide.
```js
import axios from "axios";
import { settle } from "axios/unsafe/core/settle.js";
function myAdapter(config) {
/**
* À ce stade :
* - la configuration a été fusionnée avec les valeurs par défaut
* - les transformateurs de requête ont été exécutés
* - les intercepteurs de requête ont été exécutés
*
* L'adaptateur est maintenant responsable de l'exécution de la requête
* et du retour d'un objet de réponse valide.
*/
return new Promise((resolve, reject) => {
// Effectuez votre logique de requête personnalisée ici.
// Cet exemple utilise l'API native fetch comme point de départ.
fetch(config.url, {
method: config.method?.toUpperCase() ?? "GET",
headers: config.headers?.toJSON() ?? {},
body: config.data,
signal: config.signal,
})
.then(async (fetchResponse) => {
const responseData = await fetchResponse.text();
const response = {
data: responseData,
status: fetchResponse.status,
statusText: fetchResponse.statusText,
headers: Object.fromEntries(fetchResponse.headers.entries()),
config,
request: null,
};
// settle résout ou rejette la promise selon le statut HTTP
settle(resolve, reject, response);
/**
* Après ce point :
* - les transformateurs de réponse seront exécutés
* - les intercepteurs de réponse seront exécutés
*/
})
.catch(reject);
});
}
const instance = axios.create({ adapter: myAdapter });
```
::: tip
Le helper `settle` résout la promise pour les codes de statut 2xx et la rejette pour tout le reste, conformément au comportement par défaut d'axios. Si vous souhaitez une validation de statut personnalisée, utilisez plutôt l'option de configuration `validateStatus`.
:::
+331
View File
@@ -0,0 +1,331 @@
# Référence API
Vous trouverez ci-dessous la liste de toutes les fonctions et classes disponibles dans le package axios. Ces fonctions peuvent être utilisées et importées dans votre projet. Elles sont toutes protégées par notre engagement renouvelé à respecter le versionnage sémantique. Vous pouvez donc compter sur leur stabilité dans les versions futures, sauf en cas de changement de version majeure.
## Instance
L'instance `axios` est l'objet principal que vous utiliserez pour effectuer des requêtes HTTP. C'est une fonction fabrique qui crée une nouvelle instance de la classe `Axios`. L'instance `axios` dispose d'un certain nombre de méthodes pour effectuer des requêtes HTTP. Ces méthodes sont documentées dans la [section Alias de requête](/pages/advanced/request-method-aliases) de la documentation.
## Classes
### `Axios`
La classe `Axios` est la classe principale que vous utiliserez pour effectuer des requêtes HTTP. C'est une fonction fabrique qui crée une nouvelle instance de la classe `Axios`. La classe `Axios` dispose d'un certain nombre de méthodes pour effectuer des requêtes HTTP. Ces méthodes sont documentées dans la [section Alias de requête](/pages/advanced/request-method-aliases) de la documentation.
#### `constructor`
Crée une nouvelle instance de la classe `Axios`. Le constructeur accepte un objet de configuration optionnel en argument.
```ts
constructor(instanceConfig?: AxiosRequestConfig);
```
#### `request`
Gère l'invocation de la requête et la résolution de la réponse. C'est la méthode principale pour effectuer des requêtes HTTP. Elle accepte un objet de configuration en argument et retourne une promise qui se résout vers l'objet de réponse.
```ts
request(configOrUrl: string | AxiosRequestConfig<D>, config: AxiosRequestConfig<D>): Promise<AxiosResponse<T>>;
```
### `CancelToken` <Badge type="danger" text="Déprécié en faveur d'AbortController" />
La classe `CancelToken` était basée sur la proposition `tc39/proposal-cancelable-promises`. Elle était utilisée pour créer un token permettant d'annuler une requête HTTP. La classe `CancelToken` est désormais dépréciée en faveur de l'API `AbortController`.
Depuis la version 0.22.0, la classe `CancelToken` est dépréciée et sera supprimée dans une prochaine version. Il est recommandé d'utiliser l'API `AbortController` à la place.
La classe est exportée principalement pour des raisons de rétrocompatibilité et sera supprimée dans une prochaine version. Nous déconseillons fortement son utilisation dans de nouveaux projets et ne documentons donc pas cette API.
## Fonctions
### `AxiosError`
La classe `AxiosError` est une classe d'erreur levée lorsqu'une requête HTTP échoue. Elle étend la classe `Error` et ajoute des propriétés supplémentaires à l'objet d'erreur.
#### `constructor`
Crée une nouvelle instance de la classe `AxiosError`. Le constructeur accepte en argument un message, un code, une configuration, une requête et une réponse optionnels.
```ts
constructor(message?: string, code?: string, config?: InternalAxiosRequestConfig<D>, request?: any, response?: AxiosResponse<T, D>);
```
#### `properties`
La classe `AxiosError` fournit les propriétés suivantes :
```ts
// Instance de config.
config?: InternalAxiosRequestConfig<D>;
// Code d'erreur.
code?: string;
// Instance de requête.
request?: any;
// Instance de réponse.
response?: AxiosResponse<T, D>;
// Booléen indiquant si l'erreur est une `AxiosError`.
isAxiosError: boolean;
// Code de statut HTTP de l'erreur.
status?: number;
// Méthode utilitaire pour convertir l'erreur en objet JSON.
toJSON: () => object;
// Cause de l'erreur.
cause?: Error;
```
### `AxiosHeaders`
La classe `AxiosHeaders` est une classe utilitaire permettant de gérer les en-têtes HTTP. Elle fournit des méthodes pour manipuler les en-têtes, comme l'ajout, la suppression et la récupération d'en-têtes.
Seules les méthodes principales sont documentées ici. Pour la liste complète des méthodes, référez-vous au fichier de déclaration de types.
#### `constructor`
Crée une nouvelle instance de la classe `AxiosHeaders`. Le constructeur accepte un objet d'en-têtes optionnel en argument.
```ts
constructor(headers?: RawAxiosHeaders | AxiosHeaders | string);
```
#### `set`
Ajoute un en-tête à l'objet d'en-têtes.
```ts
set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;
set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;
```
#### `get`
Récupère un en-tête depuis l'objet d'en-têtes.
```ts
get(headerName: string, parser: RegExp): RegExpExecArray | null;
get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;
```
#### `has`
Vérifie si un en-tête existe dans l'objet d'en-têtes.
```ts
has(header: string, matcher?: AxiosHeaderMatcher): boolean;
```
#### `delete`
Supprime un en-tête de l'objet d'en-têtes.
```ts
delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;
```
#### `clear`
Supprime tous les en-têtes de l'objet d'en-têtes.
```ts
clear(matcher?: AxiosHeaderMatcher): boolean;
```
#### `normalize`
Normalise l'objet d'en-têtes.
```ts
normalize(format: boolean): AxiosHeaders;
```
#### `concat`
Concatène des objets d'en-têtes.
```ts
concat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;
```
#### `toJSON`
Convertit l'objet d'en-têtes en objet JSON.
```ts
toJSON(asStrings?: boolean): RawAxiosHeaders;
```
### `CanceledError` <Badge type="tip" text="Extension d'AxiosError" />
La classe `CanceledError` est une classe d'erreur levée lorsqu'une requête HTTP est annulée. Elle étend la classe `AxiosError`.
### `Cancel` <Badge type="tip" text="Alias de CanceledError" />
La classe `Cancel` est un alias de la classe `CanceledError`. Elle est exportée pour des raisons de rétrocompatibilité et sera supprimée dans une prochaine version.
### `isCancel`
Une fonction qui vérifie si une erreur est une `CanceledError`. Utile pour distinguer les annulations intentionnelles des erreurs inattendues.
```ts
isCancel(value: any): boolean;
```
```js
import axios from "axios";
const controller = new AbortController();
axios.get("/api/data", { signal: controller.signal }).catch((error) => {
if (axios.isCancel(error)) {
console.log("Request was cancelled:", error.message);
} else {
console.error("Unexpected error:", error);
}
});
controller.abort("User navigated away");
```
### `isAxiosError`
Une fonction qui vérifie si une erreur est une `AxiosError`. Utilisez-la dans les blocs `catch` pour accéder en toute sécurité aux propriétés spécifiques d'axios comme `error.response` et `error.config`.
```ts
isAxiosError(value: any): value is AxiosError;
```
```js
import axios from "axios";
try {
await axios.get("/api/resource");
} catch (error) {
if (axios.isAxiosError(error)) {
// error.response, error.config, error.code sont tous disponibles
console.error("HTTP error", error.response?.status, error.message);
} else {
// Une erreur non-axios (ex. une erreur de programmation)
throw error;
}
}
```
### `all` <Badge type="danger" text="Déprécié en faveur de Promise.all" />
La fonction `all` est une fonction utilitaire qui prend un tableau de promises et retourne une promise unique qui se résout lorsque toutes les promises du tableau sont résolues. La fonction `all` est désormais dépréciée en faveur de la méthode `Promise.all`. Il est recommandé d'utiliser `Promise.all` à la place.
Depuis la version 0.22.0, la fonction `all` est dépréciée et sera supprimée dans une prochaine version.
### `spread`
La fonction `spread` est une fonction utilitaire qui peut être utilisée pour décomposer un tableau d'arguments dans un appel de fonction. Utile lorsque vous avez un tableau d'arguments à passer à une fonction qui en accepte plusieurs.
```ts
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
```
### `toFormData`
Convertit un objet JavaScript simple (ou imbriqué) en instance `FormData`. Utile pour construire programmatiquement des données de formulaire multipart à partir d'un objet.
```ts
toFormData(sourceObj: object, formData?: FormData, options?: FormSerializerOptions): FormData;
```
```js
import { toFormData } from "axios";
const data = { name: "Jay", avatar: fileBlob };
const form = toFormData(data);
// form est maintenant une instance FormData prête à être envoyée
await axios.post("/api/users", form);
```
### `formToJSON`
Convertit une instance `FormData` en objet JavaScript simple. Utile pour lire les données d'un formulaire dans un format structuré.
```ts
formToJSON(form: FormData): object;
```
```js
import { formToJSON } from "axios";
const form = new FormData();
form.append("name", "Jay");
form.append("role", "admin");
const obj = formToJSON(form);
console.log(obj); // { name: "Jay", role: "admin" }
```
### `getAdapter`
Résout et retourne une fonction d'adaptateur par nom ou en passant un tableau de noms candidats. axios utilise ceci en interne pour sélectionner le meilleur adaptateur disponible pour l'environnement actuel.
```ts
getAdapter(adapters: string | string[]): AxiosAdapter;
```
```js
import { getAdapter } from "axios";
// Obtenir explicitement l'adaptateur fetch
const fetchAdapter = getAdapter("fetch");
// Obtenir le meilleur adaptateur disponible depuis une liste de priorité
const adapter = getAdapter(["fetch", "xhr", "http"]);
```
### `mergeConfig`
Fusionne deux objets de configuration axios, en appliquant la même stratégie de fusion profonde qu'axios utilise en interne lors de la combinaison des valeurs par défaut avec les options par requête. Les valeurs ultérieures ont la priorité.
```ts
mergeConfig<T>(config1: AxiosRequestConfig<T>, config2: AxiosRequestConfig<T>): AxiosRequestConfig<T>;
```
```js
import { mergeConfig } from "axios";
const base = { baseURL: "https://api.example.com", timeout: 5000 };
const override = { timeout: 10000, headers: { "X-Custom": "value" } };
const merged = mergeConfig(base, override);
// { baseURL: "https://api.example.com", timeout: 10000, headers: { "X-Custom": "value" } }
```
## Constantes
### `HttpStatusCode`
Un objet contenant une liste de codes de statut HTTP sous forme de constantes nommées. Utilisez-le pour écrire des conditions lisibles plutôt que des nombres bruts.
```js
import axios, { HttpStatusCode } from "axios";
try {
const response = await axios.get("/api/resource");
} catch (error) {
if (axios.isAxiosError(error)) {
if (error.response?.status === HttpStatusCode.NotFound) {
console.error("Resource not found");
} else if (error.response?.status === HttpStatusCode.Unauthorized) {
console.error("Authentication required");
}
}
}
```
## Divers
### `VERSION`
La version actuelle du package `axios`. Il s'agit d'une chaîne représentant le numéro de version du package, mise à jour à chaque nouvelle version.
+142
View File
@@ -0,0 +1,142 @@
# Authentification
La plupart des APIs requièrent une forme d'authentification. Cette page couvre les schémas les plus courants pour attacher des identifiants aux requêtes axios.
## Tokens Bearer (JWT)
L'approche la plus courante consiste à attacher un JWT dans l'en-tête `Authorization`. La façon la plus propre de procéder est via un intercepteur de requête sur votre instance axios, afin que le token soit lu à jour à chaque requête :
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
api.interceptors.request.use((config) => {
const token = localStorage.getItem("access_token");
if (token) {
config.headers.set("Authorization", `Bearer ${token}`);
}
return config;
});
```
## Authentification HTTP Basic
Pour les APIs utilisant l'authentification HTTP Basic, passez l'option `auth`. axios encodera les identifiants et définira automatiquement l'en-tête `Authorization` :
```js
const response = await axios.get("https://api.example.com/data", {
auth: {
username: "myUser",
password: "myPassword",
},
});
```
::: tip
Pour les tokens Bearer et les clés API, utilisez un en-tête `Authorization` personnalisé plutôt que l'option `auth``auth` est réservé à l'authentification HTTP Basic.
:::
## Clés API
Les clés API sont généralement passées sous forme d'en-tête ou de paramètre de requête, selon ce qu'attend l'API :
```js
// En tant qu'en-tête
const api = axios.create({
baseURL: "https://api.example.com",
headers: { "X-API-Key": "your-api-key-here" },
});
// En tant que paramètre de requête
const response = await axios.get("https://api.example.com/data", {
params: { apiKey: "your-api-key-here" },
});
```
## Renouvellement de token
Lorsque les tokens d'accès expirent, vous devez les renouveler silencieusement et réessayer la requête échouée. Un intercepteur de réponse est l'endroit idéal pour implémenter cela :
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
// Suivre si un renouvellement est déjà en cours pour éviter des appels parallèles
let isRefreshing = false;
let failedQueue = [];
const processQueue = (error, token = null) => {
failedQueue.forEach((prom) => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});
failedQueue = [];
};
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
if (isRefreshing) {
// Mettre la requête en file d'attente jusqu'à la fin du renouvellement
return new Promise((resolve, reject) => {
failedQueue.push({ resolve, reject });
})
.then((token) => {
originalRequest.headers["Authorization"] = `Bearer ${token}`;
return api(originalRequest);
})
.catch((err) => Promise.reject(err));
}
originalRequest._retry = true;
isRefreshing = true;
try {
const { data } = await axios.post("/auth/refresh", {
refreshToken: localStorage.getItem("refresh_token"),
});
const newToken = data.access_token;
localStorage.setItem("access_token", newToken);
api.defaults.headers.common["Authorization"] = `Bearer ${newToken}`;
processQueue(null, newToken);
return api(originalRequest);
} catch (refreshError) {
processQueue(refreshError, null);
// Rediriger vers la connexion ou émettre un événement
localStorage.removeItem("access_token");
window.location.href = "/login";
return Promise.reject(refreshError);
} finally {
isRefreshing = false;
}
}
return Promise.reject(error);
}
);
```
## Authentification par cookie
Pour les APIs basées sur les sessions qui s'appuient sur les cookies, définissez `withCredentials: true` pour inclure les cookies dans les requêtes cross-origin :
```js
const api = axios.create({
baseURL: "https://api.example.com",
withCredentials: true, // envoyer les cookies avec chaque requête
});
```
::: warning
`withCredentials: true` exige que le serveur réponde avec `Access-Control-Allow-Credentials: true` et un `Access-Control-Allow-Origin` spécifique (pas de joker).
:::
+70
View File
@@ -0,0 +1,70 @@
# Annulation
À partir de la version v0.22.0, Axios prend en charge AbortController pour annuler les requêtes de manière propre. Cette fonctionnalité est disponible dans le navigateur et dans Node.js lorsque vous utilisez une version d'Axios qui prend en charge AbortController. Pour annuler une requête, vous devez créer une instance d'`AbortController` et passer son `signal` à l'option `signal` de la requête.
```js
const controller = new AbortController();
axios
.get("/foo/bar", {
signal: controller.signal,
})
.then(function (response) {
//...
});
// annuler la requête
controller.abort();
```
## CancelToken <Badge type="danger" text="Déprécié" />
Vous pouvez également utiliser l'API `CancelToken` pour annuler les requêtes. Cette API est dépréciée et sera supprimée dans la prochaine version majeure. Il est recommandé d'utiliser `AbortController` à la place. Vous pouvez créer un token d'annulation en utilisant la factory `CancelToken.source` comme indiqué ci-dessous :
```js
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios
.get("/user/12345", {
cancelToken: source.token,
})
.catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log("Request canceled", thrown.message);
} else {
// gérer l'erreur
}
});
axios.post(
"/user/12345",
{
name: "new name",
},
{
cancelToken: source.token,
}
);
// annuler la requête (le paramètre message est optionnel)
source.cancel("Operation canceled by the user.");
```
Vous pouvez également créer un token d'annulation en passant une fonction d'exécution au constructeur `CancelToken` :
```js
const CancelToken = axios.CancelToken;
let cancel;
axios.get("/user/12345", {
cancelToken: new CancelToken(function executor(c) {
// Une fonction d'exécution reçoit une fonction d'annulation comme paramètre
cancel = c;
}),
});
// annuler la requête
cancel();
```
Vous pouvez annuler plusieurs requêtes avec le même token d'annulation ou le même abort controller. Si un token d'annulation est déjà annulé au moment où une requête Axios démarre, alors la requête est annulée immédiatement, sans aucune tentative d'effectuer une vraie requête.
+48
View File
@@ -0,0 +1,48 @@
# Valeurs par défaut de configuration
axios vous permet de spécifier des valeurs par défaut de configuration qui seront appliquées à toutes les requêtes. Vous pouvez définir des valeurs par défaut pour `baseURL`, `headers`, `timeout` et d'autres propriétés. Voici un exemple d'utilisation des valeurs par défaut de configuration :
```js
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/posts";
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN;
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
```
## Valeurs par défaut d'une instance personnalisée
Les instances axios sont déclarées avec leurs propres valeurs par défaut lors de leur création. Ces valeurs par défaut peuvent être remplacées en définissant la propriété `defaults` de l'instance. Voici un exemple d'utilisation des valeurs par défaut d'une instance personnalisée :
```js
var instance = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/posts",
timeout: 1000,
headers: { Authorization: "foobar" },
});
instance.defaults.headers.common["Authorization"] = AUTH_TOKEN;
```
## Ordre de priorité de la configuration
La configuration est fusionnée selon un ordre de priorité. L'ordre est le suivant : d'abord les valeurs par défaut de la bibliothèque, puis les propriétés par défaut de l'instance, et enfin l'argument de configuration de la requête. Voici un exemple de cet ordre de priorité :
Créons d'abord une instance avec les valeurs par défaut fournies par la bibliothèque. À ce stade, la valeur de configuration du timeout est `0`, valeur par défaut de la bibliothèque.
```js
const instance = axios.create();
```
Nous allons maintenant remplacer la valeur par défaut du timeout pour l'instance par `2500` millisecondes. Désormais, toutes les requêtes utilisant cette instance attendront 2,5 secondes avant d'expirer.
```js
instance.defaults.timeout = 2500;
```
Enfin, nous allons effectuer une requête avec un timeout de `5000` millisecondes. Cette requête attendra 5 secondes avant d'expirer.
```js
instance.get("/longRequest", {
timeout: 5000,
});
```
@@ -0,0 +1,87 @@
# Créer une instance
`axios.create()` vous permet de créer une instance axios préconfigurée. L'instance partage la même API de requête et de réponse que l'objet `axios` par défaut, mais utilise la configuration que vous fournissez comme base pour chaque requête. C'est la façon recommandée d'utiliser axios dans toute application dépassant un seul fichier.
```ts
import axios from "axios";
const instance = axios.create({
baseURL: "https://api.example.com",
timeout: 5000,
headers: { "X-Custom-Header": "foobar" },
});
```
La méthode `create` accepte l'objet complet de [Configuration de requête](/pages/advanced/request-config). Vous pouvez ensuite utiliser l'instance exactement comme l'objet axios par défaut :
```js
const response = await instance.get("/users/1");
```
## Pourquoi utiliser une instance ?
### URL de base par service
Dans la plupart des applications, vous communiquez avec plusieurs API. Créer une instance distincte par service évite de répéter l'URL de base à chaque appel :
```js
const githubApi = axios.create({ baseURL: "https://api.github.com" });
const internalApi = axios.create({ baseURL: "https://api.internal.example.com" });
const { data: repos } = await githubApi.get("/users/axios/repos");
const { data: users } = await internalApi.get("/users");
```
### En-têtes d'authentification partagés
Attachez un token d'authentification à chaque requête d'une instance sans toucher aux autres :
```js
const authApi = axios.create({
baseURL: "https://api.example.com",
headers: {
Authorization: `Bearer ${getToken()}`,
},
});
```
### Délais d'attente et nouvelles tentatives par service
Différents services ont des caractéristiques de fiabilité différentes. Définissez un délai court pour les services temps réel et un délai long pour les traitements par lots :
```js
const realtimeApi = axios.create({ baseURL: "https://realtime.example.com", timeout: 2000 });
const batchApi = axios.create({ baseURL: "https://batch.example.com", timeout: 60000 });
```
### Intercepteurs isolés
Les intercepteurs ajoutés à une instance ne s'appliquent qu'à cette instance, ce qui permet de bien séparer les responsabilités :
```js
const loggingApi = axios.create({ baseURL: "https://api.example.com" });
loggingApi.interceptors.request.use((config) => {
console.log(`${config.method?.toUpperCase()} ${config.url}`);
return config;
});
```
## Surcharger les valeurs par défaut par requête
La configuration passée au moment de la requête remplace toujours les valeurs par défaut de l'instance :
```js
const api = axios.create({ timeout: 5000 });
// Cette requête spécifique utilise un délai de 30 secondes à la place
await api.get("/slow-endpoint", { timeout: 30000 });
```
::: tip
Les valeurs par défaut de l'instance peuvent également être modifiées après sa création en écrivant dans `instance.defaults` :
```js
instance.defaults.headers.common["Authorization"] = `Bearer ${newToken}`;
```
:::
+72
View File
@@ -0,0 +1,72 @@
# Gestion des erreurs
axios peut lever de nombreux types d'erreurs différents. Certaines de ces erreurs sont causées par axios lui-même, tandis que d'autres sont causées par le serveur ou le client. Le tableau suivant liste la structure générale de l'erreur levée :
| Propriété | Définition |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| message | Un résumé rapide du message d'erreur et du statut avec lequel elle a échoué. |
| name | Définit l'origine de l'erreur. Pour axios, ce sera toujours une `AxiosError`. |
| stack | Fournit la trace de pile de l'erreur. |
| config | Un objet de configuration axios avec les configurations d'instance spécifiques définies par l'utilisateur au moment de la requête. |
| code | Représente une erreur identifiée par axios. Le tableau ci-dessous liste les définitions spécifiques des erreurs internes d'axios. |
| status | Code de statut de la réponse HTTP. Consultez [ici](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) pour la signification des codes de statut HTTP courants. |
Voici une liste des erreurs potentielles identifiées par axios :
| Code | Définition |
| ------------------------- | --------------------------------------------------------------------------------------------- |
| ERR_BAD_OPTION_VALUE | Valeur invalide ou non supportée fournie dans la configuration axios. |
| ERR_BAD_OPTION | Option invalide fournie dans la configuration axios. |
| ECONNABORTED | Indique généralement que la requête a expiré (sauf si `transitional.clarifyTimeoutError` est défini) ou a été abandonnée par le navigateur ou son plugin. |
| ETIMEDOUT | La requête a expiré en dépassant la limite de temps par défaut d'axios. `transitional.clarifyTimeoutError` doit être défini à `true`, sinon une erreur générique `ECONNABORTED` sera levée à la place. |
| ERR_NETWORK | Problème lié au réseau. Dans le navigateur, cette erreur peut également être causée par une violation de politique [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) ou de [contenu mixte](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content). Le navigateur ne permet pas au code JS de clarifier la raison réelle de l'erreur pour des raisons de sécurité ; veuillez vérifier la console. |
| ERR_FR_TOO_MANY_REDIRECTS | La requête est redirigée trop de fois ; dépasse le nombre maximum de redirections spécifié dans la configuration axios. |
| ERR_DEPRECATED | Fonctionnalité ou méthode dépréciée utilisée dans axios. |
| ERR_BAD_RESPONSE | La réponse ne peut pas être analysée correctement ou est dans un format inattendu. Généralement lié à une réponse avec un code de statut `5xx`. |
| ERR_BAD_REQUEST | La requête a un format inattendu ou des paramètres requis manquants. Généralement lié à une réponse avec un code de statut `4xx`. |
| ERR_CANCELED | Fonctionnalité ou méthode annulée explicitement par l'utilisateur via un AbortSignal (ou un CancelToken). |
| ERR_NOT_SUPPORT | Fonctionnalité ou méthode non supportée dans l'environnement axios actuel. |
| ERR_INVALID_URL | URL invalide fournie pour la requête axios. |
## Gérer les erreurs
Le comportement par défaut d'axios est de rejeter la promise si la requête échoue. Cependant, vous pouvez également capturer l'erreur et la gérer comme bon vous semble. Voici un exemple de capture d'une erreur :
```js
axios.get("/user/12345").catch(function (error) {
if (error.response) {
// La requête a été effectuée et le serveur a répondu avec un code de statut
// qui n'est pas dans la plage 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// La requête a été effectuée mais aucune réponse n'a été reçue
// `error.request` est une instance de XMLHttpRequest dans le navigateur et une instance de
// http.ClientRequest dans Node.js
console.log(error.request);
} else {
// Quelque chose s'est produit lors de la configuration de la requête qui a déclenché une erreur
console.log("Error", error.message);
}
console.log(error.config);
});
```
En utilisant l'option de configuration `validateStatus`, vous pouvez remplacer la condition par défaut (status >= 200 && status < 300) et définir le ou les codes HTTP qui doivent lever une erreur.
```js
axios.get("/user/12345", {
validateStatus: function (status) {
return status < 500; // Résoudre uniquement si le code de statut est inférieur à 500
},
});
```
En utilisant la méthode `toJSON`, vous pouvez obtenir un objet avec plus d'informations sur l'erreur.
```js
axios.get("/user/12345").catch(function (error) {
console.log(error.toJSON());
});
```
+81
View File
@@ -0,0 +1,81 @@
# Adaptateur Fetch <Badge type="tip" text="Nouveau" />
L'adaptateur `fetch` est un nouvel adaptateur introduit à partir de la version 1.7.0. Il permet d'utiliser axios avec l'API `fetch`, vous offrant ainsi le meilleur des deux mondes. Par défaut, `fetch` sera utilisé si les adaptateurs `xhr` et `http` ne sont pas disponibles dans le build, ou non supportés par l'environnement. Pour l'utiliser par défaut, il doit être sélectionné explicitement en définissant l'option `adapter` à `fetch` lors de la création d'une instance axios.
```js
import axios from 'axios';
const instance = axios.create({
adapter: 'fetch',
});
```
L'adaptateur supporte les mêmes fonctionnalités que l'adaptateur `xhr`, notamment la capture de la progression des envois et téléchargements. Il supporte également des types de réponse supplémentaires tels que `stream` et `formdata` (si l'environnement les prend en charge).
## Fetch personnalisé <Badge type="tip" text="v1.12.0+" />
À partir de `v1.12.0`, vous pouvez personnaliser l'adaptateur fetch pour utiliser une fonction `fetch` personnalisée au lieu de celle de l'environnement global. Vous pouvez passer une fonction `fetch`, ainsi que des constructeurs `Request` et `Response` personnalisés via l'option de configuration `env`. Cela est utile lorsque vous travaillez avec des environnements personnalisés ou des frameworks d'application qui fournissent leur propre implémentation de `fetch`.
::: info
Lorsque vous utilisez une fonction `fetch` personnalisée, vous devrez peut-être également fournir des constructeurs `Request` et `Response` correspondants. Si vous les omettez, les constructeurs globaux seront utilisés. Si votre `fetch` personnalisé est incompatible avec les constructeurs globaux, passez `null` pour les désactiver.
**Remarque :** Définir `Request` et `Response` à `null` rendra impossible pour l'adaptateur fetch de capturer la progression des envois et téléchargements.
:::
### Exemple de base
```js
import customFetchFunction from 'customFetchModule';
const instance = axios.create({
adapter: 'fetch',
onDownloadProgress(e) {
console.log('downloadProgress', e);
},
env: {
fetch: customFetchFunction,
Request: null, // null -> désactiver le constructeur
Response: null,
},
});
```
### Utilisation avec Tauri
[Tauri](https://tauri.app/plugin/http-client/) fournit une fonction `fetch` de plateforme qui contourne les restrictions CORS du navigateur pour les requêtes effectuées depuis la couche native. L'exemple ci-dessous montre une configuration minimale pour utiliser axios dans une application Tauri avec ce fetch personnalisé.
```js
import { fetch } from '@tauri-apps/plugin-http';
import axios from 'axios';
const instance = axios.create({
adapter: 'fetch',
onDownloadProgress(e) {
console.log('downloadProgress', e);
},
env: {
fetch,
},
});
const { data } = await instance.get('https://google.com');
```
### Utilisation avec SvelteKit
[SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) fournit une implémentation `fetch` personnalisée pour les fonctions `load` côté serveur qui gère la transmission des cookies et les URLs relatives. Comme son `fetch` est incompatible avec l'API `URL` standard, axios doit être configuré pour l'utiliser explicitement, et les constructeurs `Request` et `Response` globaux doivent être désactivés.
```js
export async function load({ fetch }) {
const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', {
adapter: 'fetch',
env: {
fetch,
Request: null,
Response: null,
},
});
return { post };
}
```
+99
View File
@@ -0,0 +1,99 @@
# Envoi de fichiers
axios simplifie l'envoi de fichiers. Utilisez `postForm` ou `FormData` lorsque vous avez besoin d'envois `multipart/form-data`.
## Fichier unique (navigateur)
Passez un objet `File` directement comme valeur de champ — axios le détectera et utilisera automatiquement le type de contenu correct :
```js
await axios.postForm("https://httpbin.org/post", {
description: "My profile photo",
file: document.querySelector("#fileInput").files[0],
});
```
## Plusieurs fichiers (navigateur)
Passez une `FileList` pour envoyer tous les fichiers sélectionnés en une seule fois. Ils seront tous envoyés sous le même nom de champ (`files[]`) :
```js
await axios.postForm(
"https://httpbin.org/post",
document.querySelector("#fileInput").files
);
```
Pour utiliser des noms de champs distincts pour chaque fichier, construisez un objet `FormData` manuellement :
```js
const formData = new FormData();
formData.append("avatar", avatarFile);
formData.append("cover", coverFile);
await axios.post("https://httpbin.org/post", formData);
```
## Suivi de la progression de l'envoi (navigateur)
Utilisez le callback `onUploadProgress` pour afficher une barre de progression ou un pourcentage à vos utilisateurs :
```js
await axios.postForm("https://httpbin.org/post", {
file: document.querySelector("#fileInput").files[0],
}, {
onUploadProgress: (progressEvent) => {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`Upload progress: ${percent}%`);
},
});
```
Consultez [Capture de progression](/pages/advanced/progress-capturing) pour la liste complète des champs disponibles sur l'événement de progression.
## Fichiers dans Node.js
Dans Node.js, utilisez `fs.createReadStream` pour envoyer un fichier depuis le système de fichiers sans le charger entièrement en mémoire :
```js
import fs from "fs";
import FormData from "form-data";
import axios from "axios";
const form = new FormData();
form.append("file", fs.createReadStream("/path/to/file.jpg"));
form.append("description", "My uploaded file");
await axios.post("https://httpbin.org/post", form);
```
::: tip
Le package npm `form-data` est nécessaire dans les environnements Node.js pour créer des objets `FormData`. Dans Node.js moderne (v18+), le `FormData` global est disponible nativement.
:::
## Envoi d'un Buffer (Node.js)
Vous pouvez également envoyer directement un `Buffer` en mémoire :
```js
const buffer = Buffer.from("Hello, world!");
const form = new FormData();
form.append("file", buffer, {
filename: "hello.txt",
contentType: "text/plain",
knownLength: buffer.length,
});
await axios.post("https://httpbin.org/post", form);
```
::: warning
La capture de la progression d'envoi de `FormData` n'est actuellement pas supportée dans les environnements Node.js.
:::
::: danger
Lors de l'envoi d'un stream lisible dans Node.js, définissez `maxRedirects: 0` pour empêcher le package `follow-redirects` de buffériser l'intégralité du stream en RAM.
:::
+188
View File
@@ -0,0 +1,188 @@
# Méthodes d'en-têtes <Badge type="tip" text="Nouveau" />
Avec l'introduction de la nouvelle classe `AxiosHeaders`, Axios fournit un ensemble de méthodes pour manipuler les en-têtes. Ces méthodes sont utilisées pour définir, récupérer et supprimer des en-têtes de manière plus pratique que la manipulation directe de l'objet d'en-têtes.
## Constructeur `new AxiosHeaders(headers?)`
Le constructeur de la classe `AxiosHeaders` accepte un objet optionnel avec des en-têtes pour initialiser l'instance. L'objet d'en-têtes peut contenir un nombre quelconque d'en-têtes, et les clés sont insensibles à la casse.
```js
constructor(headers?: RawAxiosHeaders | AxiosHeaders | string);
```
Pour plus de commodité, vous pouvez passer une chaîne avec des en-têtes séparés par un caractère de nouvelle ligne. Les en-têtes sont alors analysés et ajoutés à l'instance.
```js
const headers = new AxiosHeaders(`
Host: www.bing.com
User-Agent: curl/7.54.0
Accept: */*`);
console.log(headers);
// Object [AxiosHeaders] {
// host: 'www.bing.com',
// 'user-agent': 'curl/7.54.0',
// accept: '*/*'
// }
```
## Set
La méthode `set` est utilisée pour définir des en-têtes sur l'instance d'`AxiosHeaders`. La méthode peut être appelée avec un seul nom d'en-tête et une valeur, un objet avec plusieurs en-têtes, ou une chaîne avec des en-têtes séparés par un caractère de nouvelle ligne. La méthode accepte également un paramètre optionnel `rewrite` qui contrôle le comportement de définition de l'en-tête.
```js
set(headerName, value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher);
set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string) => boolean);
set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean);
```
L'argument `rewrite` contrôle le comportement d'écrasement :
- `false` - ne pas écraser si la valeur de l'en-tête est définie (n'est pas undefined)
- `undefined` (défaut) - écraser l'en-tête sauf si sa valeur est définie à false
- `true` - écraser dans tous les cas
L'option peut également accepter une fonction définie par l'utilisateur qui détermine si la valeur doit être écrasée ou non. La fonction reçoit la valeur actuelle, le nom de l'en-tête et l'objet d'en-têtes comme arguments.
`AxiosHeaders` conserve la casse de la première clé correspondante qu'il voit. Vous pouvez utiliser cela pour préserver la casse spécifique d'un en-tête en initialisant une clé avec `undefined` puis en définissant les valeurs ultérieurement. Voir [Préserver la casse d'un en-tête spécifique](/pages/advanced/headers#preserving-a-specific-header-case).
## Get
La méthode `get` est utilisée pour récupérer la valeur d'un en-tête. La méthode peut être appelée avec un seul nom d'en-tête, un matcher optionnel ou un analyseur. Le matcher est par défaut `true`. L'analyseur peut être une expression régulière utilisée pour extraire la valeur de l'en-tête.
```js
get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;
get(headerName: string, parser: RegExp): RegExpExecArray | null;
```
Voici un exemple de quelques-unes des utilisations possibles de la méthode `get` :
```js
const headers = new AxiosHeaders({
'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h',
});
console.log(headers.get('Content-Type'));
// multipart/form-data; boundary=Asrf456BGe4h
console.log(headers.get('Content-Type', true)); // analyser les paires clé-valeur depuis une chaîne séparée par des délimiteurs \s,;= :
// [Object: null prototype] {
// 'multipart/form-data': undefined,
// boundary: 'Asrf456BGe4h'
// }
console.log(
headers.get('Content-Type', (value, name, headers) => {
return String(value).replace(/a/g, 'ZZZ');
})
);
// multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h
console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]);
// boundary=Asrf456BGe4h
```
## Has
La méthode `has` est utilisée pour vérifier si un en-tête existe dans l'instance d'`AxiosHeaders`. La méthode peut être appelée avec un seul nom d'en-tête et un matcher optionnel.
```js
has(header: string, matcher?: AxiosHeaderMatcher): boolean;
```
::: info
Retourne true si l'en-tête est défini (n'a pas de valeur undefined).
:::
## Delete
La méthode `delete` est utilisée pour supprimer un en-tête de l'instance d'`AxiosHeaders`. La méthode peut être appelée avec un seul nom d'en-tête et un matcher optionnel.
```js
delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;
```
::: info
Retourne true si au moins un en-tête a été supprimé.
:::
## Clear
La méthode `clear` est utilisée pour supprimer tous les en-têtes de l'instance d'`AxiosHeaders` si rien n'est passé. Si un matcher est passé, seuls les en-têtes correspondant au matcher sont supprimés ; dans ce cas, le matcher est utilisé pour correspondre au nom de l'en-tête plutôt qu'à sa valeur.
```js
clear(matcher?: AxiosHeaderMatcher): boolean;
```
::: info
Retourne true si au moins un en-tête a été effacé.
:::
## Normalize
Si l'objet d'en-têtes a été modifié directement, cela peut créer des doublons avec le même nom mais dans des casses différentes. Cette méthode normalise l'objet d'en-têtes en combinant les clés dupliquées en une seule. Axios utilise cette méthode en interne après l'appel de chaque intercepteur. Définissez `format` à `true` pour convertir les noms d'en-têtes en minuscules et capitaliser les premières lettres (cOntEnt-type => Content-Type) ou `false` pour conserver le format original.
```js
const headers = new AxiosHeaders({
foo: '1',
});
headers.Foo = '2';
headers.FOO = '3';
console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' }
console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' }
console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' }
```
::: info
Retourne `this` pour le chaînage.
:::
## Concat
Fusionne l'instance avec des cibles dans une nouvelle instance AxiosHeaders. Si la cible est une chaîne, elle sera analysée comme des en-têtes HTTP bruts. Si la cible est une instance AxiosHeaders, elle sera fusionnée avec l'instance actuelle.
Utile pour les préréglages de casse lors de la composition d'en-têtes. Par exemple :
```js
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
```
```js
concat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;
```
::: info
Retourne une nouvelle instance AxiosHeaders.
:::
## toJSON
Résout toutes les valeurs d'en-têtes internes dans un nouvel objet à prototype null. Définissez `asStrings` à true pour résoudre les tableaux en une chaîne contenant tous les éléments, séparés par des virgules.
```js
toJSON(asStrings?: boolean): RawAxiosHeaders;
```
## From
Retourne une nouvelle instance d'`AxiosHeaders` créée à partir des en-têtes bruts passés, ou retourne simplement l'objet d'en-têtes donné s'il s'agit déjà d'une instance d'`AxiosHeaders`.
```js
from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;
```
## Raccourcis
Les raccourcis suivants sont disponibles :
- `setContentType`, `getContentType`, `hasContentType`
- `setContentLength`, `getContentLength`, `hasContentLength`
- `setAccept`, `getAccept`, `hasAccept`
- `setUserAgent`, `getUserAgent`, `hasUserAgent`
- `setContentEncoding`, `getContentEncoding`, `hasContentEncoding`
+153
View File
@@ -0,0 +1,153 @@
# En-têtes <Badge type="tip" text="Nouveau" />
Axios expose sa propre classe AxiosHeaders pour manipuler les en-têtes en utilisant une API de type Map qui garantit des clés insensibles à la casse. Cette classe est utilisée en interne par Axios pour gérer les en-têtes, mais elle est également exposée à l'utilisateur pour plus de commodité. Bien que les en-têtes HTTP soient insensibles à la casse, Axios conservera la casse de l'en-tête original pour des raisons stylistiques et comme solution de contournement lorsque des serveurs tiennent incorrectement compte de la casse des en-têtes. L'ancienne méthode de manipulation directe de l'objet d'en-têtes est toujours disponible, mais dépréciée et non recommandée pour un usage futur.
## Travailler avec les en-têtes
L'instance d'objet AxiosHeaders peut contenir différents types de valeurs internes qui contrôlent la logique de définition et de fusion. L'objet d'en-têtes final est obtenu par Axios en appelant la méthode toJSON. L'objet AxiosHeaders est également itérable, vous pouvez donc l'utiliser dans des boucles ou le convertir en tableau ou en objet.
Les valeurs d'en-tête peuvent être de l'un des types suivants :
- `string` - valeur de chaîne normale qui sera envoyée au serveur
- `null` - ignorer l'en-tête lors de la conversion en JSON
- `false` - ignorer l'en-tête lors de la conversion en JSON, indique également que la méthode set doit être appelée avec l'option rewrite définie à true pour écraser cette valeur (Axios l'utilise en interne pour permettre aux utilisateurs de refuser l'installation de certains en-têtes comme User-Agent ou Content-Type)
- `undefined` - la valeur n'est pas définie
::: warning
La valeur de l'en-tête est considérée comme définie si elle n'est pas undefined.
:::
L'objet d'en-têtes est toujours initialisé à l'intérieur des intercepteurs et des transformateurs, comme illustré dans l'exemple suivant :
```js
axios.interceptors.request.use((request: InternalAxiosRequestConfig) => {
request.headers.set("My-header", "value");
request.headers.set({
"My-set-header1": "my-set-value1",
"My-set-header2": "my-set-value2",
});
// Désactiver la définition ultérieure de cet en-tête par Axios
request.headers.set("User-Agent", false);
request.headers.setContentType("text/plain");
// L'accès direct comme celui-ci est déprécié
request.headers["My-set-header2"] = "newValue";
return request;
});
```
Vous pouvez itérer sur un AxiosHeaders en utilisant n'importe quelle méthode itérable, comme une boucle for-of, forEach, ou l'opérateur spread :
```js
const headers = new AxiosHeaders({
foo: '1',
bar: '2',
baz: '3',
});
for (const [header, value] of headers) {
console.log(header, value);
}
// foo 1
// bar 2
// baz 3
```
## Définir des en-têtes sur une requête
L'endroit le plus courant pour définir des en-têtes est l'option `headers` dans votre configuration de requête ou de configuration d'instance :
```js
// Sur une seule requête
await axios.get('/api/data', {
headers: {
'Accept-Language': 'en-US',
'X-Request-ID': 'abc123',
},
});
// Sur une instance (appliqué à chaque requête)
const api = axios.create({
headers: {
'X-App-Version': '2.0.0',
},
});
```
## Préserver la casse d'un en-tête spécifique
Les noms d'en-têtes Axios sont insensibles à la casse, mais `AxiosHeaders` conserve la casse de la première clé correspondante qu'il voit. Si vous avez besoin d'une casse spécifique pour un serveur avec un comportement non standard sensible à la casse, définissez un préréglage de casse dans les valeurs par défaut puis définissez les valeurs normalement.
```js
const api = axios.create();
api.defaults.headers.common = {
'content-type': undefined,
accept: undefined,
};
await api.put(url, data, {
headers: {
'Content-Type': 'application/octet-stream',
Accept: 'application/json',
},
});
```
Vous pouvez également le faire avec `AxiosHeaders` directement lors de la composition d'en-têtes :
```js
import axios, { AxiosHeaders } from 'axios';
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
await axios.put(url, data, { headers });
```
## Définir des en-têtes dans un intercepteur
Les intercepteurs sont l'endroit approprié pour attacher des en-têtes dynamiques comme les tokens d'authentification, car le token peut ne pas être disponible au moment où l'instance est créée :
```js
api.interceptors.request.use((config) => {
const token = getAuthToken(); // lire au moment de la requête
config.headers.set('Authorization', `Bearer ${token}`);
return config;
});
```
## Lire les en-têtes de réponse
Les en-têtes de réponse sont disponibles sur `response.headers` en tant qu'instance d'`AxiosHeaders`. Tous les noms d'en-têtes sont en minuscules :
```js
const response = await axios.get('/api/data');
console.log(response.headers['content-type']);
// application/json; charset=utf-8
console.log(response.headers.get('x-request-id'));
// abc123
```
## Supprimer un en-tête par défaut
Pour refuser un en-tête qu'axios définit par défaut (comme `Content-Type` ou `User-Agent`), définissez sa valeur à `false` :
```js
await axios.post('/api/data', payload, {
headers: {
'Content-Type': false, // laisser le navigateur le définir automatiquement (ex. pour FormData)
},
});
```
Pour plus de détails sur l'API complète des méthodes `AxiosHeaders`, consultez la page [Méthodes d'en-têtes](/pages/advanced/header-methods).
@@ -0,0 +1,57 @@
# Traitement de formulaires HTML (navigateur) <Badge type="tip" text="Nouveau" />
Vous pouvez également envoyer un formulaire directement depuis un élément de formulaire HTML. Cela est utile lorsque vous avez un formulaire dans votre page et que vous souhaitez le soumettre sans aucun code JavaScript.
```js
await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm'));
```
Les objets `FormData` et `HTMLForm` peuvent également être envoyés en `JSON` en définissant explicitement l'en-tête `Content-Type` à `application/json` :
```js
await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), {
headers: {
'Content-Type': 'application/json',
},
});
```
Voici un exemple de formulaire valide pouvant être soumis par le code ci-dessus :
```html
<form id="htmlForm">
<input type="text" name="foo" value="1" />
<input type="text" name="deep.prop" value="2" />
<input type="text" name="deep prop spaced" value="3" />
<input type="text" name="baz" value="4" />
<input type="text" name="baz" value="5" />
<select name="user.age">
<option value="value1">Value 1</option>
<option value="value2" selected>Value 2</option>
<option value="value3">Value 3</option>
</select>
<input type="submit" value="Save" />
</form>
```
Le formulaire ci-dessus sera soumis sous la forme :
```json
{
"foo": "1",
"deep": {
"prop": "2",
"prop spaced": "3"
},
"baz": ["4", "5"],
"user": {
"age": "value2"
}
}
```
::: warning
L'envoi de Blobs/Fichiers en JSON (base64) n'est actuellement pas supporté.
:::
+72
View File
@@ -0,0 +1,72 @@
# HTTP2 <Badge type="warning" text="Expérimental" /> <Badge type="tip" text="v1.13.0+" />
Le support expérimental de HTTP/2 a été ajouté à l'adaptateur `http` dans la version `1.13.0`. Il est disponible uniquement dans les environnements Node.js.
## Utilisation de base
Utilisez l'option `httpVersion` pour sélectionner la version du protocole pour une requête. En la définissant à `2`, vous activez HTTP/2.
```js
const { data, headers, status } = await axios.post(
"https://httpbin.org/post",
form,
{
httpVersion: 2,
},
);
```
## `http2Options`
Des options natives supplémentaires pour l'appel interne `session.request()` peuvent être passées via l'objet de configuration `http2Options`. Cela inclut également le paramètre personnalisé `sessionTimeout`, qui contrôle la durée (en millisecondes) pendant laquelle une session HTTP/2 inactive est maintenue avant d'être fermée. La valeur par défaut est `1000ms`.
```js
{
httpVersion: 2,
http2Options: {
rejectUnauthorized: false, // accepter les certificats auto-signés (développement uniquement)
sessionTimeout: 5000, // maintenir la session inactive pendant 5 secondes
},
}
```
::: warning
Le support HTTP/2 est actuellement expérimental. L'API peut changer dans les prochaines versions mineures ou de correctifs.
:::
## Exemple complet
L'exemple ci-dessous envoie une requête POST `multipart/form-data` via HTTP/2 et suit à la fois la progression de l'envoi et du téléchargement.
```js
const form = new FormData();
form.append("foo", "123");
const { data, headers, status } = await axios.post(
"https://httpbin.org/post",
form,
{
httpVersion: 2,
http2Options: {
// rejectUnauthorized: false,
// sessionTimeout: 1000
},
onUploadProgress(e) {
console.log("upload progress", e);
},
onDownloadProgress(e) {
console.log("download progress", e);
},
responseType: "arraybuffer",
},
);
```
## Référence de configuration
| Option | Type | Défaut | Description |
|---|---|---|---|
| `httpVersion` | `number` | `1` | Version du protocole HTTP à utiliser. Définissez à `2` pour activer HTTP/2. |
| `http2Options.sessionTimeout` | `number` | `1000` | Durée en millisecondes avant qu'une session HTTP/2 inactive soit fermée. |
Toutes les autres options natives de `session.request()` supportées par le module `http2` intégré de Node.js peuvent également être passées dans `http2Options`.
+116
View File
@@ -0,0 +1,116 @@
# Intercepteurs
Les intercepteurs sont un mécanisme puissant permettant d'intercepter et de modifier les requêtes et réponses HTTP. Ils sont très similaires aux middlewares dans Express.js. Un intercepteur est une fonction exécutée avant l'envoi d'une requête et avant la réception d'une réponse. Les intercepteurs sont utiles pour de nombreuses tâches telles que la journalisation, la modification des en-têtes de requête et la modification de la réponse.
L'utilisation de base des intercepteurs est la suivante :
```js
// Ajouter un intercepteur de requête
axios.interceptors.request.use(
function (config) {
// Effectuez une action avant l'envoi de la requête
return config;
},
function (error) {
// Traitez l'erreur de requête
return Promise.reject(error);
}
);
// Ajouter un intercepteur de réponse
axios.interceptors.response.use(
function (response) {
// Tout code de statut dans la plage 2xx déclenchera cette fonction
// Traitez les données de réponse
return response;
},
function (error) {
// Tout code de statut en dehors de la plage 2xx déclenchera cette fonction
// Traitez l'erreur de réponse
return Promise.reject(error);
}
);
```
## Supprimer des intercepteurs
Vous pouvez supprimer n'importe quel intercepteur en utilisant la méthode `eject` sur l'intercepteur que vous souhaitez supprimer. Vous pouvez également supprimer tous les intercepteurs en appelant la méthode `clear` sur l'objet `axios.interceptors`. Voici un exemple de suppression d'un intercepteur :
```js
// Éjecter l'intercepteur de requête
const myInterceptor = axios.interceptors.request.use(function () {
/*...*/
});
axios.interceptors.request.eject(myInterceptor);
// Éjecter l'intercepteur de réponse
const myInterceptor = axios.interceptors.response.use(function () {
/*...*/
});
axios.interceptors.response.eject(myInterceptor);
```
Voici un exemple de suppression de tous les intercepteurs :
```js
const instance = axios.create();
instance.interceptors.request.use(function () {
/*...*/
});
instance.interceptors.request.clear(); // Supprime les intercepteurs des requêtes
instance.interceptors.response.use(function () {
/*...*/
});
instance.interceptors.response.clear(); // Supprime les intercepteurs des réponses
```
## Comportement par défaut des intercepteurs
Lorsque vous ajoutez des intercepteurs de requête, ils sont considérés comme asynchrones par défaut. Cela peut provoquer un délai dans l'exécution de votre requête axios lorsque le thread principal est bloqué (une promise est créée en coulisses pour l'intercepteur et votre requête est placée en bas de la pile d'appels). Si vos intercepteurs de requête sont synchrones, vous pouvez ajouter un indicateur à l'objet d'options qui indiquera à axios d'exécuter le code de manière synchrone et d'éviter tout délai dans l'exécution des requêtes.
```js
axios.interceptors.request.use(
function (config) {
config.headers.test = "I am only a header!";
return config;
},
null,
{ synchronous: true }
);
```
## Intercepteurs avec `runWhen`
Si vous souhaitez exécuter un intercepteur particulier en fonction d'une vérification au moment de l'exécution, vous pouvez ajouter une fonction `runWhen` à l'objet d'options. L'intercepteur ne sera pas exécuté si et seulement si le résultat de `runWhen` est `false`. La fonction sera appelée avec l'objet de configuration (n'oubliez pas que vous pouvez également y lier vos propres arguments). Cela peut être utile lorsque vous avez un intercepteur de requête asynchrone qui ne doit s'exécuter que dans certaines conditions.
```js
function onGetCall(config) {
return config.method === "get";
}
axios.interceptors.request.use(
function (config) {
config.headers.test = "special get headers";
return config;
},
null,
{ runWhen: onGetCall }
);
```
## Intercepteurs multiples
Vous pouvez ajouter plusieurs intercepteurs à la même requête ou réponse. Les règles suivantes s'appliquent pour plusieurs intercepteurs dans la même chaîne, dans l'ordre indiqué ci-dessous :
- Chaque intercepteur est exécuté
- Les intercepteurs de requête sont exécutés dans l'ordre inverse (LIFO).
- Les intercepteurs de réponse sont exécutés dans l'ordre où ils ont été ajoutés (FIFO).
- Seul le résultat du dernier intercepteur est retourné
- Chaque intercepteur reçoit le résultat de son prédécesseur
- Lorsqu'un intercepteur de réussite lève une exception :
- L'intercepteur de réussite suivant n'est pas appelé
- L'intercepteur d'échec suivant est appelé
- Une fois capturée, un autre intercepteur de réussite suivant est à nouveau appelé (comme dans une chaîne de promises).
::: tip
Pour une compréhension approfondie du fonctionnement des intercepteurs, vous pouvez lire les cas de test disponibles [ici](https://github.com/axios/axios/blob/v1.x/test/specs/interceptors.spec.js).
:::
@@ -0,0 +1,120 @@
# Format multipart/form-data
axios peut envoyer des requêtes au format `multipart/form-data`. Ce format est couramment utilisé lors de l'envoi de fichiers. Pour envoyer une requête dans ce format, vous devez créer un objet `FormData` et y ajouter les données. Vous pouvez ensuite passer l'objet `FormData` à la propriété `data` de la configuration de requête axios.
```js
const formData = new FormData();
formData.append("foo", "bar");
axios.post("https://httpbin.org/post", formData);
```
Dans Node.js, vous pouvez utiliser la bibliothèque `form-data` comme suit :
```js
const FormData = require("form-data");
const form = new FormData();
form.append("my_field", "my value");
form.append("my_buffer", Buffer.alloc(10));
form.append("my_file", fs.createReadStream("/foo/bar.jpg"));
axios.post("https://example.com", form);
```
## Sérialisation automatique vers FormData <Badge type="tip" text="Nouveau" />
À partir de la version v0.27.0, Axios prend en charge la sérialisation automatique d'objets en objet FormData si l'en-tête Content-Type de la requête est défini à multipart/form-data. Cela signifie que vous pouvez passer directement un objet JavaScript à la propriété data de la configuration de requête axios. Par exemple lors de l'envoi de données vers une requête POST :
```js
import axios from "axios";
axios
.post(
"https://httpbin.org/post",
{ x: 1 },
{
headers: {
"Content-Type": "multipart/form-data",
},
}
)
.then(({ data }) => console.log(data));
```
Dans la version Node.js, le polyfill ([`form-data`](https://github.com/form-data/form-data)) est utilisé par défaut. Vous pouvez remplacer la classe FormData en définissant la variable de configuration env.FormData, mais vous n'en aurez probablement pas besoin dans la plupart des cas :
```js
const axios = require("axios");
var FormData = require("form-data");
axios
.post(
"https://httpbin.org/post",
{ x: 1, buf: Buffer.alloc(10) },
{
headers: {
"Content-Type": "multipart/form-data",
},
}
)
.then(({ data }) => console.log(data));
```
## Terminaisons supportées
Le sérialiseur FormData d'Axios supporte quelques terminaisons spéciales pour effectuer les opérations suivantes :
- `{}` - sérialiser la valeur avec JSON.stringify
- `[]` - décomposer l'objet de type tableau en champs séparés avec la même clé
::: warning
Remarque : l'opération de décomposition/expansion sera utilisée par défaut sur les tableaux et les objets FileList
:::
## Configurer le sérialiseur FormData
Le sérialiseur FormData supporte des options supplémentaires via la propriété d'objet config.formSerializer pour gérer les cas particuliers :
- `visitor: Function` - fonction visiteur définie par l'utilisateur qui sera appelée récursivement pour sérialiser l'objet de données en objet FormData en suivant des règles personnalisées.
- `dots: boolean = false` - utiliser la notation pointée au lieu de crochets pour sérialiser les tableaux et les objets ;
- `metaTokens: boolean = true` - ajouter la terminaison spéciale (ex. `user{}: '{"name": "John"}'`) dans la clé FormData. Le body-parser du backend pourrait potentiellement utiliser ces méta-informations pour analyser automatiquement la valeur en JSON.
- `indexes: null|false|true = false` - contrôle comment les index seront ajoutés aux clés décomposées d'objets de type tableau plat
- `null` - ne pas ajouter de crochets (`arr: 1`, `arr: 2`, `arr: 3`)
- `false` (défaut) - ajouter des crochets vides (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)
- `true` - ajouter des crochets avec index (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)
Par exemple, si nous avons un objet comme celui-ci :
```js
const obj = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: "Peter", surname: "Griffin" },
{ name: "Thomas", surname: "Anderson" },
],
"obj2{}": [{ x: 1 }],
};
```
Les étapes suivantes seront exécutées en interne par le sérialiseur Axios :
```js
const formData = new FormData();
formData.append("x", "1");
formData.append("arr[]", "1");
formData.append("arr[]", "2");
formData.append("arr[]", "3");
formData.append("arr2[0]", "1");
formData.append("arr2[1][0]", "2");
formData.append("arr2[2]", "3");
formData.append("users[0][name]", "Peter");
formData.append("users[0][surname]", "Griffin");
formData.append("users[1][name]", "Thomas");
formData.append("users[1][surname]", "Anderson");
formData.append("obj2{}", '[{"x":1}]');
```
Axios supporte les méthodes raccourcies suivantes : `postForm`, `putForm`, `patchForm` qui sont simplement les méthodes HTTP correspondantes avec l'en-tête `Content-Type` prédéfini à `multipart/form-data`.
@@ -0,0 +1,55 @@
# Capture de progression <Badge type="tip" text="Nouveau" />
Axios prend en charge la capture de la progression des envois et téléchargements dans les environnements navigateur et Node.js. La fréquence des événements de progression est limitée à 3 fois par seconde. Cela permet d'éviter de surcharger le navigateur avec des événements de progression. Voici un exemple de capture d'événements de progression :
```js
await axios.post(url, data, {
onUploadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number; // dans la plage [0..1]
bytes: number; // nombre d'octets transférés depuis le dernier déclenchement (delta)
estimated?: number; // temps estimé en secondes
rate?: number; // vitesse d'envoi en octets
upload: true; // indicateur d'envoi
}*/
},
onDownloadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number;
bytes: number;
estimated?: number;
rate?: number; // vitesse de téléchargement en octets
download: true; // indicateur de téléchargement
}*/
},
});
```
Vous pouvez également transmettre les événements de progression d'envoi et de téléchargement vers un stream lisible dans Node.js. Cela est utile lorsque vous souhaitez afficher la progression de manière personnalisée. Voici un exemple de transmission des événements de progression :
```js
const { data } = await axios.post(SERVER_URL, readableStream, {
onUploadProgress: ({ progress }) => {
console.log((progress * 100).toFixed(2));
},
headers: {
"Content-Length": contentLength,
},
maxRedirects: 0, // éviter de buffériser l'intégralité du stream
});
```
::: warning
La capture de la progression d'envoi de FormData n'est actuellement pas supportée dans les environnements Node.js
:::
::: danger
Il est recommandé de désactiver les redirections en définissant maxRedirects: 0 pour envoyer le stream dans l'environnement Node.js, car le package follow-redirects bufférisera l'intégralité du stream en RAM sans suivre l'algorithme de « backpressure »
:::
+81
View File
@@ -0,0 +1,81 @@
# Promises
axios est construit sur l'API Promise native d'ES6. Chaque requête axios retourne une Promise qui se résout vers un objet de réponse ou se rejette avec une erreur. Si votre environnement ne supporte pas les Promises ES6, vous devrez les polyfiller — par exemple avec [es6-promise](https://github.com/stefanpenner/es6-promise).
## then / catch / finally
Comme axios retourne une Promise standard, vous pouvez utiliser `.then()`, `.catch()` et `.finally()` pour gérer le résultat :
```js
axios.get("/api/users")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error("Request failed:", error.message);
})
.finally(() => {
console.log("Request finished");
});
```
## async / await
L'approche recommandée pour la plupart des bases de code est `async/await`, qui rend le code asynchrone lisible comme du code synchrone :
```js
async function fetchUser(id) {
try {
const response = await axios.get(`/api/users/${id}`);
return response.data;
} catch (error) {
console.error("Failed to fetch user:", error.message);
throw error;
}
}
```
## Requêtes parallèles
Comme axios retourne une Promise standard, vous pouvez utiliser `Promise.all` pour effectuer plusieurs requêtes simultanément et attendre qu'elles se terminent toutes :
```js
const [users, posts] = await Promise.all([
axios.get("/api/users"),
axios.get("/api/posts"),
]);
console.log(users.data, posts.data);
```
::: tip
`Promise.all` rejettera dès que l'une des requêtes échoue. Si vous souhaitez gérer les échecs partiels, utilisez plutôt `Promise.allSettled`.
:::
```js
const results = await Promise.allSettled([
axios.get("/api/users"),
axios.get("/api/posts"),
]);
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log(result.value.data);
} else {
console.error("Request failed:", result.reason.message);
}
});
```
## Chaînage de requêtes
Vous pouvez chaîner des appels `.then()` pour exécuter des requêtes séquentiellement, en passant les données d'une requête à la suivante :
```js
axios.get("/api/user/1")
.then(({ data: user }) => axios.get(`/api/posts?userId=${user.id}`))
.then(({ data: posts }) => {
console.log("Posts for user:", posts);
})
.catch(console.error);
```
+62
View File
@@ -0,0 +1,62 @@
# Limitation de débit <Badge type="tip" text="Nouveau" />
axios prend en charge la limitation de bande passante dans l'environnement Node.js via l'adaptateur HTTP. Cela vous permet de plafonner la vitesse d'envoi ou de téléchargement des données, ce qui est utile pour les opérations en masse, les tâches en arrière-plan ou le scraping respectueux qui ne doit pas saturer une connexion.
## `maxRate`
L'option `maxRate` accepte soit un nombre (octets par seconde) soit un tableau où la première valeur est la limite d'envoi et la deuxième valeur est la limite de téléchargement. Utilisez `[uploadRate]` pour limiter uniquement l'envoi, ou `[uploadRate, downloadRate]` pour limiter les deux sens. Lorsqu'un nombre unique est passé, la même limite s'applique à l'envoi et au téléchargement.
```js
// Limiter l'envoi et le téléchargement à 100 Ko/s
await axios.get(URL, { maxRate: 100 * 1024 });
// Limiter l'envoi à 100 Ko/s, le téléchargement à 500 Ko/s
await axios.get(URL, { maxRate: [100 * 1024, 500 * 1024] });
```
::: warning
`maxRate` n'est supporté que par l'adaptateur HTTP Node.js. Il n'a aucun effet dans les environnements navigateur.
:::
## Limitation du débit d'envoi
Plafonnez la vitesse d'envoi tout en journalisant la progression en même temps :
```js
const { data } = await axios.post(SERVER_URL, myBuffer, {
onUploadProgress: ({ progress, rate }) => {
const percent = (progress * 100).toFixed(1);
const kbps = (rate / 1024).toFixed(1);
console.log(`Upload [${percent}%] at ${kbps} KB/s`);
},
maxRate: [100 * 1024], // plafonner l'envoi à 100 Ko/s
});
```
## Limitation du débit de téléchargement
Plafonnez la vitesse de téléchargement pour les réponses volumineuses :
```js
const { data } = await axios.get(FILE_URL, {
onDownloadProgress: ({ progress, rate }) => {
const percent = (progress * 100).toFixed(1);
const kbps = (rate / 1024).toFixed(1);
console.log(`Download [${percent}%] at ${kbps} KB/s`);
},
maxRate: [Infinity, 200 * 1024], // pas de limite d'envoi, 200 Ko/s en téléchargement
responseType: "arraybuffer",
});
```
## Limitation combinée envoi et téléchargement
Passez les deux limites sous forme de tableau pour contrôler les deux sens simultanément :
```js
await axios.post(SERVER_URL, largeBuffer, {
maxRate: [50 * 1024, 500 * 1024], // 50 Ko/s en envoi, 500 Ko/s en téléchargement
});
```
+350
View File
@@ -0,0 +1,350 @@
# Configuration de requête
La configuration de requête est utilisée pour paramétrer la requête. Un large éventail d'options est disponible, mais la seule option obligatoire est `url`. Si l'objet de configuration ne contient pas de champ `method`, la méthode par défaut est `GET`.
### `url`
L'`url` est l'URL vers laquelle la requête est envoyée. Il peut s'agir d'une chaîne de caractères ou d'une instance de `URL`.
### `method`
La `method` est la méthode HTTP à utiliser pour la requête. La méthode par défaut est `GET`.
### `baseURL`
La `baseURL` est l'URL de base à ajouter en préfixe à l'`url`, sauf si celle-ci est une URL absolue. Utile pour effectuer des requêtes vers le même domaine sans avoir à répéter le nom de domaine et tout préfixe d'API ou de version.
### `allowAbsoluteUrls`
`allowAbsoluteUrls` détermine si les URLs absolues peuvent remplacer une `baseUrl` configurée. Lorsqu'elle est définie à `true` (valeur par défaut), les valeurs absolues de `url` remplacent `baseUrl`. Lorsqu'elle est définie à `false`, les valeurs absolues de `url` sont toujours précédées de `baseUrl`.
### `transformRequest`
La fonction `transformRequest` vous permet de modifier les données de la requête avant leur envoi au serveur. Cette fonction est appelée avec les données de la requête comme seul argument. Elle ne s'applique que pour les méthodes de requête `PUT`, `POST`, `PATCH` et `DELETE`. La dernière fonction du tableau doit retourner une chaîne ou une instance de Buffer, ArrayBuffer, FormData ou Stream.
### `transformResponse`
La fonction `transformResponse` vous permet de modifier les données de la réponse avant qu'elles ne soient transmises aux fonctions `then` ou `catch`. Cette fonction est appelée avec les données de la réponse comme seul argument.
### `headers`
Les `headers` sont les en-têtes HTTP à envoyer avec la requête. L'en-tête `Content-Type` est défini à `application/json` par défaut.
### `params`
Les `params` sont les paramètres d'URL à envoyer avec la requête. Il doit s'agir d'un objet simple ou d'un objet URLSearchParams. Si l'`url` contient des paramètres de requête, ils seront fusionnés avec l'objet `params`.
### `paramsSerializer`
La fonction `paramsSerializer` vous permet de sérialiser l'objet `params` avant son envoi au serveur. Plusieurs options sont disponibles pour cette fonction ; veuillez vous référer à l'exemple de configuration complète en bas de cette page.
### `data`
Les `data` sont les données à envoyer comme corps de la requête. Il peut s'agir d'une chaîne, d'un objet simple, d'un Buffer, d'un ArrayBuffer, d'un FormData, d'un Stream ou d'un URLSearchParams. Ne s'applique que pour les méthodes de requête `PUT`, `POST`, `DELETE` et `PATCH`. Sans `transformRequest`, doit être de l'un des types suivants :
- chaîne, objet simple, ArrayBuffer, ArrayBufferView, URLSearchParams
- Navigateur uniquement : FormData, File, Blob
- Node uniquement : Stream, Buffer, FormData (package form-data)
### `timeout`
Le `timeout` est le nombre de millisecondes avant l'expiration de la requête. Si la requête dure plus longtemps que `timeout`, elle sera annulée.
### `withCredentials`
La propriété `withCredentials` indique si les requêtes Cross-site Access-Control doivent être effectuées avec des informations d'identification telles que des cookies, des en-têtes d'autorisation ou des certificats client TLS. La définition de `withCredentials` n'a aucun effet sur les requêtes du même site.
### `adapter`
`adapter` permet une gestion personnalisée des requêtes, ce qui facilite les tests. Retournez une promise et fournissez une réponse valide ; consultez [les adaptateurs](/pages/advanced/adapters) pour plus d'informations. Nous fournissons également un certain nombre d'adaptateurs intégrés. L'adaptateur par défaut est `http` pour Node et `xhr` pour les navigateurs. La liste complète des adaptateurs intégrés est la suivante :
- fetch
- http
- xhr
Vous pouvez également passer un tableau d'adaptateurs ; axios utilisera le premier pris en charge par l'environnement.
### `auth`
`auth` indique que l'authentification HTTP Basic doit être utilisée, et fournit les identifiants. Cela définira un en-tête `Authorization`, en écrasant tout en-tête `Authorization` personnalisé que vous auriez défini via `headers`. Notez que seule l'authentification HTTP Basic est configurable via ce paramètre. Pour les tokens Bearer et similaires, utilisez plutôt des en-têtes `Authorization` personnalisés.
### `responseType`
Le `responseType` indique le type de données que le serveur retournera. Il peut s'agir de l'un des types suivants :
- arraybuffer
- document
- json
- text
- stream
- blob (navigateur uniquement)
- formdata (adaptateur fetch uniquement)
### `responseEncoding` <Badge type="warning" text="Node.js uniquement" />
Le `responseEncoding` indique l'encodage à utiliser pour décoder les réponses. Les options suivantes sont prises en charge :
- ascii
- ASCII
- ansi
- ANSI
- binary
- BINARY
- base64
- BASE64
- base64url
- BASE64URL
- hex
- HEX
- latin1
- LATIN1
- ucs-2
- UCS-2
- ucs2
- UCS2
- utf-8
- UTF-8
- utf8
- UTF8
- utf16le
- UTF16LE
::: tip
Remarque : ignoré pour un `responseType` de `stream` ou pour les requêtes côté client
:::
### `xsrfCookieName`
Le `xsrfCookieName` est le nom du cookie à utiliser comme valeur pour le token `XSRF`.
### `xsrfHeaderName`
Le `xsrfHeaderName` est le nom de l'en-tête à utiliser comme valeur pour le token `XSRF`.
### `withXSRFToken`
La propriété `withXSRFToken` indique si le token `XSRF` doit être envoyé avec la requête. Ne s'applique qu'aux requêtes côté client. La valeur par défaut est `undefined`.
### `onUploadProgress`
La fonction `onUploadProgress` vous permet d'écouter la progression d'un envoi.
### `onDownloadProgress`
La fonction `onDownloadProgress` vous permet d'écouter la progression d'un téléchargement.
### `maxContentLength` <Badge type="warning" text="Node.js uniquement" />
La propriété `maxContentLength` définit le nombre maximum d'octets que le serveur acceptera dans la réponse.
### `maxBodyLength` <Badge type="warning" text="Node.js uniquement" />
La propriété `maxBodyLength` définit le nombre maximum d'octets que le serveur acceptera dans la requête.
### `validateStatus`
La fonction `validateStatus` vous permet de remplacer la validation du code de statut par défaut. Par défaut, axios rejette la promise si le code de statut n'est pas dans la plage 200-299. Vous pouvez remplacer ce comportement en fournissant une fonction `validateStatus` personnalisée. La fonction doit retourner `true` si le code de statut est dans la plage que vous souhaitez accepter.
### `maxRedirects` <Badge type="warning" text="Node.js uniquement" />
La propriété `maxRedirects` définit le nombre maximum de redirections à suivre. Si défini à 0, aucune redirection ne sera suivie.
### `beforeRedirect`
La fonction `beforeRedirect` vous permet de modifier la requête avant qu'elle ne soit redirigée. Utilisez-la pour ajuster les options de requête lors d'une redirection, inspecter les derniers en-têtes de réponse, ou annuler la requête en levant une erreur. Si `maxRedirects` est défini à 0, `beforeRedirect` n'est pas utilisé.
### `socketPath` <Badge type="warning" text="Node.js uniquement" />
La propriété `socketPath` définit un socket UNIX à utiliser à la place d'une connexion TCP. Par exemple `/var/run/docker.sock` pour envoyer des requêtes au daemon Docker. Seul `socketPath` ou `proxy` peut être spécifié. Si les deux sont spécifiés, `socketPath` est utilisé.
### `transport`
La propriété `transport` définit le transport à utiliser pour la requête. Utile pour effectuer des requêtes via un protocole différent, comme `http2`.
### `httpAgent` et `httpsAgent`
Les `httpAgent` et `httpsAgent` définissent un agent personnalisé à utiliser pour les requêtes http et https respectivement dans Node.js. Cela permet d'ajouter des options comme `keepAlive` qui ne sont pas activées par défaut.
### `proxy`
Le `proxy` définit le nom d'hôte, le port et le protocole d'un serveur proxy que vous souhaitez utiliser. Vous pouvez également définir votre proxy en utilisant les variables d'environnement conventionnelles `http_proxy` et `https_proxy`.
Si vous utilisez des variables d'environnement pour la configuration de votre proxy, vous pouvez également définir une variable d'environnement `no_proxy` sous la forme d'une liste de domaines séparés par des virgules qui ne doivent pas être mandatés.
Utilisez `false` pour désactiver les proxies, en ignorant les variables d'environnement. `auth` indique que l'authentification HTTP Basic doit être utilisée pour se connecter au proxy, et fournit les identifiants. Cela définira un en-tête `Proxy-Authorization`, en écrasant tout en-tête `Proxy-Authorization` personnalisé que vous auriez défini via `headers`. Si le serveur proxy utilise HTTPS, vous devez définir le protocole à `https`.
```js
proxy: {
protocol: "https",
host: "127.0.0.1",
hostname: "localhost", // Prend le dessus sur "host" si les deux sont définis
port: 9000,
auth: {
username: "mikeymike",
password: "rapunz3l"
}
},
```
### `cancelToken`
La propriété `cancelToken` vous permet de créer un token d'annulation pouvant être utilisé pour annuler la requête. Pour plus d'informations, consultez la documentation sur l'[annulation](/pages/advanced/cancellation).
### `signal`
La propriété `signal` vous permet de passer une instance d'`AbortSignal` à la requête. Cela vous permet d'annuler la requête en utilisant l'API `AbortController`.
### `decompress` <Badge type="warning" text="Node.js uniquement" />
La propriété `decompress` indique si les données de la réponse doivent être automatiquement décompressées. La valeur par défaut est `true`.
### `insecureHTTPParser`
Indique s'il faut utiliser un analyseur HTTP non sécurisé qui accepte des en-têtes HTTP invalides. Cela peut permettre l'interopérabilité avec des implémentations HTTP non conformes. L'utilisation de l'analyseur non sécurisé doit être évitée.
Notez que l'option `insecureHTTPParser` n'est disponible que dans Node.js 12.10.0 et ultérieur. Consultez la [documentation Node.js](https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none) pour plus d'informations. Voir l'ensemble complet des options [ici](https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback)
### `transitional`
La propriété `transitional` vous permet d'activer ou de désactiver certaines fonctionnalités de transition. Les options suivantes sont disponibles :
- `silentJSONParsing` : Si défini à `true`, axios n'affichera pas d'avertissement lorsqu'il rencontre des réponses JSON invalides, définissant la valeur de retour à null. Utile lorsque vous travaillez avec des APIs qui retournent du JSON invalide.
- `forcedJSONParsing` : Force axios à analyser les réponses JSON comme du JSON, même si la réponse n'est pas du JSON valide. Utile lorsque vous travaillez avec des APIs qui retournent du JSON invalide.
- `clarifyTimeoutError` : Clarifie le message d'erreur lorsqu'une requête expire. Utile lors du débogage de problèmes de délai d'attente.
- `legacyInterceptorReqResOrdering` : Lorsque défini à true, l'ordre hérité de traitement requête/réponse des intercepteurs sera utilisé.
### `env`
La propriété `env` vous permet de définir certaines options de configuration. Par exemple, la classe FormData qui est utilisée pour sérialiser automatiquement le payload en objet FormData.
- FormData: window?.FormData || global?.FormData
### `formSerializer`
La fonction `formSerializer` vous permet de sérialiser l'objet `data` avant son envoi au serveur. Plusieurs options sont disponibles pour cette fonction ; veuillez vous référer à l'exemple de configuration complète en bas de cette page.
### `maxRate` <Badge type="warning" text="Node.js uniquement" />
La propriété `maxRate` définit la **bande passante** maximale (en octets par seconde) pour l'envoi et/ou le téléchargement. Elle accepte soit un nombre unique (appliqué dans les deux sens) soit un tableau de deux éléments `[uploadRate, downloadRate]` où chaque élément est une limite en octets par seconde. Par exemple, `100 * 1024` signifie 100 Ko/s. Consultez [Limitation de débit](/pages/advanced/rate-limiting) pour des exemples.
## Exemple de configuration complète
```js
{
url: "/posts",
method: "get",
baseURL: "https://jsonplaceholder.typicode.com",
allowAbsoluteUrls: true,
transformRequest: [function (data, headers) {
return data;
}],
transformResponse: [function (data) {
return data;
}],
headers: {"X-Requested-With": "XMLHttpRequest"},
params: {
postId: 5
},
paramsSerializer: {
// Fonction d'encodage personnalisée qui envoie les paires clé/valeur de façon itérative.
encode?: (param: string): string => { /* Effectuez des opérations personnalisées ici et retournez la chaîne transformée */ },
// Fonction de sérialisation personnalisée pour l'ensemble du paramètre. Permet à l'utilisateur de reproduire le comportement antérieur à la v1.x.
serialize?: (params: Record<string, any>, options?: ParamsSerializerOptions ),
// Configuration du format des index de tableaux dans les params.
// Trois options disponibles :
// (1) indexes: null (pas de crochets)
// (2) (défaut) indexes: false (crochets vides)
// (3) indexes: true (crochets avec index).
indexes: false
},
data: {
firstName: "Fred"
},
// Syntaxe alternative pour envoyer des données dans le corps de la méthode post : seule la valeur est envoyée, pas la clé
data: "Country=Brasil&City=Belo Horizonte",
timeout: 1000,
withCredentials: false,
adapter: function (config) {
// Faites ce que vous voulez
},
adapter: "xhr",
auth: {
username: "janedoe",
password: "s00pers3cret"
},
responseType: "json",
responseEncoding: "utf8",
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined),
onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) {
// Faites ce que vous voulez avec l'événement de progression Axios
},
onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) {
// Faites ce que vous voulez avec l'événement de progression Axios
},
maxContentLength: 2000,
maxBodyLength: 2000,
validateStatus: function (status) {
return status >= 200 && status < 300;
},
maxRedirects: 21,
beforeRedirect: (options, { headers }) => {
if (options.hostname === "typicode.com") {
options.auth = "user:password";
}
},
socketPath: null,
transport: undefined,
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
proxy: {
protocol: "https",
host: "127.0.0.1",
// hostname: "127.0.0.1" // Prend le dessus sur "host" si les deux sont définis
port: 9000,
auth: {
username: "mikeymike",
password: "rapunz3l"
}
},
cancelToken: new CancelToken(function (cancel) {
cancel("Operation has been canceled.");
}),
signal: new AbortController().signal,
decompress: true,
insecureHTTPParser: undefined,
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false,
legacyInterceptorReqResOrdering: true,
},
env: {
FormData: window?.FormData || global?.FormData
},
formSerializer: {
// Fonction visiteur personnalisée pour sérialiser les valeurs du formulaire
visitor: (value, key, path, helpers) => {};
// Utiliser des points au lieu de crochets
dots: boolean;
// Conserver les terminaisons spéciales comme {} dans la clé de paramètre
metaTokens: boolean;
// Utiliser le format des index de tableau :
// null - pas de crochets
// false - crochets vides
// true - crochets avec index
indexes: boolean;
},
maxRate: [
100 * 1024, // Limite d'envoi de 100Ko/s,
100 * 1024 // Limite de téléchargement de 100Ko/s
]
}
```
@@ -0,0 +1,130 @@
# Alias de requête
axios fournit un ensemble d'alias pour effectuer des requêtes HTTP. Ces alias sont des raccourcis pour effectuer des requêtes via la méthode `request`. Ils sont conçus pour être faciles à utiliser et offrir une façon plus pratique d'effectuer des requêtes.
axios s'efforce de suivre les RFC 7231 et RFC 5789 aussi fidèlement que possible. Les alias sont conçus pour être cohérents avec les méthodes HTTP définies dans ces RFC.
### `axios`
axios peut être utilisé pour effectuer une requête HTTP en passant uniquement l'objet de configuration. L'objet de configuration complet est documenté [ici](/pages/advanced/request-config)
```ts
axios(url: string | AxiosRequestConfig, config?: AxiosRequestConfig);
```
## Alias de méthode
Les alias suivants sont disponibles pour effectuer des requêtes :
### `request`
La méthode `request` est la méthode principale pour effectuer des requêtes HTTP. Elle accepte un objet de configuration en argument et retourne une promise qui se résout vers l'objet de réponse. C'est une méthode générique pouvant être utilisée pour tout type de requête HTTP.
```ts
axios.request(config: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `get`
La méthode `get` est utilisée pour effectuer une requête GET. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse.
```ts
axios.get(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `delete`
La méthode `delete` est utilisée pour effectuer une requête DELETE. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse.
```ts
axios.delete(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `head`
La méthode `head` est utilisée pour effectuer une requête HEAD. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse.
```ts
axios.head(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `options`
La méthode `options` est utilisée pour effectuer une requête OPTIONS. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse.
```ts
axios.options(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `post`
La méthode `post` est utilisée pour effectuer une requête POST. Elle accepte une URL, un objet de données optionnel et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse.
```ts
axios.post(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `put`
La méthode `put` est utilisée pour effectuer une requête PUT. Elle accepte une URL, un objet de données optionnel et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse.
```ts
axios.put(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `patch`
La méthode `patch` est utilisée pour effectuer une requête PATCH. Elle accepte une URL, un objet de données optionnel et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse.
```ts
axios.patch(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
## Méthodes raccourcies pour les données de formulaire
Ces méthodes sont équivalentes à leurs homologues ci-dessus, mais prédéfinissent le `Content-Type` à `multipart/form-data`. Elles constituent la façon recommandée d'envoyer des fichiers ou de soumettre des formulaires HTML.
### `postForm`
```ts
axios.postForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// Envoyer un fichier depuis un input file du navigateur
await axios.postForm("/api/upload", {
file: document.querySelector("#fileInput").files[0],
description: "Profile photo",
});
```
### `putForm`
```ts
axios.putForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// Remplacer une ressource avec des données de formulaire
await axios.putForm("/api/users/1/avatar", {
avatar: document.querySelector("#avatarInput").files[0],
});
```
### `patchForm`
```ts
axios.patchForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// Mettre à jour des champs spécifiques avec des données de formulaire
await axios.patchForm("/api/users/1", {
displayName: "New Name",
avatar: document.querySelector("#avatarInput").files[0],
});
```
::: tip
`postForm`, `putForm` et `patchForm` acceptent les mêmes types de données que leurs méthodes de base — objets simples, `FormData`, `FileList` et `HTMLFormElement`. Consultez [Envoi de fichiers](/pages/advanced/file-posting) pour plus d'exemples.
:::
+64
View File
@@ -0,0 +1,64 @@
# Schéma de réponse
Chaque requête axios se résout vers un objet de réponse ayant la structure suivante. Le schéma est cohérent aussi bien dans les environnements navigateur que Node.js.
```js
{
// Les données de réponse fournies par le serveur.
// Lors de l'utilisation de `transformResponse`, ce sera le résultat de la dernière transformation.
data: {},
// Le code de statut HTTP de la réponse du serveur (ex. 200, 404, 500).
status: 200,
// Le message de statut HTTP correspondant au code de statut (ex. "OK", "Not Found").
statusText: "OK",
// Les en-têtes de réponse envoyés par le serveur.
// Les noms d'en-têtes sont en minuscules. Vous pouvez y accéder par notation crochet ou point.
headers: {},
// La configuration axios utilisée pour cette requête, incluant baseURL,
// headers, timeout, params, et toutes autres options que vous avez fournies.
config: {},
// L'objet de requête sous-jacent.
// Dans Node.js : la dernière instance de `http.ClientRequest` (après toute redirection).
// Dans le navigateur : l'instance de `XMLHttpRequest`.
request: {},
}
```
## Accéder aux champs de la réponse
En pratique, vous déstructurerez généralement uniquement les parties dont vous avez besoin :
```js
const { data, status, headers } = await axios.get("/api/users/1");
console.log(status); // 200
console.log(headers["content-type"]); // "application/json; charset=utf-8"
console.log(data); // { id: 1, name: "Jay", email: "jay@example.com" }
```
## Vérifier le code de statut
axios résout la promise pour toute réponse 2xx et rejette pour tout ce qui est en dehors de cette plage par défaut. Vous pouvez personnaliser ce comportement avec l'option de configuration `validateStatus` :
```js
const response = await axios.get("/api/resource", {
validateStatus: (status) => status < 500, // résoudre pour tout statut inférieur à 500
});
```
## Accéder aux en-têtes de réponse
Tous les noms d'en-têtes de réponse sont en minuscules, quelle que soit la façon dont le serveur les a envoyés :
```js
const response = await axios.get("/api/resource");
// Ces deux lignes sont équivalentes
const contentType = response.headers["content-type"];
const contentType2 = response.headers.get("content-type");
```
+130
View File
@@ -0,0 +1,130 @@
# Nouvelles tentatives et récupération sur erreur
Les requêtes réseau peuvent échouer pour des raisons transitoires — une défaillance momentanée du serveur, une brève interruption du réseau, ou une réponse de limitation de débit. Implémenter une stratégie de nouvelle tentative dans un intercepteur vous permet de gérer ces échecs de manière transparente, sans polluer votre code applicatif.
## Nouvelle tentative de base avec un intercepteur de réponse
L'approche la plus simple consiste à intercepter des codes de statut d'erreur spécifiques et à renvoyer immédiatement la requête originale un nombre limité de fois :
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
const MAX_RETRIES = 3;
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
// Ne réessayer que pour les erreurs réseau ou les erreurs serveur 5xx
const shouldRetry =
!error.response || (error.response.status >= 500 && error.response.status < 600);
if (!shouldRetry) {
return Promise.reject(error);
}
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= MAX_RETRIES) {
return Promise.reject(error);
}
config._retryCount += 1;
return api(config);
}
);
```
## Délai exponentiel
Réessayer immédiatement après un échec peut surcharger un serveur déjà en difficulté. Le délai exponentiel attend progressivement plus longtemps entre chaque tentative :
```js
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
const shouldRetry =
!error.response || (error.response.status >= 500 && error.response.status < 600);
if (!shouldRetry) return Promise.reject(error);
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= 3) return Promise.reject(error);
config._retryCount += 1;
// Attendre 200ms, 400ms, 800ms, ... avant chaque nouvelle tentative
const backoff = 100 * 2 ** config._retryCount;
await delay(backoff);
return api(config);
}
);
```
## Nouvelle tentative sur 429 (limite de débit) avec Retry-After
Lorsque le serveur répond avec `429 Too Many Requests`, il inclut souvent un en-tête `Retry-After` indiquant exactement combien de temps attendre :
```js
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
if (error.response?.status !== 429) return Promise.reject(error);
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= 3) return Promise.reject(error);
config._retryCount += 1;
const retryAfterHeader = error.response.headers["retry-after"];
const waitMs = retryAfterHeader
? parseFloat(retryAfterHeader) * 1000 // l'en-tête est en secondes
: 1000; // par défaut 1 seconde
await new Promise((resolve) => setTimeout(resolve, waitMs));
return api(config);
}
);
```
## Désactiver les nouvelles tentatives pour une requête spécifique
Si certaines requêtes ne doivent jamais être réessayées (ex. des mutations non idempotentes que vous ne voulez pas dupliquer), ajoutez un indicateur à la configuration de la requête :
```js
// Ajoutez ceci dans votre intercepteur avant la logique de nouvelle tentative :
if (config._noRetry) return Promise.reject(error);
// Puis désactivez les nouvelles tentatives pour des appels spécifiques :
await api.post("/payments/charge", body, { _noRetry: true });
```
## Combiner nouvelles tentatives et annulation
Utilisez un `AbortController` pour annuler une requête qui attend un délai de backoff :
```js
const controller = new AbortController();
try {
await api.get("/api/data", { signal: controller.signal });
} catch (error) {
if (axios.isCancel(error)) {
console.log("Request aborted by user");
}
}
// Annuler la requête (et tout délai de nouvelle tentative en attente) depuis un autre endroit :
controller.abort();
```
+145
View File
@@ -0,0 +1,145 @@
# Tests
Tester du code qui effectue des requêtes HTTP avec axios est simple. L'approche recommandée consiste à simuler (mocker) axios lui-même afin que vos tests s'exécutent sans toucher un vrai réseau, vous donnant un contrôle total sur les réponses que reçoit votre code.
## Simulation avec Vitest ou Jest
Vitest et Jest supportent tous deux la simulation de modules avec `vi.mock` / `jest.mock`. Vous pouvez simuler l'ensemble du module axios et contrôler ce que chaque méthode retourne :
```js
// user-service.js
import axios from "axios";
export async function getUser(id) {
const { data } = await axios.get(`/api/users/${id}`);
return data;
}
```
```js
// user-service.test.js
import { describe, it, expect, vi } from "vitest";
import axios from "axios";
import { getUser } from "./user-service";
vi.mock("axios");
describe("getUser", () => {
it("returns user data on success", async () => {
const mockUser = { id: 1, name: "Jay" };
// Faire en sorte que axios.get se résolve avec notre fausse réponse
axios.get.mockResolvedValueOnce({ data: mockUser });
const result = await getUser(1);
expect(result).toEqual(mockUser);
expect(axios.get).toHaveBeenCalledWith("/api/users/1");
});
it("throws when the request fails", async () => {
axios.get.mockRejectedValueOnce(new Error("Network error"));
await expect(getUser(1)).rejects.toThrow("Network error");
});
});
```
## Simuler une AxiosError
Pour tester les chemins de gestion d'erreurs qui inspectent `error.response`, créez directement une instance d'`AxiosError` :
```js
import axios, { AxiosError } from "axios";
import { vi } from "vitest";
const mockError = new AxiosError(
"Not Found",
"ERR_BAD_REQUEST",
{}, // config
{}, // request
{ // response
status: 404,
statusText: "Not Found",
data: { message: "User not found" },
headers: {},
config: {},
}
);
axios.get.mockRejectedValueOnce(mockError);
```
## Utiliser axios-mock-adapter
[axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) est une bibliothèque qui installe un adaptateur personnalisé sur votre instance axios, interceptant les requêtes au niveau de l'adaptateur. Cela signifie que vos intercepteurs continuent de s'exécuter, ce qui la rend plus adaptée aux tests d'intégration.
```bash
npm install --save-dev axios-mock-adapter
```
```js
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
const mock = new MockAdapter(axios);
// Simuler une requête GET
mock.onGet("/api/users/1").reply(200, { id: 1, name: "Jay" });
// Simuler une requête POST
mock.onPost("/api/users").reply(201, { id: 2, name: "New User" });
// Simuler une erreur réseau
mock.onGet("/api/failing").networkError();
// Simuler un délai d'attente dépassé
mock.onGet("/api/slow").timeout();
```
Réinitialisez les simulations entre les tests :
```js
afterEach(() => {
mock.reset(); // effacer tous les gestionnaires enregistrés
});
```
## Tester les intercepteurs
Pour tester les intercepteurs de manière isolée, créez une nouvelle instance axios dans votre test :
```js
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
describe("auth interceptor", () => {
it("attaches a Bearer token to every request", async () => {
const instance = axios.create();
const mock = new MockAdapter(instance);
// Ajoutez votre intercepteur
instance.interceptors.request.use((config) => {
config.headers.set("Authorization", "Bearer test-token");
return config;
});
// Capturez la configuration de la requête en inspectant ce que mock a reçu
let capturedConfig;
mock.onGet("/api/data").reply((config) => {
capturedConfig = config;
return [200, {}];
});
await instance.get("/api/data");
expect(capturedConfig.headers["Authorization"]).toBe("Bearer test-token");
});
});
```
## Conseils
- Simulez toujours au niveau du module (ou utilisez `MockAdapter`) — évitez de simuler des méthodes individuelles sur une instance partagée, car l'état peut fuiter entre les tests.
- Préférez `mockResolvedValueOnce` / `mockRejectedValueOnce` à `mockResolvedValue` pour que les tests soient isolés et ne s'affectent pas mutuellement.
- Pour tester la logique de nouvelle tentative, utilisez `MockAdapter` afin que l'intercepteur testé s'exécute réellement à chaque tentative.
+8
View File
@@ -0,0 +1,8 @@
# TypeScript
`axios` inclut des définitions de types pour TypeScript. Elles sont incluses dans le package npm `axios` via le fichier `index.d.ts`. Comme axios publie à la fois avec un export par défaut ESM et un `module.exports` CJS, il existe quelques nuances à prendre en compte :
- Le paramètre recommandé est d'utiliser `"moduleResolution": "node16"` (impliqué par `"module": "node16"`). Notez que cela nécessite TypeScript 4.7 ou supérieur.
- Si vous utilisez ESM, vos paramètres devraient convenir.
- Si vous compilez TypeScript en CJS et ne pouvez pas utiliser `"moduleResolution": "node16"`, vous devez activer `esModuleInterop`.
- Si vous utilisez TypeScript pour vérifier les types de code JavaScript CJS, votre seule option est d'utiliser `"moduleResolution": "node16"`.
@@ -0,0 +1,78 @@
# Format x-www-form-urlencoded
## URLSearchParams
Par défaut, axios sérialise les objets JavaScript en `JSON`. Pour envoyer des données au format [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) à la place, vous pouvez utiliser l'API [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams), [supportée](http://www.caniuse.com/#feat=urlsearchparams) par la grande majorité des navigateurs, et [Node.js](https://nodejs.org/api/url.html#url_class_urlsearchparams) depuis la version v10 (publiée en 2018).
```js
const params = new URLSearchParams({ foo: 'bar' });
params.append('extraparam', 'value');
axios.post('/foo', params);
```
## Chaîne de requête <Badge type="danger" text="Très ancien" />
Pour les navigateurs plus anciens ou les environnements sans `URLSearchParams`, vous pouvez utiliser la bibliothèque [`qs`](https://github.com/ljharb/qs) pour sérialiser des objets au format `application/x-www-form-urlencoded`.
```js
const qs = require('qs');
axios.post('/foo', qs.stringify({ bar: 123 }));
```
Dans les très anciennes versions de Node.js, vous pouvez utiliser le module natif `querystring` fourni avec Node.js. Notez que ce module a été déprécié dans Node.js v16 — préférez `URLSearchParams` ou `qs` pour le nouveau code.
```js
const querystring = require('querystring');
axios.post('https://something.com/', querystring.stringify({ foo: 'bar' }));
```
## Sérialisation automatique vers URLSearchParams <Badge type="tip" text="Nouveau" />
À partir de la version v0.21.0, axios sérialise automatiquement les objets JavaScript en `URLSearchParams` si l'en-tête `Content-Type` est défini à `application/x-www-form-urlencoded`. Cela signifie que vous pouvez passer directement un objet JavaScript à la propriété `data` de la configuration de requête axios. Par exemple lors de l'envoi de données vers une requête `POST` :
```js
const data = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: 'Peter', surname: 'Griffin' },
{ name: 'Thomas', surname: 'Anderson' },
],
};
await axios.postForm('https://postman-echo.com/post', data, {
headers: { 'content-type': 'application/x-www-form-urlencoded' },
});
```
L'objet `data` sera automatiquement sérialisé en `URLSearchParams` et envoyé au format `application/x-www-form-urlencoded`. Le serveur recevra les données suivantes :
```json
{
"x": "1",
"arr[]": ["1", "2", "3"],
"arr2[0]": "1",
"arr2[1][0]": "2",
"arr2[2]": "3",
"users[0][name]": "Peter",
"users[0][surname]": "Griffin",
"users[1][name]": "Thomas",
"users[1][surname]": "Anderson"
}
```
Si le body-parser de votre backend (comme `body-parser` d'`express.js`) prend en charge le décodage des objets imbriqués, vous obtiendrez automatiquement le même objet côté serveur.
```js
var app = express();
app.use(bodyParser.urlencoded({ extended: true })); // support des corps encodés
app.post('/', function (req, res, next) {
// écho du corps en JSON
res.send(JSON.stringify(req.body));
});
server = app.listen(3000);
```
@@ -0,0 +1,226 @@
# Exemples JavaScript
## Importer la bibliothèque
Pour importer la bibliothèque dans un environnement CommonJS, vous pouvez utiliser la fonction `require`, ou l'instruction `import` si vous utilisez un bundler comme Webpack ou Rollup.
#### Sans bundler
```js
const axios = require("axios");
```
#### Avec bundler (webpack, rollup, vite, etc.)
```js
import axios from "axios";
```
## Utiliser then/catch/finally
Comme axios retourne une Promise en son coeur, vous pouvez choisir d'utiliser des callbacks avec `then`, `catch` et `finally` pour gérer vos données de réponse, les erreurs et la fin de la requête.
### Requête GET
```js
axios
.get("https://jsonplaceholder.typicode.com/posts", {
params: {
postId: 5,
},
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Requête POST
```js
axios
.post("https://jsonplaceholder.typicode.com/posts", {
title: "foo",
body: "bar",
userId: 1,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Requête PUT
```js
axios
.put("https://jsonplaceholder.typicode.com/posts/1", {
title: "foo",
body: "bar",
userId: 1,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Requête PATCH
```js
axios
.patch("https://jsonplaceholder.typicode.com/posts/1", {
title: "foo",
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### Requête DELETE
```js
axios
.delete("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
## Utiliser async/await
Une autre façon de gérer les promises est d'utiliser `async` et `await`. Cela vous permet d'utiliser des blocs try/catch/finally pour gérer les erreurs et la fin de la requête. Cette approche rend votre code plus lisible et plus facile à comprendre, et permet également d'éviter ce qu'on appelle le « callback hell ».
::: tip
Remarque : async/await fait partie d'ECMAScript 2017 et n'est pas supporté par Internet Explorer et les navigateurs plus anciens. À utiliser avec précaution.
:::
### Requête GET
```js
const getPosts = async () => {
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts",
{
params: {
postId: 5,
},
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Requête POST
```js
const createPost = async () => {
try {
const response = await axios.post(
"https://jsonplaceholder.typicode.com/posts",
{
title: "foo",
body: "bar",
userId: 1,
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Requête PUT
```js
const updatePost = async () => {
try {
const response = await axios.put(
"https://jsonplaceholder.typicode.com/posts/1",
{
title: "foo",
body: "bar",
userId: 1,
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Requête PATCH
```js
const updatePost = async () => {
try {
const response = await axios.patch(
"https://jsonplaceholder.typicode.com/posts/1",
{
title: "foo",
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### Requête DELETE
```js
const deletePost = async () => {
try {
const response = await axios.delete(
"https://jsonplaceholder.typicode.com/posts/1"
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
@@ -0,0 +1,139 @@
# Exemple TypeScript
## Importer les types
axios inclut des définitions TypeScript prêtes à l'emploi. Vous pouvez importer les types dont vous avez besoin directement depuis `"axios"` :
```ts
import axios from "axios";
import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
```
## Typer une requête
Utilisez un paramètre de type générique sur la réponse pour indiquer à TypeScript la forme que prendront vos données :
```ts
import axios from "axios";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
const response = await axios.get<Post>("https://jsonplaceholder.typicode.com/posts/1");
console.log(response.data.title); // TypeScript sait que c'est une string
```
## Typer une fonction
Encapsulez les requêtes dans des fonctions avec des types de retour explicites pour une sécurité de type maximale :
```ts
import axios, { AxiosResponse } from "axios";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
const getPost = async (id: number): Promise<Post> => {
const response = await axios.get<Post>(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
return response.data;
};
```
## Typer une requête POST
Vous pouvez typer à la fois le corps de la requête et la réponse attendue :
```ts
type CreatePostBody = {
title: string;
body: string;
userId: number;
};
type CreatePostResponse = CreatePostBody & { id: number };
const createPost = async (data: CreatePostBody): Promise<CreatePostResponse> => {
const response = await axios.post<CreatePostResponse>(
"https://jsonplaceholder.typicode.com/posts",
data
);
return response.data;
};
```
## Instance axios typée
Créez une instance typée afin d'y intégrer votre URL de base et vos en-têtes :
```ts
import axios from "axios";
import type { AxiosInstance } from "axios";
const api: AxiosInstance = axios.create({
baseURL: "https://api.example.com",
timeout: 5000,
});
```
## Intercepteurs typés
Utilisez `InternalAxiosRequestConfig` (et non `AxiosRequestConfig`) pour les intercepteurs de requête dans v1.x :
```ts
import axios from "axios";
import type { InternalAxiosRequestConfig, AxiosResponse } from "axios";
api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
config.headers.set("Authorization", `Bearer ${getToken()}`);
return config;
});
api.interceptors.response.use(
(response: AxiosResponse) => response,
(error) => Promise.reject(error)
);
```
## Typer les erreurs
Utilisez `axios.isAxiosError()` pour affiner le type d'une erreur capturée :
```ts
import axios, { AxiosError } from "axios";
type ApiError = {
message: string;
code: number;
};
try {
await axios.get("/api/protected-resource");
} catch (error) {
if (axios.isAxiosError<ApiError>(error)) {
// error.response?.data est typé comme ApiError
console.error(error.response?.data.message);
console.error(error.response?.status);
} else {
throw error;
}
}
```
## Notes sur la configuration TypeScript
Comme axios publie à la fois des versions ESM et CJS, il existe quelques nuances selon votre configuration :
- Le paramètre recommandé est `"moduleResolution": "node16"` (impliqué par `"module": "node16"`). Cela nécessite TypeScript 4.7 ou supérieur.
- Si vous compilez TypeScript vers CJS et ne pouvez pas utiliser `"moduleResolution": "node16"`, activez `"esModuleInterop": true`.
- Si vous utilisez TypeScript pour vérifier les types de code JavaScript CJS, votre seule option est `"moduleResolution": "node16"`.
+42
View File
@@ -0,0 +1,42 @@
# Fonctionnalités
axios est un client HTTP puissant qui propose une API simple et facile à utiliser pour effectuer des requêtes HTTP. Il prend en charge tous les navigateurs modernes et est largement utilisé dans la communauté JavaScript. Voici quelques-unes des fonctionnalités qui font d'axios un excellent choix pour votre prochain projet.
## Isomorphique
axios est un client HTTP universel qui peut être utilisé aussi bien dans le navigateur que dans Node.js. Cela signifie que vous pouvez utiliser axios pour effectuer des requêtes API depuis votre code frontend aussi bien que depuis votre code backend. Cela fait d'axios un excellent choix pour développer des applications web progressives, des applications monopages et des applications avec rendu côté serveur.
axios est également un excellent choix pour les équipes qui travaillent à la fois sur le frontend et le backend. En utilisant axios pour les deux, vous disposez d'une API cohérente pour effectuer des requêtes HTTP, ce qui peut contribuer à réduire la complexité de votre code.
## Support Fetch <Badge type="tip" text="Nouveau" />
axios offre une prise en charge de premier plan de l'API Fetch, qui est un remplacement moderne de l'API XHR. L'adaptateur est optionnel et peut être activé via la configuration. La même API est maintenue pour les adaptateurs XHR et Fetch, ce qui facilite l'adoption de l'API Fetch dans votre code sans modifier votre code existant.
## Support des navigateurs
axios prend en charge tous les navigateurs modernes et certains navigateurs plus anciens, notamment Chrome, Firefox, Safari et Edge. axios est un excellent choix pour développer des applications web devant prendre en charge un large éventail de navigateurs.
## Support de Node.js
axios supporte également un large éventail de versions de Node.js, avec une compatibilité testée jusqu'à la version v12.x, ce qui en fait un bon choix dans les environnements où la mise à jour vers la dernière version de Node.js n'est pas possible ou pratique.
En plus de Node.js, axios dispose de tests de fumée pour Bun et Deno qui valident les comportements clés de l'exécution et renforcent la confiance dans la compatibilité multi-environnements.
## Fonctionnalités supplémentaires
- Support de l'API Promise
- Interception des requêtes et des réponses
- Transformation des données de requête et de réponse
- Abort controller
- Délais d'attente (timeouts)
- Sérialisation des paramètres de requête avec support des entrées imbriquées
- Sérialisation automatique du corps de la requête vers :
- JSON (application/json)
- Multipart / FormData (multipart/form-data)
- Formulaire encodé en URL (application/x-www-form-urlencoded)
- Envoi de formulaires HTML en JSON
- Gestion automatique des données JSON dans la réponse
- Capture de la progression pour les navigateurs et Node.js avec des informations supplémentaires (vitesse de transfert, temps restant)
- Limitation de la bande passante pour Node.js
- Compatible avec les implémentations conformes de FormData et Blob (y compris Node.js)
- Protection côté client contre les attaques XSRF
@@ -0,0 +1,73 @@
# Premiers pas
Bienvenue dans la documentation d'axios ! Ce guide vous aidera à démarrer avec axios et à effectuer votre première requête API. Si vous débutez avec axios, nous vous recommandons de commencer ici.
## Installation
Vous pouvez utiliser axios dans votre projet de plusieurs façons. La méthode la plus courante consiste à l'installer depuis npm et à l'inclure dans votre projet. Nous supportons également jsDelivr, unpkg, et d'autres options.
#### Avec npm
```bash
npm install axios
```
#### Avec pnpm
```bash
pnpm install axios
```
#### Avec yarn
```bash
yarn add axios
```
#### Avec bun
```bash
bun add axios
```
#### Avec deno
```bash
deno install npm:axios
```
#### Avec jsDelivr
Lors de l'utilisation de jsDelivr, nous recommandons d'utiliser la version minifiée ainsi que d'épingler le numéro de version afin d'éviter des changements inattendus. Si vous souhaitez utiliser la dernière version, vous pouvez le faire en omettant le numéro de version. Ceci est fortement déconseillé en production car cela peut entraîner des modifications inattendues dans votre application.
```html
<script src="https://cdn.jsdelivr.net/npm/axios@<x.x.x>/dist/axios.min.js"></script>
```
#### Avec unpkg
Lors de l'utilisation d'unpkg, nous recommandons d'utiliser la version minifiée ainsi que d'épingler le numéro de version afin d'éviter des changements inattendus. Si vous souhaitez utiliser la dernière version, vous pouvez le faire en omettant le numéro de version. Ceci est fortement déconseillé en production car cela peut entraîner des modifications inattendues dans votre application.
```html
<script src="https://unpkg.com/axios@<x.x.x>/dist/axios.min.js"></script>
```
## Votre première requête
Une requête axios peut être effectuée en seulement deux lignes de code. Envoyer votre première requête avec axios est très simple. Vous pouvez interroger n'importe quelle API en fournissant l'URL et la méthode. Par exemple, pour effectuer une requête GET vers l'API JSONPlaceholder, vous pouvez utiliser le code suivant :
```js
import axios from "axios";
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts/1"
);
console.log(response.data);
```
axios propose une API simple pour effectuer des requêtes. Vous pouvez utiliser la méthode `axios.get` pour une requête GET, la méthode `axios.post` pour une requête POST, et ainsi de suite. Vous pouvez également utiliser la méthode `axios.request` pour effectuer une requête avec n'importe quelle méthode HTTP.
## Prochaines étapes
Maintenant que vous avez effectué votre première requête avec axios, vous êtes prêt à explorer le reste de la documentation. Vous pouvez en apprendre davantage sur l'envoi de requêtes, la gestion des réponses et l'utilisation d'axios dans vos projets. Consultez le reste de la documentation pour en savoir plus.
@@ -0,0 +1,92 @@
# Guide de migration
Ce guide a pour but de vous aider à migrer votre projet d'une version du framework à une autre. Il est recommandé de lire les notes de version de chaque version majeure que vous migrez, car elles peuvent contenir des informations importantes sur les changements incompatibles.
## Migration de v0.x vers v1.x
### Modification de l'instruction d'importation
Dans v1.x, l'instruction d'importation a été modifiée pour utiliser l'export `default`. Vous devrez donc mettre à jour vos instructions d'importation en conséquence.
```diff
- import { axios } from "axios";
+ import axios from "axios";
```
### Modifications du système d'intercepteurs
Dans v1.x, vous devez utiliser le type `InternalAxiosRequestConfig` pour typer le paramètre `config` dans l'intercepteur de `request`. En effet, le paramètre `config` est désormais typé comme `InternalAxiosRequestConfig` au lieu du type public `AxiosRequestConfig`.
```diff
- axios.interceptors.request.use((config: AxiosRequestConfig) => {
+ axios.interceptors.request.use((config: InternalAxiosRequestConfig) => {
return config;
});
```
### Modifications de la structure des en-têtes de requête
Dans v1.x, la structure des en-têtes de requête a été modifiée pour supprimer la propriété `common`. Vous devrez donc mettre à jour votre code pour utiliser la nouvelle structure des en-têtes de requête comme suit :
```diff
- if (request.headers?.common?.Authorization) {
- request.headers.common.Authorization = ...
+ if (request.headers?.Authorization) {
+ request.headers.Authorization = ...
```
Les en-têtes par défaut qui se trouvaient précédemment sous `common`, `get`, `post`, etc. sont désormais définis directement sur `axios.defaults.headers` :
```diff
- axios.defaults.headers.common["Accept"] = "application/json";
+ axios.defaults.headers["Accept"] = "application/json";
```
### Données multipart/form-data
Si une requête inclut un payload `FormData`, l'en-tête `Content-Type: multipart/form-data` est désormais défini automatiquement. Supprimez tout en-tête manuel pour éviter les doublons :
```diff
- axios.post("/upload", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
+ axios.post("/upload", formData);
```
Si vous définissez explicitement `Content-Type: application/json`, axios sérialisera désormais automatiquement les données en JSON.
### Sérialisation des paramètres
v1.x a introduit plusieurs changements incompatibles dans la façon dont les paramètres d'URL sont sérialisés. Les plus importants :
**Les `params` sont désormais encodés en pourcentage par défaut.** Si votre backend attendait des crochets bruts issus de l'encodage de style qs, vous devrez peut-être configurer un sérialiseur personnalisé :
```js
import qs from 'qs';
axios.create({
paramsSerializer: {
serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' }),
},
});
```
**Les objets imbriqués dans `params` sont désormais sérialisés avec la notation entre crochets** (`foo[bar]=1`) plutôt que la notation pointée. Si votre backend attendait la notation pointée, utilisez un sérialiseur personnalisé.
**Les paramètres `null` et `undefined`** sont désormais gérés de manière cohérente : les valeurs `null` sont sérialisées comme des chaînes vides, tandis que les valeurs `undefined` sont entièrement omises.
Pour les options complètes de configuration de la sérialisation des paramètres, consultez la page [Configuration de requête](/pages/advanced/request-config).
### Les éléments internes ne sont plus exportés
Nous avons décidé de ne plus exporter les éléments internes d'axios. Vous devrez donc mettre à jour votre code pour n'utiliser que l'API publique d'axios. Cette modification a été apportée pour simplifier l'API et réduire la surface exposée d'axios, nous permettant ainsi d'effectuer des modifications internes sans les déclarer comme des changements incompatibles.
Veuillez consulter la [référence API](/pages/advanced/api-reference) sur ce site pour obtenir les dernières informations sur l'API publique d'axios.
### Configuration de requête
Nous avons apporté des modifications à l'objet de configuration de requête. Veuillez consulter la [référence de configuration](/pages/advanced/request-config) sur ce site pour obtenir les dernières informations.
### Changements incompatibles non répertoriés
Ce guide n'est pas exhaustif et peut ne pas couvrir tous les changements incompatibles. Si vous rencontrez un problème, veuillez ouvrir un ticket sur le [dépôt GitHub de la documentation](https://github.com/axios/docs) avec le label `breaking change`.
+24
View File
@@ -0,0 +1,24 @@
# Politique de sécurité
## Signaler une vulnérabilité
Si vous pensez avoir trouvé une vulnérabilité de sécurité dans le projet, veuillez nous la signaler comme décrit ci-dessous. Nous prenons toutes les vulnérabilités de sécurité au sérieux. Si vous avez trouvé une vulnérabilité dans une bibliothèque tierce, veuillez la signaler aux mainteneurs de cette bibliothèque.
## Processus de signalement
Veuillez ne pas signaler les vulnérabilités de sécurité via des issues GitHub publiques. Veuillez utiliser le canal de sécurité officiel sur GitHub en créant un [avis de sécurité](https://github.com/axios/axios/security).
## Politique de divulgation
Lorsque nous recevons un rapport de vulnérabilité de sécurité, nous lui assignons un responsable principal. Cette personne est responsable du rapport de vulnérabilité. Le responsable confirmera le problème et déterminera les versions affectées. Il évaluera ensuite le problème et déterminera la gravité du problème. Le responsable développera un correctif pour le problème et préparera une version. Le responsable informera le rapporteur lorsque le correctif sera prêt à être annoncé.
## Mises à jour de sécurité
Les mises à jour de sécurité seront publiées dès que possible après que le correctif a été développé et testé. Nous informerons les utilisateurs de la version via le dépôt GitHub du projet. Nous publierons également les notes de version et les avis de sécurité sur la page des versions GitHub du projet. Nous déprécierons également toutes les versions contenant la vulnérabilité de sécurité.
## Partenaires de sécurité et remerciements
Nous tenons à remercier les chercheurs en sécurité suivants pour leur collaboration afin de contribuer à la sécurité du projet pour tous :
- [Socket Dev](https://socket.dev/)
- [GitHub Security Lab](https://securitylab.github.com/)
+44
View File
@@ -0,0 +1,44 @@
# Versionnage sémantique
Le versionnage sémantique est un schéma de versionnage utilisé pour communiquer la nature des changements dans un package logiciel. C'est un ensemble simple de règles et d'exigences qui dictent comment les numéros de version sont attribués et incrémentés.
## Versionnage d'axios
axios suit le schéma de versionnage sémantique. Cela signifie que chaque version d'axios se voit attribuer un numéro de version composé de trois parties : majeure, mineure et correctif. Le numéro de version est incrémenté en fonction de la nature des changements apportés dans la version.
Dans le passé, axios n'a pas toujours strictement suivi le versionnage sémantique, mais à l'avenir, une adhérence beaucoup plus stricte au schéma de versionnage sémantique sera maintenue pour garantir que les utilisateurs peuvent se fier aux numéros de version pour communiquer la nature des changements dans la bibliothèque.
Un bref aperçu du schéma de versionnage est fourni ci-dessous.
## Format de version
Un numéro de version sémantique est composé de trois parties :
1. Version majeure
2. Version mineure
3. Version de correctif
Le numéro de version est écrit sous la forme `MAJEURE.MINEURE.CORRECTIF`. Chaque partie du numéro de version a une signification spécifique :
- **Version majeure** : Incrémentée lorsque vous effectuez des changements d'API incompatibles.
- **Version mineure** : Incrémentée lorsque vous ajoutez des fonctionnalités de manière rétrocompatible.
- **Version de correctif** : Incrémentée lorsque vous effectuez des corrections de bugs rétrocompatibles.
## Versions de pré-publication
En plus des trois parties du numéro de version, vous pouvez ajouter une version de pré-publication. Cela se fait en ajoutant un tiret et une série d'identifiants séparés par des points immédiatement après la version de correctif. Par exemple, `1.0.0-alpha.1`.
Les versions de pré-publication sont utilisées pour indiquer qu'une version est instable et peut ne pas satisfaire les exigences de compatibilité prévues telles qu'indiquées par le numéro de version. Les versions de pré-publication sont ordonnées en fonction de l'ordre des identifiants. Par exemple, `1.0.0-alpha.1` vient avant `1.0.0-alpha.2`.
## Plages de versions
Lorsque vous spécifiez une plage de versions pour un package, vous pouvez utiliser une variété d'opérateurs pour spécifier la plage de versions acceptables. Les opérateurs suivants sont disponibles :
- `>` : Supérieur à
- `<` : Inférieur à
- `>=` : Supérieur ou égal à
- `<=` : Inférieur ou égal à
- `~` : Approximativement égal à
- `^` : Compatible avec
Par exemple, `^1.0.0` signifie que toute version supérieure ou égale à `1.0.0` et inférieure à `2.0.0` est acceptable.
+185
View File
@@ -0,0 +1,185 @@
---
layout: page
---
<script setup>
import allSponsors from '../../../data/sponsors.json';
const sponsors = [...allSponsors.platinum, ...allSponsors.gold, ...allSponsors.silver, ...allSponsors.bronze, ...allSponsors.backer];
const capitalizeFirstLetter = (word) => {
return String(word).charAt(0).toUpperCase() + String(word).slice(1);
};
</script>
<div style="margin: 1rem 7rem; max-width: 1200px;">
<h1 style="line-height: 64px; font-size: 32px; letter-spacing: -0.4px; font-weight: 600; margin-top: 2rem;">Sponsors</h1>
<p>Axios est soutenu par les organisations suivantes. Si vous souhaitez sponsoriser Axios, consultez notre <a href="https://opencollective.com/axios" target="_blank" style="color: #007bff;">page Open Collective</a> pour plus d'informations.</p>
<div :class="$style.sponsorCloudWrapper">
<div :class="$style.sponsorCloudContainer">
<div :class="$style.sponsorCloudGrid">
<div :class="$style.sponsorCloudImageWrapper" v-for="(sponsor, key) in sponsors" :key="sponsor.name">
<img :src="sponsor.imageUrl" :alt="sponsor.name" style="max-height: 72px; width: 100%; object-fit: contain;" />
<dl>
<dd :class="$style.sponsorTag">
<span :class="$style[`tagSponsor${capitalizeFirstLetter(sponsor.tier)}`]">{{ capitalizeFirstLetter(sponsor.tier) }}</span>
</dd>
</dl>
<a :href="sponsor.website" rel="noopener noreferrer" target="_blank" :class="$style.sponsorName">{{ sponsor.name }}</a>
</div>
</div>
</div>
</div>
</div>
<style module>
.sponsorCloudWrapper {
margin-top: 2rem;
margin-bottom: 2rem;
}
.sponsorCloudContainer {
max-width: 80rem;
}
.sponsorCloudGrid {
display: grid;
overflow: hidden;
margin-left: -1.5rem;
margin-right: -1.5rem;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.125rem;
}
.sponsorCloudImageWrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem;
background-color: rgb(156 163 175 / 0.05);
}
.sponsorTag {
margin-top: 0.75rem;
margin-inline-start: 0px;
}
.sponsorName {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 3rem;
margin-top: 1rem !important;
font-size: 0.875rem !important;
line-height: 1.25rem !important;
font-weight: 600 !important;
color: var(--vp-c-text-1) !important;
text-wrap-style: pretty;
display: -webkit-box;
text-align: center;
}
.tagSponsorPlatinum {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #000;
background-color: #E5E7EB;
}
.tagSponsorGold {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #F59E0B;
}
.tagSponsorSilver {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #9CA3AF;
}
.tagSponsorBronze {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #854D0E;
}
.tagSponsorBacker {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #2563EB;
}
@media (min-width: 640px) {
.sponsorCloudGrid {
margin-left: 0;
margin-right: 0;
border-radius: 1rem;
}
.sponsorCloudImageWrapper {
padding: 2.5rem;
}
}
@media (min-width: 768px) {
.sponsorCloudGrid {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
</style>
+329
View File
@@ -0,0 +1,329 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: 'axios 文档'
text: 'axios 是一个基于 Promise 的简单 HTTP 客户端,适用于浏览器和 Node.js'
image:
dark: /logo.svg
light: /logo-light.svg
alt: axios
actions:
- theme: brand
text: 快速开始
link: /zh/pages/getting-started/first-steps
- theme: alt
text: API 参考
link: /zh/pages/advanced/api-reference
features:
- title: 简单易用
details: axios 上手极为简单,一行代码即可完成初始化。最基本的 API 请求仅需 2 行代码。
- title: 强大的拦截器
details: 创新的拦截器系统让您可以完全掌控请求和响应的生命周期,支持修改请求、响应及错误。
- title: TypeScript 支持
details: axios 提供完整的类型声明,全面支持 TypeScript,让您可以在 TypeScript 项目中放心使用。
---
<script setup>
import Splide from '@splidejs/splide';
import { onMounted } from 'vue';
import allSponsors from '../data/sponsors.json';
onMounted(() => {
new Splide(
'.splide',
{
type: 'loop',
autoplay: true,
interval: 3000,
perPage: 5,
perMove: 1,
gap: 10,
snap: true,
pagination: false,
breakpoints: {
1200: {
perPage: 4,
},
960: {
perPage: 3,
},
640: {
perPage: 2,
},
480: {
perPage: 1,
},
},
}
).mount();
});
const activePlatinumSponsors = allSponsors.platinum.filter((sponsor) => sponsor.active);
const activeGoldSponsors = allSponsors.gold.filter((sponsor) => sponsor.active);
const activeSilverSponsors = allSponsors.silver.filter((sponsor) => sponsor.active);
const sponsors = [...activePlatinumSponsors, ...activeGoldSponsors, ...activeSilverSponsors];
const capitalizeFirstLetter = (word) => {
return String(word).charAt(0).toUpperCase() + String(word).slice(1);
};
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css">
<div style="margin: 0 auto; max-width: 1200px;">
<h3 style="line-height: 64px;font-size: 28px;letter-spacing: -0.4px;font-weight: 600;margin-top: 2rem;">赞助商</h3>
</div>
<div v-if="sponsors.length > 0" :class="$style.container" class="splide">
<div class="splide__track">
<div role="list" class="splide__list">
<div v-for="(sponsor, key) in sponsors" :key="sponsor.name" :class="$style.cardWrapper" :style="key === 0 ? 'margin-left: 0.5rem' : key === sponsors.length - 1 ? 'margin-right: 0.5rem' : ''" class="splide__slide">
<div :class="$style.imgWrapper">
<img :class="$style.img" :src="sponsor.imageUrl" alt="" />
</div>
<div style="padding-left: 0.5rem; padding-right: 0.5rem; height: 100%;">
<p :class="$style.heading">{{ sponsor.name }}</p>
<dl :class="$style.cardDl">
<dd style="margin-top: 0.75rem; margin-inline-start: 0px;">
<span :class="$style[`tagSponsor${capitalizeFirstLetter(sponsor.tier)}`]">{{ capitalizeFirstLetter(sponsor.tier) }}</span>
</dd>
</dl>
</div>
<div>
<div :class="$style.linksWrapper">
<div :class="$style.link">
<a :href="sponsor.website" :class="$style.rightLink" target="_blank">
<div :class="$style.linkIcon">
<svg data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="m20.893 13.393-1.135-1.135a2.252 2.252 0 0 1-.421-.585l-1.08-2.16a.414.414 0 0 0-.663-.107.827.827 0 0 1-.812.21l-1.273-.363a.89.89 0 0 0-.738 1.595l.587.39c.59.395.674 1.23.172 1.732l-.2.2c-.212.212-.33.498-.33.796v.41c0 .409-.11.809-.32 1.158l-1.315 2.191a2.11 2.11 0 0 1-1.81 1.025 1.055 1.055 0 0 1-1.055-1.055v-1.172c0-.92-.56-1.747-1.414-2.089l-.655-.261a2.25 2.25 0 0 1-1.383-2.46l.007-.042a2.25 2.25 0 0 1 .29-.787l.09-.15a2.25 2.25 0 0 1 2.37-1.048l1.178.236a1.125 1.125 0 0 0 1.302-.795l.208-.73a1.125 1.125 0 0 0-.578-1.315l-.665-.332-.091.091a2.25 2.25 0 0 1-1.591.659h-.18c-.249 0-.487.1-.662.274a.931.931 0 0 1-1.458-1.137l1.411-2.353a2.25 2.25 0 0 0 .286-.76m11.928 9.869A9 9 0 0 0 8.965 3.525m11.928 9.868A9 9 0 1 1 8.965 3.525"></path>
</svg>
</div>
</a>
</div>
<div v-if="sponsor.twitter" :class="$style.link" style="margin-left: -1px;">
<a :href="sponsor.twitter" :class="$style.leftLink" target="_blank">
<div :class="$style.linkIcon">
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" fill="currentColor" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 462.799"><path fill-rule="nonzero" d="M403.229 0h78.506L310.219 196.04 512 462.799H354.002L230.261 301.007 88.669 462.799h-78.56l183.455-209.683L0 0h161.999l111.856 147.88L403.229 0zm-27.556 415.805h43.505L138.363 44.527h-46.68l283.99 371.278z"/></svg>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style module>
.container {
display: flex;
margin: 0 auto;
max-width: 1200px;
}
.cardWrapper {
display: flex;
flex-direction: column;
grid-column: span 1 / span 1;
border-radius: 0.5rem;
border: 1px solid var(--vp-c-gutter) !important;
text-align: center;
background-color: var(--card-background-color) !important;
width: 100%;
max-width: 11.5rem;
scroll-snap-align: center;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
flex-shrink: 0 !important;
margin-bottom: 0.5rem !important;
margin-top: 0.5rem !important;
margin-left: auto;
margin-right: auto;
}
.imgWrapper {
display: flex;
padding: 1.75rem;
padding-bottom: 0.75rem;
flex-direction: column;
flex: 1 1 0%;
align-items: center;
justify-content: center;
}
.img {
width: 8rem;
height: 8rem;
}
.heading {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 3rem;
margin-top: 1rem !important;
font-size: 1rem !important;
line-height: 1.5rem !important;
font-weight: 600 !important;
color: var(--vp-c-text-1) !important;
text-wrap-style: pretty;
display: -webkit-box;
}
.cardDl {
display: flex;
margin-top: 0.25rem;
flex-direction: column;
flex-grow: 1;
justify-content: space-between;
}
.tagSponsorPlatinum {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #000;
background-color: #E5E7EB;
}
.tagSponsorGold {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #F59E0B;
}
.tagSponsorSilver {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #9CA3AF;
}
.tagSponsorBronze {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #854D0E;
}
.tagSponsorBacker {
display: inline-flex;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
align-items: center;
border-radius: 9999px;
box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
--tw-ring-inset: inset;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
color: #FFF;
background-color: #2563EB;
}
.linksWrapper {
display: flex;
margin-top: -1px;
}
.link {
display: flex;
flex: 1 1 0%;
width: 0;
}
.rightLink {
display: inline-flex;
position: relative;
padding-top: 1rem;
padding-bottom: 1rem;
margin-right: -1px;
flex: 1 1 0%;
column-gap: 0.75rem;
justify-content: center;
align-items: center;
border-bottom-left-radius: 0.5rem;
border-top: 1px;
border-right: 1px;
border-left: 0px;
border-bottom: 0px;
border-style: solid;
border-color: var(--vp-c-gutter);
width: 0;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #111827;
}
.leftLink {
display: inline-flex;
position: relative;
padding-top: 1rem;
padding-bottom: 1rem;
flex: 1 1 0%;
column-gap: 0.75rem;
justify-content: center;
align-items: center;
border-bottom-right-radius: 0.5rem;
border-top: 1px;
border-left: 0px;
border-bottom: 0px;
border-right: 0px;
border-style: solid;
border-color: var(--vp-c-gutter);
width: 0;
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 600;
color: #111827;
}
.linkIcon {
width: 1.25rem;
height: 1.25rem;
color: #9CA3AF;
}
</style>
+88
View File
@@ -0,0 +1,88 @@
# 适配器
适配器允许你自定义 axios 处理请求数据的方式。默认情况下,axios 使用 `['xhr', 'http', 'fetch']` 的有序优先级列表,并选择当前环境支持的第一个适配器。实际上,这意味着在浏览器中使用 `xhr`,在 Node.js 中使用 `http`,在两者均不可用的环境(如 Cloudflare Workers 或 Deno)中使用 `fetch`
编写自定义适配器可以让你完全掌控 axios 如何发起请求和处理响应,适用于测试、自定义传输或非标准环境等场景。
## 内置适配器
可以通过 `adapter` 配置选项按名称选择内置适配器:
```js
// 使用 fetch 适配器
const instance = axios.create({ adapter: "fetch" });
// 使用 XHR 适配器(浏览器默认)
const instance = axios.create({ adapter: "xhr" });
// 使用 HTTP 适配器(Node.js 默认)
const instance = axios.create({ adapter: "http" });
```
你也可以传入一个适配器名称数组,axios 将使用当前环境支持的第一个:
```js
const instance = axios.create({ adapter: ["fetch", "xhr", "http"] });
```
关于 `fetch` 适配器的更多详情,请参阅 [Fetch 适配器](/pages/advanced/fetch-adapter)页面。
## 创建自定义适配器
要创建自定义适配器,需要编写一个接受 `config` 对象并返回 Promise 的函数,该 Promise 需解析为有效的 axios 响应对象。
```js
import axios from "axios";
import { settle } from "axios/unsafe/core/settle.js";
function myAdapter(config) {
/**
* 到此时:
* - config 已与默认配置合并
* - 请求转换器已执行
* - 请求拦截器已执行
*
* 适配器现在负责发起请求
* 并返回有效的响应对象。
*/
return new Promise((resolve, reject) => {
// 在此执行自定义请求逻辑。
// 本示例以原生 fetch API 为起点。
fetch(config.url, {
method: config.method?.toUpperCase() ?? "GET",
headers: config.headers?.toJSON() ?? {},
body: config.data,
signal: config.signal,
})
.then(async (fetchResponse) => {
const responseData = await fetchResponse.text();
const response = {
data: responseData,
status: fetchResponse.status,
statusText: fetchResponse.statusText,
headers: Object.fromEntries(fetchResponse.headers.entries()),
config,
request: null,
};
// settle 根据 HTTP 状态码决定是 resolve 还是 reject
settle(resolve, reject, response);
/**
* 到此后:
* - 响应转换器将执行
* - 响应拦截器将执行
*/
})
.catch(reject);
});
}
const instance = axios.create({ adapter: myAdapter });
```
::: tip
`settle` 辅助函数对 2xx 状态码 resolve Promise,对其他状态码 reject Promise,与 axios 的默认行为一致。如果需要自定义状态码验证,请改用 `validateStatus` 配置选项。
:::
+331
View File
@@ -0,0 +1,331 @@
# API 参考
以下是 axios 包中所有可用函数和类的列表。这些函数可在你的项目中使用和导入。所有函数和类均受我们遵循语义化版本的承诺保护,即在未发布主版本变更的情况下,这些 API 将保持稳定不变。
## 实例
`axios` 实例是你用于发起 HTTP 请求的主要对象,它是一个创建 `Axios` 类新实例的工厂函数。`axios` 实例提供了多个请求方法,详见文档的[请求别名](/pages/advanced/request-method-aliases)章节。
## 类
### `Axios`
`Axios` 类是发起 HTTP 请求的核心类,是一个创建 `Axios` 类新实例的工厂函数。该类提供多个 HTTP 请求方法,详见文档的[请求别名](/pages/advanced/request-method-aliases)章节。
#### `constructor`
创建一个新的 `Axios` 实例,构造函数接受一个可选的配置对象作为参数。
```ts
constructor(instanceConfig?: AxiosRequestConfig);
```
#### `request`
处理请求调用和响应解析,是发起 HTTP 请求的核心方法。接受一个配置对象作为参数,返回一个解析为响应对象的 Promise。
```ts
request(configOrUrl: string | AxiosRequestConfig<D>, config: AxiosRequestConfig<D>): Promise<AxiosResponse<T>>;
```
### `CancelToken` <Badge type="danger" text="已废弃,请改用 AbortController" />
`CancelToken` 类基于 `tc39/proposal-cancelable-promises` 提案,用于创建可取消 HTTP 请求的令牌。该类现已废弃,推荐使用 `AbortController` API。
从 0.22.0 版本起,`CancelToken` 类已废弃,将在未来版本中移除。建议改用 `AbortController` API。
该类主要为了向后兼容而保留导出,未来将被移除。我们强烈不建议在新项目中使用,因此不再对其 API 进行文档说明。
## 函数
### `AxiosError`
`AxiosError` 类是 HTTP 请求失败时抛出的错误类,继承自 `Error` 类并添加了额外属性。
#### `constructor`
创建一个新的 `AxiosError` 实例,构造函数接受可选的 message、code、config、request 和 response 作为参数。
```ts
constructor(message?: string, code?: string, config?: InternalAxiosRequestConfig<D>, request?: any, response?: AxiosResponse<T, D>);
```
#### `properties`
`AxiosError` 类提供以下属性:
```ts
// 配置实例。
config?: InternalAxiosRequestConfig<D>;
// 错误代码。
code?: string;
// 请求实例。
request?: any;
// 响应实例。
response?: AxiosResponse<T, D>;
// 表示该错误是否为 AxiosError 的布尔值。
isAxiosError: boolean;
// 错误状态码。
status?: number;
// 将错误转换为 JSON 对象的辅助方法。
toJSON: () => object;
// 错误原因。
cause?: Error;
```
### `AxiosHeaders`
`AxiosHeaders` 类是用于管理 HTTP 请求头的工具类,提供添加、删除和获取请求头等操作方法。
此处仅列出主要方法,完整方法列表请参阅类型声明文件。
#### `constructor`
创建一个新的 `AxiosHeaders` 实例,构造函数接受一个可选的请求头对象作为参数。
```ts
constructor(headers?: RawAxiosHeaders | AxiosHeaders | string);
```
#### `set`
向请求头对象添加一个请求头。
```ts
set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders;
set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;
```
#### `get`
从请求头对象获取一个请求头。
```ts
get(headerName: string, parser: RegExp): RegExpExecArray | null;
get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;
```
#### `has`
检查请求头对象中是否存在某个请求头。
```ts
has(header: string, matcher?: AxiosHeaderMatcher): boolean;
```
#### `delete`
从请求头对象移除一个请求头。
```ts
delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;
```
#### `clear`
从请求头对象移除所有请求头。
```ts
clear(matcher?: AxiosHeaderMatcher): boolean;
```
#### `normalize`
规范化请求头对象。
```ts
normalize(format: boolean): AxiosHeaders;
```
#### `concat`
合并多个请求头对象。
```ts
concat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;
```
#### `toJSON`
将请求头对象转换为 JSON 对象。
```ts
toJSON(asStrings?: boolean): RawAxiosHeaders;
```
### `CanceledError` <Badge type="tip" text="继承自 AxiosError" />
`CanceledError` 类是 HTTP 请求被取消时抛出的错误类,继承自 `AxiosError` 类。
### `Cancel` <Badge type="tip" text="CanceledError 的别名" />
`Cancel` 类是 `CanceledError` 类的别名,为向后兼容而保留导出,将在未来版本中移除。
### `isCancel`
检查某个错误是否为 `CanceledError` 的函数,可用于区分主动取消和意外错误。
```ts
isCancel(value: any): boolean;
```
```js
import axios from "axios";
const controller = new AbortController();
axios.get("/api/data", { signal: controller.signal }).catch((error) => {
if (axios.isCancel(error)) {
console.log("Request was cancelled:", error.message);
} else {
console.error("Unexpected error:", error);
}
});
controller.abort("User navigated away");
```
### `isAxiosError`
检查某个错误是否为 `AxiosError` 的函数。在 `catch` 块中使用此函数,可安全访问 axios 特有的错误属性,如 `error.response``error.config`
```ts
isAxiosError(value: any): value is AxiosError;
```
```js
import axios from "axios";
try {
await axios.get("/api/resource");
} catch (error) {
if (axios.isAxiosError(error)) {
// error.response、error.config、error.code 均可使用
console.error("HTTP error", error.response?.status, error.message);
} else {
// 非 axios 错误(例如编程错误)
throw error;
}
}
```
### `all` <Badge type="danger" text="已废弃,请改用 Promise.all" />
`all` 函数接受一组 Promise 并返回一个在所有 Promise 都完成后才完成的单一 Promise,现已废弃,推荐使用 `Promise.all` 方法。
从 0.22.0 版本起,`all` 函数已废弃,将在未来版本中移除。建议改用 `Promise.all` 方法。
### `spread`
`spread` 函数可将一个参数数组展开为函数调用的多个参数,在你需要将数组参数传递给接收多个参数的函数时非常实用。
```ts
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
```
### `toFormData`
将普通 JavaScript 对象(包括嵌套对象)转换为 `FormData` 实例,在需要从对象中以编程方式构建 multipart 表单数据时非常实用。
```ts
toFormData(sourceObj: object, formData?: FormData, options?: FormSerializerOptions): FormData;
```
```js
import { toFormData } from "axios";
const data = { name: "Jay", avatar: fileBlob };
const form = toFormData(data);
// form 现在是一个可直接发送的 FormData 实例
await axios.post("/api/users", form);
```
### `formToJSON`
`FormData` 实例转换回普通 JavaScript 对象,在需要以结构化格式读取表单数据时非常实用。
```ts
formToJSON(form: FormData): object;
```
```js
import { formToJSON } from "axios";
const form = new FormData();
form.append("name", "Jay");
form.append("role", "admin");
const obj = formToJSON(form);
console.log(obj); // { name: "Jay", role: "admin" }
```
### `getAdapter`
通过名称或名称数组解析并返回一个适配器函数。axios 在内部使用此函数为当前环境选择最合适的适配器。
```ts
getAdapter(adapters: string | string[]): AxiosAdapter;
```
```js
import { getAdapter } from "axios";
// 显式获取 fetch 适配器
const fetchAdapter = getAdapter("fetch");
// 按优先级列表获取最合适的适配器
const adapter = getAdapter(["fetch", "xhr", "http"]);
```
### `mergeConfig`
合并两个 axios 配置对象,使用与 axios 内部合并默认配置和请求级选项相同的深度合并策略。后者的值优先级更高。
```ts
mergeConfig<T>(config1: AxiosRequestConfig<T>, config2: AxiosRequestConfig<T>): AxiosRequestConfig<T>;
```
```js
import { mergeConfig } from "axios";
const base = { baseURL: "https://api.example.com", timeout: 5000 };
const override = { timeout: 10000, headers: { "X-Custom": "value" } };
const merged = mergeConfig(base, override);
// { baseURL: "https://api.example.com", timeout: 10000, headers: { "X-Custom": "value" } }
```
## 常量
### `HttpStatusCode`
包含 HTTP 状态码命名常量的对象,可用于编写更具可读性的条件判断,避免直接使用数字字面量。
```js
import axios, { HttpStatusCode } from "axios";
try {
const response = await axios.get("/api/resource");
} catch (error) {
if (axios.isAxiosError(error)) {
if (error.response?.status === HttpStatusCode.NotFound) {
console.error("Resource not found");
} else if (error.response?.status === HttpStatusCode.Unauthorized) {
console.error("Authentication required");
}
}
}
```
## 其他
### `VERSION`
`axios` 包的当前版本号字符串,随每次发布更新。
+142
View File
@@ -0,0 +1,142 @@
# 认证
大多数 API 都需要某种形式的认证。本页介绍在 axios 请求中附加凭据的最常见模式。
## Bearer 令牌(JWT
最常见的方式是在 `Authorization` 请求头中附加 JWT。最简洁的做法是通过 axios 实例上的请求拦截器实现,这样令牌会在每次请求时实时读取:
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
api.interceptors.request.use((config) => {
const token = localStorage.getItem("access_token");
if (token) {
config.headers.set("Authorization", `Bearer ${token}`);
}
return config;
});
```
## HTTP Basic 认证
对于使用 HTTP Basic 认证的 API,传入 `auth` 选项即可。axios 会自动对凭据进行编码并设置 `Authorization` 请求头:
```js
const response = await axios.get("https://api.example.com/data", {
auth: {
username: "myUser",
password: "myPassword",
},
});
```
::: tip
对于 Bearer 令牌和 API 密钥,请使用自定义 `Authorization` 请求头,而非 `auth` 选项——`auth` 仅适用于 HTTP Basic 认证。
:::
## API 密钥
API 密钥通常作为请求头或查询参数传递,具体取决于 API 的要求:
```js
// 作为请求头
const api = axios.create({
baseURL: "https://api.example.com",
headers: { "X-API-Key": "your-api-key-here" },
});
// 作为查询参数
const response = await axios.get("https://api.example.com/data", {
params: { apiKey: "your-api-key-here" },
});
```
## 令牌刷新
当访问令牌过期时,你需要静默刷新它并重新发送失败的请求。响应拦截器是实现此逻辑的合适位置:
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
// 跟踪是否已有刷新正在进行,以避免并行发起多个刷新请求
let isRefreshing = false;
let failedQueue = [];
const processQueue = (error, token = null) => {
failedQueue.forEach((prom) => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});
failedQueue = [];
};
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
if (isRefreshing) {
// 将请求加入队列,等待刷新完成
return new Promise((resolve, reject) => {
failedQueue.push({ resolve, reject });
})
.then((token) => {
originalRequest.headers["Authorization"] = `Bearer ${token}`;
return api(originalRequest);
})
.catch((err) => Promise.reject(err));
}
originalRequest._retry = true;
isRefreshing = true;
try {
const { data } = await axios.post("/auth/refresh", {
refreshToken: localStorage.getItem("refresh_token"),
});
const newToken = data.access_token;
localStorage.setItem("access_token", newToken);
api.defaults.headers.common["Authorization"] = `Bearer ${newToken}`;
processQueue(null, newToken);
return api(originalRequest);
} catch (refreshError) {
processQueue(refreshError, null);
// 跳转到登录页或触发事件
localStorage.removeItem("access_token");
window.location.href = "/login";
return Promise.reject(refreshError);
} finally {
isRefreshing = false;
}
}
return Promise.reject(error);
}
);
```
## 基于 Cookie 的认证
对于依赖 Cookie 的会话 API,设置 `withCredentials: true` 以在跨域请求中携带 Cookie
```js
const api = axios.create({
baseURL: "https://api.example.com",
withCredentials: true, // 每次请求均携带 Cookie
});
```
::: warning
`withCredentials: true` 要求服务器响应时携带 `Access-Control-Allow-Credentials: true`,且 `Access-Control-Allow-Origin` 必须为具体域名(不能是通配符)。
:::
+70
View File
@@ -0,0 +1,70 @@
# 取消请求
从 v0.22.0 起,axios 支持使用 AbortController 以简洁的方式取消请求。该功能在浏览器和 Node.js(使用支持 AbortController 的 axios 版本)中均可使用。要取消请求,需要创建一个 `AbortController` 实例,并将其 `signal` 传入请求的 `signal` 选项。
```js
const controller = new AbortController();
axios
.get("/foo/bar", {
signal: controller.signal,
})
.then(function (response) {
//...
});
// 取消请求
controller.abort();
```
## CancelToken <Badge type="danger" text="已废弃" />
你也可以使用 `CancelToken` API 来取消请求。该 API 已废弃,将在下一个主版本中移除,建议改用 `AbortController`。可以使用 `CancelToken.source` 工厂方法创建取消令牌,如下所示:
```js
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios
.get("/user/12345", {
cancelToken: source.token,
})
.catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log("Request canceled", thrown.message);
} else {
// 处理错误
}
});
axios.post(
"/user/12345",
{
name: "new name",
},
{
cancelToken: source.token,
}
);
// 取消请求(message 参数可选)
source.cancel("Operation canceled by the user.");
```
也可以通过向 `CancelToken` 构造函数传入执行函数来创建取消令牌:
```js
const CancelToken = axios.CancelToken;
let cancel;
axios.get("/user/12345", {
cancelToken: new CancelToken(function executor(c) {
// 执行函数接收一个 cancel 函数作为参数
cancel = c;
}),
});
// 取消请求
cancel();
```
你可以使用同一个取消令牌或 AbortController 取消多个请求。如果在 axios 请求开始时取消令牌已处于已取消状态,则请求会立即被取消,不会尝试发起实际的网络请求。
+48
View File
@@ -0,0 +1,48 @@
# 配置默认值
axios 允许你指定应用于每个请求的配置默认值,包括 `baseURL``headers``timeout` 等属性。下面是使用配置默认值的示例:
```js
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/posts";
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN;
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
```
## 自定义实例默认值
axios 实例在创建时会有自己的默认配置,这些默认配置可以通过修改实例的 `defaults` 属性来覆盖。下面是使用自定义实例默认值的示例:
```js
var instance = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/posts",
timeout: 1000,
headers: { Authorization: "foobar" },
});
instance.defaults.headers.common["Authorization"] = AUTH_TOKEN;
```
## 配置优先级
配置将按照优先级顺序合并,依次为:库的默认值、实例的默认属性,最后是请求时传入的配置参数。下面通过示例说明优先级顺序。
首先,创建一个使用库提供的默认值的实例。此时 timeout 配置值为 `0`,这是库的默认值。
```js
const instance = axios.create();
```
接下来,将实例的 timeout 默认值覆盖为 `2500` 毫秒。此后,使用该实例的所有请求都将在 2.5 秒后超时。
```js
instance.defaults.timeout = 2500;
```
最后,发起一个 timeout 为 `5000` 毫秒的请求,该请求将在 5 秒后超时。
```js
instance.get("/longRequest", {
timeout: 5000,
});
```
@@ -0,0 +1,87 @@
# 创建实例
`axios.create()` 允许你创建一个预配置的 axios 实例。该实例与默认 `axios` 对象拥有相同的请求和响应 API,但会将你提供的配置作为每次请求的基础配置。对于任何超过单文件规模的应用,这是使用 axios 的推荐方式。
```ts
import axios from "axios";
const instance = axios.create({
baseURL: "https://api.example.com",
timeout: 5000,
headers: { "X-Custom-Header": "foobar" },
});
```
`create` 方法接受完整的[请求配置](/pages/advanced/request-config)对象。之后可以像使用默认 axios 对象一样使用该实例:
```js
const response = await instance.get("/users/1");
```
## 为什么要使用实例?
### 按服务设置 baseURL
在大多数应用中,你需要与多个 API 通信。为每个服务创建独立的实例,可以避免在每次调用时重复指定 baseURL:
```js
const githubApi = axios.create({ baseURL: "https://api.github.com" });
const internalApi = axios.create({ baseURL: "https://api.internal.example.com" });
const { data: repos } = await githubApi.get("/users/axios/repos");
const { data: users } = await internalApi.get("/users");
```
### 共享认证请求头
在一个实例上附加认证令牌,让该实例的所有请求自动携带,而不影响其他实例:
```js
const authApi = axios.create({
baseURL: "https://api.example.com",
headers: {
Authorization: `Bearer ${getToken()}`,
},
});
```
### 按服务设置超时与重试
不同服务有不同的可靠性特征。可以为实时服务设置较短的超时,为批处理任务设置较长的超时:
```js
const realtimeApi = axios.create({ baseURL: "https://realtime.example.com", timeout: 2000 });
const batchApi = axios.create({ baseURL: "https://batch.example.com", timeout: 60000 });
```
### 隔离的拦截器
添加到实例上的拦截器只对该实例生效,有助于保持关注点分离:
```js
const loggingApi = axios.create({ baseURL: "https://api.example.com" });
loggingApi.interceptors.request.use((config) => {
console.log(`${config.method?.toUpperCase()} ${config.url}`);
return config;
});
```
## 按请求覆盖默认配置
在请求时传入的配置始终会覆盖实例默认配置:
```js
const api = axios.create({ timeout: 5000 });
// 这个特定请求使用 30 秒超时
await api.get("/slow-endpoint", { timeout: 30000 });
```
::: tip
实例默认配置也可以在创建后通过修改 `instance.defaults` 来更改:
```js
instance.defaults.headers.common["Authorization"] = `Bearer ${newToken}`;
```
:::
+70
View File
@@ -0,0 +1,70 @@
# 错误处理
axios 可能会抛出多种不同类型的错误,有些来自 axios 本身,有些来自服务器或客户端。下表列出了所抛出错误的基本结构:
| 属性 | 说明 |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| message | 错误信息的简要摘要,以及失败时的状态码。 |
| name | 定义错误的来源,对于 axios 来说始终是 `AxiosError`。 |
| stack | 提供错误的堆栈跟踪。 |
| config | 包含用户在发起请求时定义的特定实例配置的 axios 配置对象。 |
| code | 表示 axios 内部识别的错误,下表列出了 axios 内部错误的具体说明。 |
| status | HTTP 响应状态码。常见 HTTP 响应状态码的含义请参阅[此处](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)。 |
以下是 axios 内部可能出现的错误列表:
| 错误代码 | 说明 |
| ------------------------- | --------------------------------------------------------------------------------------- |
| ERR_BAD_OPTION_VALUE | axios 配置中提供了无效或不支持的值。 |
| ERR_BAD_OPTION | axios 配置中提供了无效选项。 |
| ECONNABORTED | 通常表示请求已超时(除非设置了 `transitional.clarifyTimeoutError`)或被浏览器或其插件中止。 |
| ETIMEDOUT | 请求因超过 axios 默认时限而超时。必须将 `transitional.clarifyTimeoutError` 设置为 `true`,否则会抛出通用的 `ECONNABORTED` 错误。 |
| ERR_NETWORK | 网络相关问题。在浏览器中,此错误也可能由 [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) 或[混合内容](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content)策略违规引起。出于安全考虑,浏览器不允许 JS 代码获知错误的真实原因,请检查控制台。 |
| ERR_FR_TOO_MANY_REDIRECTS | 请求重定向次数过多,超过了 axios 配置中指定的最大重定向次数。 |
| ERR_DEPRECATED | 使用了 axios 中已废弃的功能或方法。 |
| ERR_BAD_RESPONSE | 响应无法正确解析或格式异常,通常与 `5xx` 状态码的响应有关。 |
| ERR_BAD_REQUEST | 请求格式异常或缺少必要参数,通常与 `4xx` 状态码的响应有关。 |
| ERR_CANCELED | 功能或方法被用户通过 AbortSignal(或 CancelToken)显式取消。 |
| ERR_NOT_SUPPORT | 当前 axios 环境不支持该功能或方法。 |
| ERR_INVALID_URL | axios 请求提供了无效的 URL。 |
## 处理错误
axios 的默认行为是在请求失败时 reject Promise。不过,你也可以捕获错误并按需处理。以下是捕获错误的示例:
```js
axios.get("/user/12345").catch(function (error) {
if (error.response) {
// 请求已发出,服务器返回了不在 2xx 范围内的状态码
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// 请求已发出,但未收到响应
// `error.request` 在浏览器中是 XMLHttpRequest 实例,在 node.js 中是 http.ClientRequest 实例
console.log(error.request);
} else {
// 在设置请求时触发了错误
console.log("Error", error.message);
}
console.log(error.config);
});
```
使用 `validateStatus` 配置选项,可以覆盖默认条件(`status >= 200 && status < 300`),自定义应当抛出错误的 HTTP 状态码。
```js
axios.get("/user/12345", {
validateStatus: function (status) {
return status < 500; // 仅在状态码小于 500 时 resolve
},
});
```
使用 `toJSON` 方法,可以获取包含更多错误信息的对象。
```js
axios.get("/user/12345").catch(function (error) {
console.log(error.toJSON());
});
```
+81
View File
@@ -0,0 +1,81 @@
# Fetch 适配器 <Badge type="tip" text="新特性" />
`fetch` 适配器是我们在 1.7.0 版本中引入的新适配器,使 axios 能够使用 `fetch` API,兼顾两者的优势。默认情况下,当构建中 `xhr``http` 适配器不可用,或当前环境不支持时,会使用 `fetch`。若要将其作为默认适配器,必须在创建 axios 实例时通过 `adapter` 选项显式指定。
```js
import axios from 'axios';
const instance = axios.create({
adapter: 'fetch',
});
```
该适配器支持与 `xhr` 适配器相同的功能,包括上传和下载进度捕获,还支持额外的响应类型,如 `stream``formdata`(如果环境支持)。
## 自定义 fetch <Badge type="tip" text="v1.12.0+" />
`v1.12.0` 起,你可以自定义 fetch 适配器,使用自定义的 `fetch` 函数代替环境全局的 `fetch`。可以通过 `env` 配置选项传入自定义的 `fetch` 函数、`Request``Response` 构造函数。这在使用提供了自己 `fetch` 实现的自定义环境或应用框架时非常实用。
::: info
使用自定义 `fetch` 函数时,可能还需要提供匹配的 `Request``Response` 构造函数。如果省略,将使用全局构造函数。如果你的自定义 `fetch` 与全局构造函数不兼容,可以传入 `null` 来禁用它们。
**注意:**`Request``Response` 设置为 `null` 后,fetch 适配器将无法捕获上传和下载进度。
:::
### 基本示例
```js
import customFetchFunction from 'customFetchModule';
const instance = axios.create({
adapter: 'fetch',
onDownloadProgress(e) {
console.log('downloadProgress', e);
},
env: {
fetch: customFetchFunction,
Request: null, // null -> 禁用该构造函数
Response: null,
},
});
```
### 与 Tauri 一起使用
[Tauri](https://tauri.app/plugin/http-client/) 提供了一个平台 `fetch` 函数,可绕过浏览器对原生层请求的 CORS 限制。以下示例展示了在 Tauri 应用中使用该自定义 fetch 配置 axios 的最简设置。
```js
import { fetch } from '@tauri-apps/plugin-http';
import axios from 'axios';
const instance = axios.create({
adapter: 'fetch',
onDownloadProgress(e) {
console.log('downloadProgress', e);
},
env: {
fetch,
},
});
const { data } = await instance.get('https://google.com');
```
### 与 SvelteKit 一起使用
[SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) 为服务端 `load` 函数提供了自定义的 `fetch` 实现,用于处理 Cookie 转发和相对 URL。由于其 `fetch` 与标准 `URL` API 不兼容,必须明确配置 axios 使用它,并禁用全局 `Request``Response` 构造函数。
```js
export async function load({ fetch }) {
const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', {
adapter: 'fetch',
env: {
fetch,
Request: null,
Response: null,
},
});
return { post };
}
```
+99
View File
@@ -0,0 +1,99 @@
# 文件上传
axios 让文件上传变得简单。需要 `multipart/form-data` 上传时,使用 `postForm``FormData` 即可。
## 单文件上传(浏览器)
直接将 `File` 对象作为字段值传入——axios 会自动检测并使用正确的内容类型:
```js
await axios.postForm("https://httpbin.org/post", {
description: "My profile photo",
file: document.querySelector("#fileInput").files[0],
});
```
## 多文件上传(浏览器)
传入 `FileList` 可一次性上传所有选中的文件,所有文件将使用相同的字段名(`files[]`)发送:
```js
await axios.postForm(
"https://httpbin.org/post",
document.querySelector("#fileInput").files
);
```
如需为每个文件使用不同的字段名,请手动构建 `FormData` 对象:
```js
const formData = new FormData();
formData.append("avatar", avatarFile);
formData.append("cover", coverFile);
await axios.post("https://httpbin.org/post", formData);
```
## 跟踪上传进度(浏览器)
使用 `onUploadProgress` 回调向用户显示进度条或百分比:
```js
await axios.postForm("https://httpbin.org/post", {
file: document.querySelector("#fileInput").files[0],
}, {
onUploadProgress: (progressEvent) => {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`Upload progress: ${percent}%`);
},
});
```
进度事件对象上可用的完整字段列表,请参阅[进度捕获](/pages/advanced/progress-capturing)。
## Node.js 中的文件上传
在 Node.js 中,使用 `fs.createReadStream` 上传文件系统中的文件,无需将整个文件加载到内存:
```js
import fs from "fs";
import FormData from "form-data";
import axios from "axios";
const form = new FormData();
form.append("file", fs.createReadStream("/path/to/file.jpg"));
form.append("description", "My uploaded file");
await axios.post("https://httpbin.org/post", form);
```
::: tip
在 Node.js 环境中创建 `FormData` 对象需要 `form-data` npm 包。在现代 Node.jsv18+)中,全局 `FormData` 已原生可用。
:::
## 上传 BufferNode.js
也可以直接上传内存中的 `Buffer`
```js
const buffer = Buffer.from("Hello, world!");
const form = new FormData();
form.append("file", buffer, {
filename: "hello.txt",
contentType: "text/plain",
knownLength: buffer.length,
});
await axios.post("https://httpbin.org/post", form);
```
::: warning
Node.js 环境目前不支持捕获 `FormData` 上传进度。
:::
::: danger
在 Node.js 中上传可读流时,请设置 `maxRedirects: 0`,以防止 `follow-redirects` 包将整个流缓冲到内存中。
:::
+188
View File
@@ -0,0 +1,188 @@
# 请求头方法 <Badge type="tip" text="新特性" />
随着新 `AxiosHeaders` 类的引入,axios 提供了一组操作请求头的方法,比直接操作请求头对象更加方便。
## 构造函数 `new AxiosHeaders(headers?)`
`AxiosHeaders` 类的构造函数接受一个可选的请求头对象来初始化实例,对象可以包含任意数量的请求头,且键名不区分大小写。
```js
constructor(headers?: RawAxiosHeaders | AxiosHeaders | string);
```
为方便起见,你可以传入一个以换行符分隔的请求头字符串,它们会被解析并添加到实例中。
```js
const headers = new AxiosHeaders(`
Host: www.bing.com
User-Agent: curl/7.54.0
Accept: */*`);
console.log(headers);
// Object [AxiosHeaders] {
// host: 'www.bing.com',
// 'user-agent': 'curl/7.54.0',
// accept: '*/*'
// }
```
## Set
`set` 方法用于在 `AxiosHeaders` 实例上设置请求头,可以传入单个请求头名称和值、包含多个请求头的对象,或以换行符分隔的请求头字符串。该方法还接受一个可选的 `rewrite` 参数,用于控制设置请求头时的覆盖行为。
```js
set(headerName, value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher);
set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string) => boolean);
set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean);
```
`rewrite` 参数控制覆盖行为:
- `false` - 如果请求头的值已设置(不为 undefined),则不覆盖
- `undefined`(默认)- 覆盖请求头,除非其值被设置为 false
- `true` - 始终覆盖
该参数也可以接受一个用户自定义函数,用于决定是否应覆盖该值,函数接收当前值、请求头名称和请求头对象作为参数。
`AxiosHeaders` 会保留第一个匹配键的大小写形式。你可以利用这一特性,先以 `undefined` 值预设一个键名,之后再设置值,从而保留特定的请求头大小写。详见[保留特定请求头大小写](/pages/advanced/headers#preserving-a-specific-header-case)。
## Get
`get` 方法用于获取请求头的值,可以传入单个请求头名称、可选的匹配器或解析器。匹配器默认为 `true`,解析器可以是用于从请求头中提取值的正则表达式。
```js
get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;
get(headerName: string, parser: RegExp): RegExpExecArray | null;
```
以下是 `get` 方法的一些使用示例:
```js
const headers = new AxiosHeaders({
'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h',
});
console.log(headers.get('Content-Type'));
// multipart/form-data; boundary=Asrf456BGe4h
console.log(headers.get('Content-Type', true)); // 解析以 \s,;= 为分隔符的键值对字符串:
// [Object: null prototype] {
// 'multipart/form-data': undefined,
// boundary: 'Asrf456BGe4h'
// }
console.log(
headers.get('Content-Type', (value, name, headers) => {
return String(value).replace(/a/g, 'ZZZ');
})
);
// multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h
console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]);
// boundary=Asrf456BGe4h
```
## Has
`has` 方法用于检查 `AxiosHeaders` 实例中是否存在某个请求头,可以传入单个请求头名称和可选的匹配器。
```js
has(header: string, matcher?: AxiosHeaderMatcher): boolean;
```
::: info
如果请求头已设置(值不为 undefined),则返回 true。
:::
## Delete
`delete` 方法用于从 `AxiosHeaders` 实例中删除某个请求头,可以传入单个请求头名称和可选的匹配器。
```js
delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;
```
::: info
如果至少有一个请求头被移除,则返回 true。
:::
## Clear
`clear` 方法用于在不传入任何参数时删除 `AxiosHeaders` 实例中的所有请求头。如果传入匹配器,则只移除与匹配器匹配的请求头,此时匹配器用于匹配请求头名称而非值。
```js
clear(matcher?: AxiosHeaderMatcher): boolean;
```
::: info
如果至少有一个请求头被清除,则返回 true。
:::
## Normalize
如果直接修改了请求头对象,可能导致相同名称但大小写不同的重复项。此方法通过将重复键合并为一个来规范化请求头对象。axios 在每个拦截器调用后内部使用此方法。将 format 设置为 true 可将请求头名称转换为首字母大写的格式(cOntEnt-type => Content-Type),设置为 false 则保留原始格式。
```js
const headers = new AxiosHeaders({
foo: '1',
});
headers.Foo = '2';
headers.FOO = '3';
console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' }
console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' }
console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' }
```
::: info
返回 `this` 以支持链式调用。
:::
## Concat
将实例与目标对象合并到一个新的 AxiosHeaders 实例中。如果目标是字符串,它将被解析为原始 HTTP 请求头;如果目标是 AxiosHeaders 实例,它将与当前实例合并。
这对于组合请求头时的大小写预设非常有用,例如:
```js
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
```
```js
concat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;
```
::: info
返回一个新的 AxiosHeaders 实例。
:::
## toJSON
将所有内部请求头值解析到一个新的 null 原型对象中。将 `asStrings` 设置为 true 可将数组解析为以逗号分隔的字符串。
```js
toJSON(asStrings?: boolean): RawAxiosHeaders;
```
## From
从传入的原始请求头创建并返回一个新的 `AxiosHeaders` 实例;如果传入的已经是 `AxiosHeaders` 实例,则直接返回该实例。
```js
from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;
```
## 快捷方法
以下快捷方法可供使用:
- `setContentType``getContentType``hasContentType`
- `setContentLength``getContentLength``hasContentLength`
- `setAccept``getAccept``hasAccept`
- `setUserAgent``getUserAgent``hasUserAgent`
- `setContentEncoding``getContentEncoding``hasContentEncoding`
+153
View File
@@ -0,0 +1,153 @@
# 请求头 <Badge type="tip" text="新特性" />
axios 暴露了自己的 AxiosHeaders 类,通过类 Map 的 API 来操作请求头,保证键名不区分大小写。axios 内部使用该类管理请求头,同时也将其暴露给用户以提供便利。尽管 HTTP 请求头本身不区分大小写,axios 仍会保留原始请求头的大小写形式,以满足风格需求,并在服务器错误地将请求头大小写视为有效区分时提供兼容。直接操作请求头对象的旧方式仍然可用,但已废弃,不建议在新代码中使用。
## 使用请求头
AxiosHeaders 对象实例可以包含不同类型的内部值,用于控制设置和合并逻辑。axios 在将最终请求头对象发送前会调用 `toJSON` 方法。AxiosHeaders 对象也是可迭代的,可以在循环中使用,或转换为数组或对象。
请求头值可以是以下类型之一:
- `string` - 正常的字符串值,将被发送到服务器
- `null` - 转换为 JSON 时跳过该请求头
- `false` - 转换为 JSON 时跳过该请求头,并额外表示调用 `set` 方法时必须将 `rewrite` 选项设置为 true 才能覆盖此值(axios 内部使用此机制允许用户选择不安装某些请求头,如 User-Agent 或 Content-Type
- `undefined` - 值未设置
::: warning
如果请求头值不是 undefined,则视为已设置。
:::
请求头对象始终在拦截器和转换器中初始化,如以下示例所示:
```js
axios.interceptors.request.use((request: InternalAxiosRequestConfig) => {
request.headers.set("My-header", "value");
request.headers.set({
"My-set-header1": "my-set-value1",
"My-set-header2": "my-set-value2",
});
// 禁止 axios 后续设置此请求头
request.headers.set("User-Agent", false);
request.headers.setContentType("text/plain");
// 直接访问的方式已废弃
request.headers["My-set-header2"] = "newValue";
return request;
});
```
你可以使用任何可迭代方法遍历 AxiosHeaders,如 for-of 循环、forEach 或展开运算符:
```js
const headers = new AxiosHeaders({
foo: '1',
bar: '2',
baz: '3',
});
for (const [header, value] of headers) {
console.log(header, value);
}
// foo 1
// bar 2
// baz 3
```
## 在请求中设置请求头
最常见的设置请求头的方式是在请求配置或实例配置的 `headers` 选项中设置:
```js
// 针对单个请求
await axios.get('/api/data', {
headers: {
'Accept-Language': 'en-US',
'X-Request-ID': 'abc123',
},
});
// 针对实例(应用于每个请求)
const api = axios.create({
headers: {
'X-App-Version': '2.0.0',
},
});
```
## 保留特定请求头大小写
axios 请求头名称不区分大小写,但 `AxiosHeaders` 会保留第一个匹配键的大小写形式。如果你需要为大小写敏感的非标准服务器保留特定大小写,可以在 `defaults` 中预设键名,之后再按常规方式设置值。
```js
const api = axios.create();
api.defaults.headers.common = {
'content-type': undefined,
accept: undefined,
};
await api.put(url, data, {
headers: {
'Content-Type': 'application/octet-stream',
Accept: 'application/json',
},
});
```
也可以在组合请求头时直接使用 `AxiosHeaders` 实现:
```js
import axios, { AxiosHeaders } from 'axios';
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
await axios.put(url, data, { headers });
```
## 在拦截器中设置请求头
拦截器是附加动态请求头(如认证令牌)的合适位置,因为令牌可能在实例首次创建时还不可用:
```js
api.interceptors.request.use((config) => {
const token = getAuthToken(); // 在请求时读取
config.headers.set('Authorization', `Bearer ${token}`);
return config;
});
```
## 读取响应头
响应头以 `AxiosHeaders` 实例的形式在 `response.headers` 上可用,所有头名称均为小写:
```js
const response = await axios.get('/api/data');
console.log(response.headers['content-type']);
// application/json; charset=utf-8
console.log(response.headers.get('x-request-id'));
// abc123
```
## 移除默认请求头
如需取消 axios 默认设置的请求头(如 `Content-Type``User-Agent`),将其值设置为 `false`
```js
await axios.post('/api/data', payload, {
headers: {
'Content-Type': false, // 让浏览器自动设置(例如针对 FormData)
},
});
```
关于完整 `AxiosHeaders` 方法 API 的详细说明,请参阅[请求头方法](/pages/advanced/header-methods)页面。
@@ -0,0 +1,57 @@
# HTML 表单提交(浏览器) <Badge type="tip" text="新特性" />
你也可以直接从 HTML 表单元素提交数据,无需任何额外的 JavaScript 代码即可提交页面中的表单。
```js
await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm'));
```
`FormData``HTMLForm` 对象也可以通过显式将 `Content-Type` 请求头设置为 `application/json` 来以 `JSON` 格式发送:
```js
await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), {
headers: {
'Content-Type': 'application/json',
},
});
```
以下是一个有效的、可被上述代码提交的表单示例:
```html
<form id="htmlForm">
<input type="text" name="foo" value="1" />
<input type="text" name="deep.prop" value="2" />
<input type="text" name="deep prop spaced" value="3" />
<input type="text" name="baz" value="4" />
<input type="text" name="baz" value="5" />
<select name="user.age">
<option value="value1">Value 1</option>
<option value="value2" selected>Value 2</option>
<option value="value3">Value 3</option>
</select>
<input type="submit" value="Save" />
</form>
```
上述表单将以如下格式提交:
```json
{
"foo": "1",
"deep": {
"prop": "2",
"prop spaced": "3"
},
"baz": ["4", "5"],
"user": {
"age": "value2"
}
}
```
::: warning
目前不支持将 Blob/File 以 JSONbase64)格式发送。
:::
+72
View File
@@ -0,0 +1,72 @@
# HTTP2 <Badge type="warning" text="实验性" /> <Badge type="tip" text="v1.13.0+" />
`1.13.0` 版本中,`http` 适配器新增了实验性的 HTTP/2 支持,仅在 Node.js 环境中可用。
## 基本用法
使用 `httpVersion` 选项来选择请求使用的协议版本,将其设置为 `2` 可启用 HTTP/2。
```js
const { data, headers, status } = await axios.post(
"https://httpbin.org/post",
form,
{
httpVersion: 2,
},
);
```
## `http2Options`
可以通过 `http2Options` 配置对象传入内部 `session.request()` 调用的原生额外选项,其中还包括自定义的 `sessionTimeout` 参数,用于控制空闲 HTTP/2 会话在关闭前保持存活的时间(毫秒),默认值为 `1000ms`
```js
{
httpVersion: 2,
http2Options: {
rejectUnauthorized: false, // 接受自签名证书(仅用于开发环境)
sessionTimeout: 5000, // 空闲会话保持 5 秒
},
}
```
::: warning
HTTP/2 支持目前仍为实验性功能,API 可能在未来的次要版本或补丁版本中发生变化。
:::
## 完整示例
以下示例通过 HTTP/2 发送 `multipart/form-data` POST 请求,并同时跟踪上传和下载进度。
```js
const form = new FormData();
form.append("foo", "123");
const { data, headers, status } = await axios.post(
"https://httpbin.org/post",
form,
{
httpVersion: 2,
http2Options: {
// rejectUnauthorized: false,
// sessionTimeout: 1000
},
onUploadProgress(e) {
console.log("upload progress", e);
},
onDownloadProgress(e) {
console.log("download progress", e);
},
responseType: "arraybuffer",
},
);
```
## 配置参考
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| `httpVersion` | `number` | `1` | 使用的 HTTP 协议版本,设置为 `2` 可启用 HTTP/2。 |
| `http2Options.sessionTimeout` | `number` | `1000` | 空闲 HTTP/2 会话关闭前等待的时间(毫秒)。 |
Node.js 内置 `http2` 模块支持的其他原生 `session.request()` 选项也可以通过 `http2Options` 传入。
+116
View File
@@ -0,0 +1,116 @@
# 拦截器
拦截器是一种强大的机制,可用于拦截和修改 HTTP 请求与响应,与 Express.js 中的中间件非常相似。拦截器是在请求发送前和响应接收前执行的函数,适用于日志记录、修改请求头、修改响应等多种场景。
拦截器的基本用法如下:
```js
// 添加请求拦截器
axios.interceptors.request.use(
function (config) {
// 在请求发送之前执行某些操作
return config;
},
function (error) {
// 处理请求错误
return Promise.reject(error);
}
);
// 添加响应拦截器
axios.interceptors.response.use(
function (response) {
// 状态码在 2xx 范围内的响应会触发此函数
// 处理响应数据
return response;
},
function (error) {
// 状态码不在 2xx 范围内的响应会触发此函数
// 处理响应错误
return Promise.reject(error);
}
);
```
## 移除拦截器
可以通过对要移除的拦截器调用 `eject` 方法来移除特定拦截器。也可以通过在 `axios.interceptors` 对象上调用 `clear` 方法来移除所有拦截器。以下是移除拦截器的示例:
```js
// 移除请求拦截器
const myInterceptor = axios.interceptors.request.use(function () {
/*...*/
});
axios.interceptors.request.eject(myInterceptor);
// 移除响应拦截器
const myInterceptor = axios.interceptors.response.use(function () {
/*...*/
});
axios.interceptors.response.eject(myInterceptor);
```
以下是移除所有拦截器的示例:
```js
const instance = axios.create();
instance.interceptors.request.use(function () {
/*...*/
});
instance.interceptors.request.clear(); // 移除所有请求拦截器
instance.interceptors.response.use(function () {
/*...*/
});
instance.interceptors.response.clear(); // 移除所有响应拦截器
```
## 拦截器的默认行为
添加请求拦截器时,默认被视为异步执行。当主线程被阻塞时(拦截器底层会创建一个 Promise,你的请求会被放到调用栈底部),这可能导致 axios 请求的执行出现延迟。如果你的请求拦截器是同步的,可以在选项对象中添加一个标志,告知 axios 同步运行该代码,从而避免请求执行的延迟。
```js
axios.interceptors.request.use(
function (config) {
config.headers.test = "I am only a header!";
return config;
},
null,
{ synchronous: true }
);
```
## 使用 `runWhen` 的拦截器
如果你希望根据运行时条件决定是否执行某个拦截器,可以在选项对象中添加 `runWhen` 函数。仅当 `runWhen` 返回 `false` 时,拦截器不会执行。该函数会以 config 对象作为参数调用(你也可以为其绑定自定义参数)。这对于只需在特定时机运行的异步请求拦截器非常实用。
```js
function onGetCall(config) {
return config.method === "get";
}
axios.interceptors.request.use(
function (config) {
config.headers.test = "special get headers";
return config;
},
null,
{ runWhen: onGetCall }
);
```
## 多个拦截器
你可以在同一个请求或响应上添加多个拦截器,同一拦截器链中的多个拦截器遵循以下规则:
- 每个拦截器都会执行
- 请求拦截器按照后进先出(LIFO)的顺序执行
- 响应拦截器按照添加顺序(FIFO)执行
- 只返回最后一个拦截器的结果
- 每个拦截器接收其前驱拦截器的结果
- 当成功回调中的拦截器抛出错误时
- 后续的成功回调拦截器不会被调用
- 后续的错误回调拦截器会被调用
- 一旦被捕获,后续的成功回调拦截器将再次被调用(与 Promise 链的行为一致)
::: tip
要深入了解拦截器的工作原理,可以查阅[这里](https://github.com/axios/axios/blob/v1.x/test/specs/interceptors.spec.js)的测试用例。
:::
@@ -0,0 +1,120 @@
# multipart/form-data 格式
axios 支持以 `multipart/form-data` 格式发送请求,这种格式常用于文件上传。要以该格式发送请求,需要创建一个 `FormData` 对象并向其追加数据,然后将 `FormData` 对象传入 axios 请求配置的 `data` 属性。
```js
const formData = new FormData();
formData.append("foo", "bar");
axios.post("https://httpbin.org/post", formData);
```
在 Node.js 中,可以使用 `form-data` 库,如下所示:
```js
const FormData = require("form-data");
const form = new FormData();
form.append("my_field", "my value");
form.append("my_buffer", Buffer.alloc(10));
form.append("my_file", fs.createReadStream("/foo/bar.jpg"));
axios.post("https://example.com", form);
```
## 自动序列化为 FormData <Badge type="tip" text="新特性" />
从 v0.27.0 起,如果请求的 Content-Type 请求头设置为 `multipart/form-data`,axios 支持自动将对象序列化为 FormData 对象。这意味着你可以直接将 JavaScript 对象传入 axios 请求配置的 `data` 属性。例如,向 POST 请求传递数据时:
```js
import axios from "axios";
axios
.post(
"https://httpbin.org/post",
{ x: 1 },
{
headers: {
"Content-Type": "multipart/form-data",
},
}
)
.then(({ data }) => console.log(data));
```
在 Node.js 构建中,默认使用 ([`form-data`](https://github.com/form-data/form-data)) 作为 polyfill。你可以通过设置 `env.FormData` 配置变量来覆盖 FormData 类,但大多数情况下不需要这样做:
```js
const axios = require("axios");
var FormData = require("form-data");
axios
.post(
"https://httpbin.org/post",
{ x: 1, buf: Buffer.alloc(10) },
{
headers: {
"Content-Type": "multipart/form-data",
},
}
)
.then(({ data }) => console.log(data));
```
## 支持的特殊结尾
axios FormData 序列化器支持以下特殊结尾,用于执行对应操作:
- `{}` - 使用 JSON.stringify 序列化该值
- `[]` - 将类数组对象展开为具有相同键的独立字段
::: warning
注意:展开/扩展操作默认应用于数组和 FileList 对象
:::
## 配置 FormData 序列化器
FormData 序列化器通过 `config.formSerializer` 对象属性支持以下额外选项,用于处理特殊情况:
- `visitor: Function` - 用户自定义的访问者函数,将递归调用以按照自定义规则将数据对象序列化为 FormData 对象。
- `dots: boolean = false` - 使用点号表示法代替方括号来序列化数组和对象;
- `metaTokens: boolean = true` - 在 FormData 键中添加特殊结尾(如 `user{}: '{"name": "John"}'`)。后端 body 解析器可以利用此元信息自动将值解析为 JSON。
- `indexes: null|false|true = false` - 控制如何为扁平类数组对象的展开键添加索引
- `null` - 不添加方括号(`arr: 1``arr: 2``arr: 3`
- `false`(默认)- 添加空方括号(`arr[]: 1``arr[]: 2``arr[]: 3`
- `true` - 添加带索引的方括号(`arr[0]: 1``arr[1]: 2``arr[2]: 3`
例如,对于以下对象:
```js
const obj = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: "Peter", surname: "Griffin" },
{ name: "Thomas", surname: "Anderson" },
],
"obj2{}": [{ x: 1 }],
};
```
axios 序列化器内部将执行以下步骤:
```js
const formData = new FormData();
formData.append("x", "1");
formData.append("arr[]", "1");
formData.append("arr[]", "2");
formData.append("arr[]", "3");
formData.append("arr2[0]", "1");
formData.append("arr2[1][0]", "2");
formData.append("arr2[2]", "3");
formData.append("users[0][name]", "Peter");
formData.append("users[0][surname]", "Griffin");
formData.append("users[1][name]", "Thomas");
formData.append("users[1][surname]", "Anderson");
formData.append("obj2{}", '[{"x":1}]');
```
axios 支持以下快捷方法:`postForm``putForm``patchForm`,它们分别对应相应的 HTTP 方法,并预设 `Content-Type` 请求头为 `multipart/form-data`
@@ -0,0 +1,55 @@
# 进度捕获 <Badge type="tip" text="新特性" />
axios 同时支持在浏览器和 Node.js 环境中捕获请求的上传/下载进度。进度事件的触发频率被限制为每秒最多 3 次,以避免浏览器被过多的进度事件压垮。以下是捕获进度事件的示例:
```js
await axios.post(url, data, {
onUploadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number; // 范围 [0..1]
bytes: number; // 自上次触发以来传输的字节数(增量)
estimated?: number; // 预计剩余时间(秒)
rate?: number; // 上传速度(字节/秒)
upload: true; // 上传标识
}*/
},
onDownloadProgress: function (axiosProgressEvent) {
/*{
loaded: number;
total?: number;
progress?: number;
bytes: number;
estimated?: number;
rate?: number; // 下载速度(字节/秒)
download: true; // 下载标识
}*/
},
});
```
你也可以在 Node.js 中将上传和下载进度事件流式传输到可读流,以便以自定义方式显示进度。以下是流式传输进度事件的示例:
```js
const { data } = await axios.post(SERVER_URL, readableStream, {
onUploadProgress: ({ progress }) => {
console.log((progress * 100).toFixed(2));
},
headers: {
"Content-Length": contentLength,
},
maxRedirects: 0, // 避免缓冲整个流
});
```
::: warning
Node.js 环境目前不支持捕获 FormData 上传进度
:::
::: danger
建议通过设置 `maxRedirects: 0` 来禁用重定向,以便在 Node.js 环境中上传流,因为 `follow-redirects` 包会不遵循"背压"算法而将整个流缓冲到内存中
:::
+81
View File
@@ -0,0 +1,81 @@
# Promise
axios 基于原生 ES6 Promise API 构建。每个 axios 请求都返回一个 Promise,该 Promise 解析为响应对象或以错误拒绝。如果你的环境不支持 ES6 Promise,需要使用 polyfill,例如 [es6-promise](https://github.com/stefanpenner/es6-promise)。
## then / catch / finally
由于 axios 返回的是标准 Promise,你可以使用 `.then()``.catch()``.finally()` 来处理结果:
```js
axios.get("/api/users")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error("Request failed:", error.message);
})
.finally(() => {
console.log("Request finished");
});
```
## async / await
大多数代码库推荐使用 `async/await`,它使异步代码读起来像同步代码:
```js
async function fetchUser(id) {
try {
const response = await axios.get(`/api/users/${id}`);
return response.data;
} catch (error) {
console.error("Failed to fetch user:", error.message);
throw error;
}
}
```
## 并行请求
由于 axios 返回标准 Promise,你可以使用 `Promise.all` 同时发起多个请求,并等待所有请求完成:
```js
const [users, posts] = await Promise.all([
axios.get("/api/users"),
axios.get("/api/posts"),
]);
console.log(users.data, posts.data);
```
::: tip
`Promise.all` 会在任何一个请求失败时立即 reject。如果你希望处理部分失败的情况,请改用 `Promise.allSettled`
:::
```js
const results = await Promise.allSettled([
axios.get("/api/users"),
axios.get("/api/posts"),
]);
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log(result.value.data);
} else {
console.error("Request failed:", result.reason.message);
}
});
```
## 链式请求
可以链式调用 `.then()` 来顺序执行请求,将上一个请求的数据传递给下一个:
```js
axios.get("/api/user/1")
.then(({ data: user }) => axios.get(`/api/posts?userId=${user.id}`))
.then(({ data: posts }) => {
console.log("Posts for user:", posts);
})
.catch(console.error);
```
+62
View File
@@ -0,0 +1,62 @@
# 速率限制 <Badge type="tip" text="新特性" />
axios 通过 HTTP 适配器在 Node.js 环境中支持带宽限制。你可以限制数据的上传或下载速度,适用于批量操作、后台任务或不希望占满带宽的礼貌抓取等场景。
## `maxRate`
`maxRate` 选项接受一个数字(字节/秒)或一个数组,数组第一个值为上传限制,第二个值为下载限制。使用 `[uploadRate]` 仅限制上传,使用 `[uploadRate, downloadRate]` 同时限制两个方向。传入单个数字时,该限制同时应用于上传和下载。
```js
// 将上传和下载速度均限制为 100 KB/s
await axios.get(URL, { maxRate: 100 * 1024 });
// 上传限制 100 KB/s,下载限制 500 KB/s
await axios.get(URL, { maxRate: [100 * 1024, 500 * 1024] });
```
::: warning
`maxRate` 仅支持 Node.js HTTP 适配器,在浏览器环境中无效。
:::
## 上传速率限制
限制上传速度的同时记录进度:
```js
const { data } = await axios.post(SERVER_URL, myBuffer, {
onUploadProgress: ({ progress, rate }) => {
const percent = (progress * 100).toFixed(1);
const kbps = (rate / 1024).toFixed(1);
console.log(`Upload [${percent}%] at ${kbps} KB/s`);
},
maxRate: [100 * 1024], // 上传限制 100 KB/s
});
```
## 下载速率限制
限制大响应体的下载速度:
```js
const { data } = await axios.get(FILE_URL, {
onDownloadProgress: ({ progress, rate }) => {
const percent = (progress * 100).toFixed(1);
const kbps = (rate / 1024).toFixed(1);
console.log(`Download [${percent}%] at ${kbps} KB/s`);
},
maxRate: [Infinity, 200 * 1024], // 不限制上传,下载限制 200 KB/s
responseType: "arraybuffer",
});
```
## 同时限制上传和下载
将两个限制作为数组传入,可同时控制两个方向:
```js
await axios.post(SERVER_URL, largeBuffer, {
maxRate: [50 * 1024, 500 * 1024], // 上传 50 KB/s,下载 500 KB/s
});
```
+350
View File
@@ -0,0 +1,350 @@
# 请求配置
请求配置用于配置 HTTP 请求的各项参数。虽然有大量可用选项,但唯一必填的选项是 `url`。如果配置对象中没有 `method` 字段,默认使用 `GET` 方法。
### `url`
`url` 是请求的目标 URL,可以是字符串或 `URL` 实例。
### `method`
`method` 是请求使用的 HTTP 方法,默认为 `GET`
### `baseURL`
`baseURL` 是拼接在 `url` 前面的基础 URL,除非 `url` 是绝对 URL。这对于向同一域名发起请求非常实用,无需在每次请求时重复写域名和 API 版本前缀。
### `allowAbsoluteUrls`
`allowAbsoluteUrls` 决定绝对 URL 是否可以覆盖已配置的 `baseUrl`。设置为 `true`(默认值)时,绝对 `url` 会覆盖 `baseUrl`;设置为 `false` 时,绝对 `url` 始终会拼接在 `baseUrl` 之后。
### `transformRequest`
`transformRequest` 函数允许你在数据发送到服务器之前对其进行修改,仅适用于 `PUT``POST``PATCH``DELETE` 请求方法。数组中的最后一个函数必须返回字符串、Buffer、ArrayBuffer、FormData 或 Stream 实例。
### `transformResponse`
`transformResponse` 函数允许你在数据传递给 `then``catch` 函数之前对响应数据进行修改,函数以响应数据为唯一参数。
### `headers`
`headers` 是随请求发送的 HTTP 请求头,默认将 `Content-Type` 设置为 `application/json`
### `params`
`params` 是随请求发送的 URL 查询参数,必须是普通对象或 URLSearchParams 对象。如果 `url` 中已包含查询参数,它们将与 `params` 对象合并。
### `paramsSerializer`
`paramsSerializer` 函数允许你在参数发送到服务器之前自定义 `params` 对象的序列化方式,有多个可用选项,详见本页末尾的完整请求配置示例。
### `data`
`data` 是作为请求体发送的数据,可以是字符串、普通对象、Buffer、ArrayBuffer、FormData、Stream 或 URLSearchParams,仅适用于 `PUT``POST``DELETE``PATCH` 请求方法。在未设置 `transformRequest` 的情况下,必须是以下类型之一:
- string、普通对象、ArrayBuffer、ArrayBufferView、URLSearchParams
- 仅浏览器:FormData、File、Blob
- 仅 Node.jsStream、Buffer、FormDataform-data 包)
### `timeout`
`timeout` 是请求超时前等待的毫秒数。如果请求耗时超过 `timeout`,请求将被中止。
### `withCredentials`
`withCredentials` 属性指示跨域 Access-Control 请求是否应携带 cookie、授权请求头或 TLS 客户端证书等凭据。该设置对同源请求无效。
### `adapter`
`adapter` 允许自定义请求处理方式,便于测试。返回一个 Promise 并提供有效的响应,详见[适配器](/pages/advanced/adapters)文档。我们还提供了多个内置适配器,Node.js 默认使用 `http`,浏览器默认使用 `xhr`。内置适配器列表如下:
- fetch
- http
- xhr
你也可以传入一个适配器数组,axios 将使用当前环境支持的第一个适配器。
### `auth`
`auth` 表示使用 HTTP Basic 认证,并提供凭据。这将设置 `Authorization` 请求头,覆盖任何通过 `headers` 自定义的 `Authorization` 请求头。请注意,仅 HTTP Basic 认证可通过此参数配置,Bearer 令牌等请改用自定义 `Authorization` 请求头。
### `responseType`
`responseType` 指示服务器响应的数据类型,可以是以下之一:
- arraybuffer
- document
- json
- text
- stream
- blob(仅浏览器)
- formdata(仅 fetch 适配器)
### `responseEncoding` <Badge type="warning" text="仅 Node.js" />
`responseEncoding` 指示解码响应时使用的编码,支持以下选项:
- ascii
- ASCII
- ansi
- ANSI
- binary
- BINARY
- base64
- BASE64
- base64url
- BASE64URL
- hex
- HEX
- latin1
- LATIN1
- ucs-2
- UCS-2
- ucs2
- UCS2
- utf-8
- UTF-8
- utf8
- UTF8
- utf16le
- UTF16LE
::: tip
注意:当 `responseType``stream` 或客户端请求时,此选项将被忽略
:::
### `xsrfCookieName`
`xsrfCookieName` 是用作 `XSRF` 令牌值的 cookie 名称。
### `xsrfHeaderName`
`xsrfHeaderName` 是用作 `XSRF` 令牌值的请求头名称。
### `withXSRFToken`
`withXSRFToken` 属性指示是否随请求发送 `XSRF` 令牌,仅适用于客户端请求,默认值为 undefined。
### `onUploadProgress`
`onUploadProgress` 函数允许你监听上传进度。
### `onDownloadProgress`
`onDownloadProgress` 函数允许你监听下载进度。
### `maxContentLength` <Badge type="warning" text="仅 Node.js" />
`maxContentLength` 属性定义服务器在响应中允许接收的最大字节数。
### `maxBodyLength` <Badge type="warning" text="仅 Node.js" />
`maxBodyLength` 属性定义服务器在请求中允许接收的最大字节数。
### `validateStatus`
`validateStatus` 函数允许你覆盖默认的状态码验证逻辑。默认情况下,axios 会在状态码不在 200-299 范围内时拒绝 Promise。你可以提供自定义的 `validateStatus` 函数来覆盖此行为,该函数应在状态码在你希望接受的范围内时返回 `true`
### `maxRedirects` <Badge type="warning" text="仅 Node.js" />
`maxRedirects` 属性定义最大重定向次数,设置为 0 时不跟随任何重定向。
### `beforeRedirect`
`beforeRedirect` 函数允许你在请求重定向前对其进行修改,可用于调整重定向时的请求选项、检查最新的响应头或通过抛出错误来取消请求。当 `maxRedirects` 设置为 0 时,不会使用 `beforeRedirect`
### `socketPath` <Badge type="warning" text="仅 Node.js" />
`socketPath` 属性定义用于替代 TCP 连接的 UNIX 套接字路径,例如 `/var/run/docker.sock`,用于向 Docker 守护进程发送请求。`socketPath``proxy` 只能指定其中一个,如果两者都指定,则使用 `socketPath`
### `transport`
`transport` 属性定义请求使用的传输方式,适用于通过不同协议(如 `http2`)发起请求的场景。
### `httpAgent` 和 `httpsAgent`
`httpAgent``httpsAgent` 分别定义在 Node.js 中执行 HTTP 和 HTTPS 请求时使用的自定义代理,可用于添加 `keepAlive` 等默认未启用的选项。
### `proxy`
`proxy` 定义代理服务器的主机名、端口和协议,也可以通过常规的 `http_proxy``https_proxy` 环境变量来定义代理。
如果你使用环境变量配置代理,还可以定义 `no_proxy` 环境变量,以逗号分隔的方式列出不需要代理的域名。
设置为 `false` 可禁用代理,忽略环境变量。`auth` 表示使用 HTTP Basic 认证连接代理并提供凭据,这将设置 `Proxy-Authorization` 请求头,覆盖任何通过 `headers` 自定义的 `Proxy-Authorization` 请求头。如果代理服务器使用 HTTPS,则必须将协议设置为 `https`
```js
proxy: {
protocol: "https",
host: "127.0.0.1",
hostname: "localhost", // 如果同时定义了 "host" 和 "hostname",则优先使用 "hostname"
port: 9000,
auth: {
username: "mikeymike",
password: "rapunz3l"
}
},
```
### `cancelToken`
`cancelToken` 属性允许你创建一个取消令牌,用于取消请求。详见[取消请求](/pages/advanced/cancellation)文档。
### `signal`
`signal` 属性允许你向请求传入一个 `AbortSignal` 实例,从而通过 `AbortController` API 取消请求。
### `decompress` <Badge type="warning" text="仅 Node.js" />
`decompress` 属性指示是否自动解压响应数据,默认值为 `true`
### `insecureHTTPParser`
指示是否使用接受无效 HTTP 请求头的不安全 HTTP 解析器,可用于与不符合规范的 HTTP 实现互通。不建议使用不安全解析器。
请注意,`insecureHTTPParser` 选项仅在 Node.js 12.10.0 及更高版本中可用。请阅读 [Node.js 文档](https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none)以获取更多信息。完整选项列表见[此处](https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback)。
### `transitional`
`transitional` 属性允许你启用或禁用某些过渡性功能,可用选项如下:
- `silentJSONParsing`:设置为 `true` 时,遇到无效 JSON 响应时 axios 不会输出警告,返回值设为 null。适用于返回无效 JSON 的 API。
- `forcedJSONParsing`:强制 axios 将响应解析为 JSON,即使响应不是有效的 JSON。适用于返回无效 JSON 的 API。
- `clarifyTimeoutError`:在请求超时时提供更清晰的错误信息,适用于调试超时问题。
- `legacyInterceptorReqResOrdering`:设置为 true 时使用旧版拦截器请求/响应排序。
### `env`
`env` 属性允许你设置一些配置选项,例如用于自动将数据序列化为 FormData 对象的 FormData 类。
- FormData: window?.FormData || global?.FormData
### `formSerializer`
`formSerializer` 函数允许你在数据发送到服务器之前自定义 `data` 对象的序列化方式,有多个可用选项,详见本页末尾的完整请求配置示例。
### `maxRate` <Badge type="warning" text="仅 Node.js" />
`maxRate` 属性定义上传和/或下载的最大**带宽**(字节/秒)。接受单个数字(同时适用于两个方向)或两元素数组 `[uploadRate, downloadRate]`,每个元素为字节/秒限制。例如,`100 * 1024` 表示 100 KB/s。详见[速率限制](/pages/advanced/rate-limiting)中的示例。
## 完整请求配置示例
```js
{
url: "/posts",
method: "get",
baseURL: "https://jsonplaceholder.typicode.com",
allowAbsoluteUrls: true,
transformRequest: [function (data, headers) {
return data;
}],
transformResponse: [function (data) {
return data;
}],
headers: {"X-Requested-With": "XMLHttpRequest"},
params: {
postId: 5
},
paramsSerializer: {
// 自定义编码函数,以迭代方式逐个序列化键值对。
encode?: (param: string): string => { /* 在此执行自定义操作并返回转换后的字符串 */ },
// 对整个参数进行自定义序列化的函数,允许用户模拟 1.x 之前的行为。
serialize?: (params: Record<string, any>, options?: ParamsSerializerOptions ),
// 配置数组索引在参数中的格式。
// 三种可用选项:
// (1) indexes: null(不添加方括号)
// (2)(默认)indexes: false(添加空方括号)
// (3) indexes: true(添加带索引的方括号)
indexes: false
},
data: {
firstName: "Fred"
},
// 另一种将数据发送到请求体的语法,仅适用于 POST 方法,只发送值,不发送键
data: "Country=Brasil&City=Belo Horizonte",
timeout: 1000,
withCredentials: false,
adapter: function (config) {
// 在此执行自定义逻辑
},
adapter: "xhr",
auth: {
username: "janedoe",
password: "s00pers3cret"
},
responseType: "json",
responseEncoding: "utf8",
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined),
onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) {
// 在此处理 axios 进度事件
},
onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) {
// 在此处理 axios 进度事件
},
maxContentLength: 2000,
maxBodyLength: 2000,
validateStatus: function (status) {
return status >= 200 && status < 300;
},
maxRedirects: 21,
beforeRedirect: (options, { headers }) => {
if (options.hostname === "typicode.com") {
options.auth = "user:password";
}
},
socketPath: null,
transport: undefined,
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
proxy: {
protocol: "https",
host: "127.0.0.1",
// hostname: "127.0.0.1" // 如果同时定义了 "host" 和 "hostname",则优先使用 "hostname"
port: 9000,
auth: {
username: "mikeymike",
password: "rapunz3l"
}
},
cancelToken: new CancelToken(function (cancel) {
cancel("Operation has been canceled.");
}),
signal: new AbortController().signal,
decompress: true,
insecureHTTPParser: undefined,
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false,
legacyInterceptorReqResOrdering: true,
},
env: {
FormData: window?.FormData || global?.FormData
},
formSerializer: {
// 自定义访问者函数,用于序列化表单值
visitor: (value, key, path, helpers) => {};
// 使用点号表示法代替方括号格式
dots: boolean;
// 在参数键中保留特殊结尾(如 {})
metaTokens: boolean;
// 使用数组索引格式:
// null - 不添加方括号
// false - 添加空方括号
// true - 添加带索引的方括号
indexes: boolean;
},
maxRate: [
100 * 1024, // 上传限制 100KB/s
100 * 1024 // 下载限制 100KB/s
]
}
```
@@ -0,0 +1,130 @@
# 请求别名
axios 提供了一组发起 HTTP 请求的别名方法,这些别名是 `request` 方法的快捷方式,设计简洁、使用方便。
axios 尽量遵循 RFC 7231 和 RFC 5789 规范,别名方法与这些规范中定义的 HTTP 方法保持一致。
### `axios`
axios 可以通过仅传入配置对象来发起 HTTP 请求,完整的配置对象文档见[此处](/pages/advanced/request-config)。
```ts
axios(url: string | AxiosRequestConfig, config?: AxiosRequestConfig);
```
## 方法别名
以下是可用的请求别名方法:
### `request`
`request` 方法是发起 HTTP 请求的主方法,接受一个配置对象并返回解析为响应对象的 Promise,可用于发起任意类型的 HTTP 请求。
```ts
axios.request(config: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `get`
`get` 方法用于发起 GET 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。
```ts
axios.get(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `delete`
`delete` 方法用于发起 DELETE 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。
```ts
axios.delete(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `head`
`head` 方法用于发起 HEAD 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。
```ts
axios.head(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `options`
`options` 方法用于发起 OPTIONS 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。
```ts
axios.options(url: string, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `post`
`post` 方法用于发起 POST 请求,接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。
```ts
axios.post(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `put`
`put` 方法用于发起 PUT 请求,接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。
```ts
axios.put(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
### `patch`
`patch` 方法用于发起 PATCH 请求,接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。
```ts
axios.patch(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
## 表单数据快捷方法
这些方法与上述对应方法等价,但会预设 `Content-Type``multipart/form-data`,是上传文件或提交 HTML 表单的推荐方式。
### `postForm`
```ts
axios.postForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// 从浏览器文件输入框上传文件
await axios.postForm("/api/upload", {
file: document.querySelector("#fileInput").files[0],
description: "Profile photo",
});
```
### `putForm`
```ts
axios.putForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// 用表单数据替换资源
await axios.putForm("/api/users/1/avatar", {
avatar: document.querySelector("#avatarInput").files[0],
});
```
### `patchForm`
```ts
axios.patchForm(url: string, data?: D, config?: AxiosRequestConfig<C>): AxiosResponse<R>;
```
```js
// 使用表单数据更新特定字段
await axios.patchForm("/api/users/1", {
displayName: "New Name",
avatar: document.querySelector("#avatarInput").files[0],
});
```
::: tip
`postForm``putForm``patchForm` 接受与基础方法相同的所有数据类型——普通对象、`FormData``FileList` 以及 `HTMLFormElement`。更多示例请参阅[文件上传](/pages/advanced/file-posting)。
:::
+63
View File
@@ -0,0 +1,63 @@
# 响应结构
每个 axios 请求都会解析为具有以下结构的响应对象,在浏览器和 Node.js 环境中保持一致。
```js
{
// 服务器提供的响应数据。
// 使用 `transformResponse` 时,这将是最后一次转换的结果。
data: {},
// 服务器响应的 HTTP 状态码(如 200、404、500)。
status: 200,
// 与状态码对应的 HTTP 状态消息(如 "OK"、"Not Found")。
statusText: "OK",
// 服务器发送的响应头。
// 响应头名称均为小写,可通过方括号或点号表示法访问。
headers: {},
// 本次请求使用的 axios 配置,包括 baseURL、headers、timeout、params 及其他选项。
config: {},
// 底层请求对象。
// 在 Node.js 中:最后一个 `http.ClientRequest` 实例(经过任何重定向后)。
// 在浏览器中:`XMLHttpRequest` 实例。
request: {},
}
```
## 访问响应字段
实际使用中,你通常只需要解构出所需的部分:
```js
const { data, status, headers } = await axios.get("/api/users/1");
console.log(status); // 200
console.log(headers["content-type"]); // "application/json; charset=utf-8"
console.log(data); // { id: 1, name: "Jay", email: "jay@example.com" }
```
## 检查状态码
axios 默认对任何 2xx 响应 resolve Promise,对超出该范围的响应 reject Promise。可以通过 `validateStatus` 配置选项自定义此行为:
```js
const response = await axios.get("/api/resource", {
validateStatus: (status) => status < 500, // 500 以下的所有状态码均 resolve
});
```
## 访问响应头
无论服务器如何发送,所有响应头名称均为小写:
```js
const response = await axios.get("/api/resource");
// 以下两种写法等价
const contentType = response.headers["content-type"];
const contentType2 = response.headers.get("content-type");
```
+130
View File
@@ -0,0 +1,130 @@
# 重试与错误恢复
网络请求可能因瞬时原因而失败——服务器抖动、短暂的网络中断或限流响应。在拦截器中实现重试策略,可以让你透明地处理这些失败,无需在业务代码中添加繁琐的重试逻辑。
## 基本重试(使用响应拦截器)
最简单的方式是捕获特定错误状态码,并在有限次数内立即重新发送原始请求:
```js
import axios from "axios";
const api = axios.create({ baseURL: "https://api.example.com" });
const MAX_RETRIES = 3;
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
// 仅在网络错误或 5xx 服务器错误时重试
const shouldRetry =
!error.response || (error.response.status >= 500 && error.response.status < 600);
if (!shouldRetry) {
return Promise.reject(error);
}
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= MAX_RETRIES) {
return Promise.reject(error);
}
config._retryCount += 1;
return api(config);
}
);
```
## 指数退避
失败后立即重试可能会使本已压力过大的服务器雪上加霜。指数退避策略会在每次重试之间等待逐渐增长的时间:
```js
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
const shouldRetry =
!error.response || (error.response.status >= 500 && error.response.status < 600);
if (!shouldRetry) return Promise.reject(error);
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= 3) return Promise.reject(error);
config._retryCount += 1;
// 每次重试前分别等待 200ms、400ms、800ms……
const backoff = 100 * 2 ** config._retryCount;
await delay(backoff);
return api(config);
}
);
```
## 响应 429(限流)时使用 Retry-After
当服务器返回 `429 Too Many Requests` 时,通常会在响应头中包含 `Retry-After` 字段,明确告知你需要等待多长时间:
```js
api.interceptors.response.use(
(response) => response,
async (error) => {
const config = error.config;
if (error.response?.status !== 429) return Promise.reject(error);
config._retryCount = config._retryCount ?? 0;
if (config._retryCount >= 3) return Promise.reject(error);
config._retryCount += 1;
const retryAfterHeader = error.response.headers["retry-after"];
const waitMs = retryAfterHeader
? parseFloat(retryAfterHeader) * 1000 // 请求头单位为秒
: 1000; // 默认等待 1 秒
await new Promise((resolve) => setTimeout(resolve, waitMs));
return api(config);
}
);
```
## 针对特定请求禁用重试
如果某些请求不应被重试(例如不幂等的变更操作,不希望重复执行),可以在请求配置中添加一个标志:
```js
// 在重试逻辑之前,在拦截器中添加以下判断:
if (config._noRetry) return Promise.reject(error);
// 然后在特定调用中禁用重试:
await api.post("/payments/charge", body, { _noRetry: true });
```
## 结合重试与取消
使用 `AbortController` 可以取消正在等待退避延迟的请求:
```js
const controller = new AbortController();
try {
await api.get("/api/data", { signal: controller.signal });
} catch (error) {
if (axios.isCancel(error)) {
console.log("Request aborted by user");
}
}
// 从其他地方取消请求(以及任何待处理的重试延迟):
controller.abort();
```
+145
View File
@@ -0,0 +1,145 @@
# 测试
测试使用 axios 发起 HTTP 请求的代码非常简单。推荐的方式是对 axios 本身进行 mock,让测试在不触及真实网络的情况下运行,从而完全控制代码收到的响应内容。
## 使用 Vitest 或 Jest 进行 Mock
Vitest 和 Jest 都支持通过 `vi.mock` / `jest.mock` 进行模块级 mock。你可以 mock 整个 axios 模块,并控制每个方法的返回值:
```js
// user-service.js
import axios from "axios";
export async function getUser(id) {
const { data } = await axios.get(`/api/users/${id}`);
return data;
}
```
```js
// user-service.test.js
import { describe, it, expect, vi } from "vitest";
import axios from "axios";
import { getUser } from "./user-service";
vi.mock("axios");
describe("getUser", () => {
it("returns user data on success", async () => {
const mockUser = { id: 1, name: "Jay" };
// 让 axios.get 返回我们的假响应
axios.get.mockResolvedValueOnce({ data: mockUser });
const result = await getUser(1);
expect(result).toEqual(mockUser);
expect(axios.get).toHaveBeenCalledWith("/api/users/1");
});
it("throws when the request fails", async () => {
axios.get.mockRejectedValueOnce(new Error("Network error"));
await expect(getUser(1)).rejects.toThrow("Network error");
});
});
```
## Mock AxiosError
要测试检查 `error.response` 的错误处理路径,可以直接创建一个 `AxiosError` 实例:
```js
import axios, { AxiosError } from "axios";
import { vi } from "vitest";
const mockError = new AxiosError(
"Not Found",
"ERR_BAD_REQUEST",
{}, // config
{}, // request
{ // response
status: 404,
statusText: "Not Found",
data: { message: "User not found" },
headers: {},
config: {},
}
);
axios.get.mockRejectedValueOnce(mockError);
```
## 使用 axios-mock-adapter
[axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) 是一个在 axios 实例上安装自定义适配器的库,在适配器层面拦截请求。这意味着你的拦截器仍然会执行,因此更适合集成测试。
```bash
npm install --save-dev axios-mock-adapter
```
```js
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
const mock = new MockAdapter(axios);
// Mock GET 请求
mock.onGet("/api/users/1").reply(200, { id: 1, name: "Jay" });
// Mock POST 请求
mock.onPost("/api/users").reply(201, { id: 2, name: "New User" });
// Mock 网络错误
mock.onGet("/api/failing").networkError();
// Mock 超时
mock.onGet("/api/slow").timeout();
```
在每个测试之间重置 mock
```js
afterEach(() => {
mock.reset(); // 清除所有已注册的处理器
});
```
## 测试拦截器
要单独测试拦截器,在测试中创建一个全新的 axios 实例:
```js
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
describe("auth interceptor", () => {
it("attaches a Bearer token to every request", async () => {
const instance = axios.create();
const mock = new MockAdapter(instance);
// 添加你的拦截器
instance.interceptors.request.use((config) => {
config.headers.set("Authorization", "Bearer test-token");
return config;
});
// 通过检查 mock 收到的内容来捕获请求配置
let capturedConfig;
mock.onGet("/api/data").reply((config) => {
capturedConfig = config;
return [200, {}];
});
await instance.get("/api/data");
expect(capturedConfig.headers["Authorization"]).toBe("Bearer test-token");
});
});
```
## 最佳实践
- 始终在模块级别进行 mock(或使用 `MockAdapter`)——避免在共享实例的单个方法上进行 mock,因为状态可能在测试之间泄漏。
- 优先使用 `mockResolvedValueOnce` / `mockRejectedValueOnce`,而不是 `mockResolvedValue`,以确保测试相互隔离,互不影响。
- 测试重试逻辑时,使用 `MockAdapter`,以便被测拦截器在每次重试时都能真正执行。
+8
View File
@@ -0,0 +1,8 @@
# TypeScript
`axios` 支持 TypeScript 类型定义,这些定义通过 npm 包中的 `index.d.ts` 文件提供。由于 axios 同时以 ESM 默认导出和 CJS `module.exports` 两种方式发布,存在以下注意事项:
- 推荐使用 `"moduleResolution": "node16"`(由 `"module": "node16"` 隐式指定),需要 TypeScript 4.7 或更高版本。
- 如果你使用 ESM,现有配置应该没有问题。
- 如果你将 TypeScript 编译为 CJS 且无法使用 `"moduleResolution": "node16"`,则必须启用 `esModuleInterop`
- 如果你使用 TypeScript 对 CJS JavaScript 代码进行类型检查,则只能使用 `"moduleResolution": "node16"`
@@ -0,0 +1,78 @@
# x-www-form-urlencoded 格式
## URLSearchParams
默认情况下,axios 会将 JavaScript 对象序列化为 `JSON`。如果需要以 [`application/x-www-form-urlencoded` 格式](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)发送数据,可以使用 [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API,绝大多数浏览器[已支持](http://www.caniuse.com/#feat=urlsearchparams)该 APINode.js 从 v102018 年发布)开始也[支持](https://nodejs.org/api/url.html#url_class_urlsearchparams)。
```js
const params = new URLSearchParams({ foo: 'bar' });
params.append('extraparam', 'value');
axios.post('/foo', params);
```
## 查询字符串 <Badge type="danger" text="非常旧" />
对于不支持 `URLSearchParams` 的旧版浏览器或环境,可以使用 [`qs`](https://github.com/ljharb/qs) 库将对象序列化为 `application/x-www-form-urlencoded` 格式。
```js
const qs = require('qs');
axios.post('/foo', qs.stringify({ bar: 123 }));
```
在非常旧的 Node.js 版本中,可以使用 Node.js 内置的 `querystring` 模块。注意该模块在 Node.js v16 中已废弃——新代码请优先使用 `URLSearchParams``qs`
```js
const querystring = require('querystring');
axios.post('https://something.com/', querystring.stringify({ foo: 'bar' }));
```
## 自动序列化为 URLSearchParams <Badge type="tip" text="新特性" />
从 v0.21.0 起,如果将 `Content-Type` 请求头设置为 `application/x-www-form-urlencoded`axios 会自动将 JavaScript 对象序列化为 `URLSearchParams`。这意味着你可以直接将 JavaScript 对象传入 axios 请求配置的 `data` 属性。例如,向 `POST` 请求传递数据时:
```js
const data = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: 'Peter', surname: 'Griffin' },
{ name: 'Thomas', surname: 'Anderson' },
],
};
await axios.postForm('https://postman-echo.com/post', data, {
headers: { 'content-type': 'application/x-www-form-urlencoded' },
});
```
`data` 对象将被自动序列化为 `URLSearchParams` 并以 `application/x-www-form-urlencoded` 格式发送。服务器将收到以下数据:
```json
{
"x": "1",
"arr[]": ["1", "2", "3"],
"arr2[0]": "1",
"arr2[1][0]": "2",
"arr2[2]": "3",
"users[0][name]": "Peter",
"users[0][surname]": "Griffin",
"users[1][name]": "Thomas",
"users[1][surname]": "Anderson"
}
```
如果你的后端 body 解析器(如 `express.js``body-parser`)支持嵌套对象解码,服务器端将自动还原为相同的对象结构:
```js
var app = express();
app.use(bodyParser.urlencoded({ extended: true })); // 支持编码后的请求体
app.post('/', function (req, res, next) {
// 将请求体以 JSON 格式回传
res.send(JSON.stringify(req.body));
});
server = app.listen(3000);
```
@@ -0,0 +1,226 @@
# JavaScript 示例
## 导入库
在 CommonJS 环境中,可以使用 `require` 函数导入库;如果使用 Webpack 或 Rollup 等打包工具,则可以使用 `import` 语句。
#### 不使用打包工具
```js
const axios = require("axios");
```
#### 使用打包工具(webpack、rollup、vite 等)
```js
import axios from "axios";
```
## 使用 then/catch/finally
axios 的核心返回的是一个 Promise,你可以使用 `then``catch``finally` 回调来处理响应数据、错误以及请求完成的逻辑。
### GET 请求
```js
axios
.get("https://jsonplaceholder.typicode.com/posts", {
params: {
postId: 5,
},
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### POST 请求
```js
axios
.post("https://jsonplaceholder.typicode.com/posts", {
title: "foo",
body: "bar",
userId: 1,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### PUT 请求
```js
axios
.put("https://jsonplaceholder.typicode.com/posts/1", {
title: "foo",
body: "bar",
userId: 1,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### PATCH 请求
```js
axios
.patch("https://jsonplaceholder.typicode.com/posts/1", {
title: "foo",
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
### DELETE 请求
```js
axios
.delete("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Request completed");
});
```
## 使用 async/await
处理 Promise 的另一种方式是使用 `async``await`,配合 try/catch/finally 块来处理错误和完成逻辑。这种写法可以让代码更加清晰易读,同时有效避免所谓的"回调地狱"。
::: tip
注意:async/await 属于 ECMAScript 2017 规范,Internet Explorer 及部分旧版浏览器不支持,使用时请注意兼容性。
:::
### GET 请求
```js
const getPosts = async () => {
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts",
{
params: {
postId: 5,
},
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### POST 请求
```js
const createPost = async () => {
try {
const response = await axios.post(
"https://jsonplaceholder.typicode.com/posts",
{
title: "foo",
body: "bar",
userId: 1,
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### PUT 请求
```js
const updatePost = async () => {
try {
const response = await axios.put(
"https://jsonplaceholder.typicode.com/posts/1",
{
title: "foo",
body: "bar",
userId: 1,
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### PATCH 请求
```js
const updatePost = async () => {
try {
const response = await axios.patch(
"https://jsonplaceholder.typicode.com/posts/1",
{
title: "foo",
}
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
### DELETE 请求
```js
const deletePost = async () => {
try {
const response = await axios.delete(
"https://jsonplaceholder.typicode.com/posts/1"
);
console.log(response.data);
} catch (error) {
console.error(error);
} finally {
console.log("Request completed");
}
};
```
@@ -0,0 +1,139 @@
# TypeScript 示例
## 导入类型
axios 内置了 TypeScript 类型定义,你可以直接从 `"axios"` 导入所需的类型:
```ts
import axios from "axios";
import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
```
## 为请求标注类型
在响应上使用泛型参数,告知 TypeScript 数据的具体结构:
```ts
import axios from "axios";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
const response = await axios.get<Post>("https://jsonplaceholder.typicode.com/posts/1");
console.log(response.data.title); // TypeScript 知道这是一个字符串
```
## 为函数标注类型
将请求封装在函数中,并明确声明返回类型,以获得最佳的类型安全性:
```ts
import axios, { AxiosResponse } from "axios";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
const getPost = async (id: number): Promise<Post> => {
const response = await axios.get<Post>(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
return response.data;
};
```
## 为 POST 请求标注类型
你可以同时为请求体和预期响应标注类型:
```ts
type CreatePostBody = {
title: string;
body: string;
userId: number;
};
type CreatePostResponse = CreatePostBody & { id: number };
const createPost = async (data: CreatePostBody): Promise<CreatePostResponse> => {
const response = await axios.post<CreatePostResponse>(
"https://jsonplaceholder.typicode.com/posts",
data
);
return response.data;
};
```
## 带类型的 axios 实例
创建一个带类型的实例,将 baseURL 和请求头内置其中:
```ts
import axios from "axios";
import type { AxiosInstance } from "axios";
const api: AxiosInstance = axios.create({
baseURL: "https://api.example.com",
timeout: 5000,
});
```
## 带类型的拦截器
在 v1.x 中,请求拦截器应使用 `InternalAxiosRequestConfig`(而非 `AxiosRequestConfig`):
```ts
import axios from "axios";
import type { InternalAxiosRequestConfig, AxiosResponse } from "axios";
api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
config.headers.set("Authorization", `Bearer ${getToken()}`);
return config;
});
api.interceptors.response.use(
(response: AxiosResponse) => response,
(error) => Promise.reject(error)
);
```
## 为错误标注类型
使用 `axios.isAxiosError()` 对捕获的错误进行类型收窄:
```ts
import axios, { AxiosError } from "axios";
type ApiError = {
message: string;
code: number;
};
try {
await axios.get("/api/protected-resource");
} catch (error) {
if (axios.isAxiosError<ApiError>(error)) {
// error.response?.data 的类型为 ApiError
console.error(error.response?.data.message);
console.error(error.response?.status);
} else {
throw error;
}
}
```
## TypeScript 配置说明
由于 axios 同时发布了 ESM 和 CJS 版本,根据你的配置不同,可能存在以下注意事项:
- 推荐设置为 `"moduleResolution": "node16"`(由 `"module": "node16"` 隐式指定),需要 TypeScript 4.7 或更高版本。
- 如果你将 TypeScript 编译为 CJS 且无法使用 `"moduleResolution": "node16"`,请启用 `"esModuleInterop": true`
- 如果你使用 TypeScript 对 CJS JavaScript 代码进行类型检查,则只能使用 `"moduleResolution": "node16"`
+42
View File
@@ -0,0 +1,42 @@
# 功能特性
axios 是一个功能强大的 HTTP 客户端,提供简单易用的 API 来发起 HTTP 请求。它支持所有主流浏览器,在 JavaScript 社区中被广泛使用。以下是 axios 的核心特性,这些特性使其成为你下一个项目的优选方案。
## 同构(Isomorphic
axios 是一个通用 HTTP 客户端,可在浏览器和 Node.js 中同时使用。这意味着你既可以在前端代码中发起 API 请求,也可以在后端代码中使用 axios,非常适合构建渐进式 Web 应用、单页应用以及服务端渲染应用。
对于同时负责前后端开发的团队,axios 也是绝佳选择。统一使用 axios 发起 HTTP 请求,可以降低代码库的复杂度,保持前后端 API 的一致性。
## Fetch 支持 <Badge type="tip" text="新特性" />
axios 对 Fetch API 提供了一流的支持。Fetch API 是 XHR API 的现代替代方案,可通过配置选项启用该适配器。XHR 适配器和 Fetch 适配器使用完全相同的 API,因此无需修改现有代码即可平滑迁移到 Fetch API。
## 浏览器支持
axios 支持所有主流浏览器及部分较旧的浏览器,包括 Chrome、Firefox、Safari 和 Edge,是构建需要兼容多种浏览器的 Web 应用的理想选择。
## Node.js 支持
axios 同样支持多个 Node.js 版本,兼容性经过测试,最早可追溯至 v12.x,在无法或不便升级到最新 Node.js 版本的环境中同样可以放心使用。
此外,axios 还有针对 Bun 和 Deno 的冒烟测试,用于验证关键的运行时行为,增强跨运行时兼容性的可信度。
## 其他特性
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- AbortController 支持
- 超时设置
- 支持嵌套参数的查询字符串序列化
- 自动将请求体序列化为:
- JSONapplication/json
- Multipart / FormDatamultipart/form-data
- URL 编码表单(application/x-www-form-urlencoded
- 将 HTML 表单数据以 JSON 格式发送
- 自动处理响应中的 JSON 数据
- 支持浏览器和 Node.js 的进度捕获,并提供额外信息(传输速率、剩余时间)
- 支持在 Node.js 中设置带宽限制
- 兼容规范的 FormData 和 Blob(包括 Node.js 环境)
- 客户端 XSRF 防护支持
@@ -0,0 +1,73 @@
# 入门指南
欢迎阅读 axios 文档!本指南将帮助你快速上手 axios,并发起第一个 API 请求。如果你是 axios 新手,建议从这里开始。
## 安装
你可以通过多种方式在项目中使用 axios。最常见的方式是通过 npm 安装,也支持 jsDelivr、unpkg 等 CDN。
#### 使用 npm
```bash
npm install axios
```
#### 使用 pnpm
```bash
pnpm install axios
```
#### 使用 yarn
```bash
yarn add axios
```
#### 使用 bun
```bash
bun add axios
```
#### 使用 deno
```bash
deno install npm:axios
```
#### 使用 jsDelivr
使用 jsDelivr 时,建议使用压缩版本并固定版本号,以避免意外更新。如需使用最新版本,可以去掉版本号,但强烈不建议在生产环境这样做,因为可能导致应用出现意外变化。
```html
<script src="https://cdn.jsdelivr.net/npm/axios@<x.x.x>/dist/axios.min.js"></script>
```
#### 使用 unpkg
使用 unpkg 时,建议使用压缩版本并固定版本号,以避免意外更新。如需使用最新版本,可以去掉版本号,但强烈不建议在生产环境这样做,因为可能导致应用出现意外变化。
```html
<script src="https://unpkg.com/axios@<x.x.x>/dist/axios.min.js"></script>
```
## 发起第一个请求
使用 axios 发起请求最少只需要两行代码。你可以通过提供 URL 和请求方法向任意 API 发送请求。例如,向 JSONPlaceholder API 发起一个 GET 请求:
```js
import axios from "axios";
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts/1"
);
console.log(response.data);
```
axios 提供了简洁的请求 API。你可以使用 `axios.get` 发起 GET 请求,使用 `axios.post` 发起 POST 请求,依此类推。也可以使用 `axios.request` 方法发起任意类型的请求。
## 下一步
现在你已经用 axios 完成了第一个请求,可以继续探索 axios 文档的其余内容。了解更多关于发起请求、处理响应以及在项目中使用 axios 的知识,请查阅文档其他章节。
@@ -0,0 +1,92 @@
# 升级指南
本指南旨在帮助你将项目从旧版本升级到新版本。建议阅读每个主要版本的发布说明,其中可能包含关于破坏性变更的重要信息。
## 从 v0.x 升级到 v1.x
### import 语句变更
在 v1.x 中,import 语句改为使用 `default` 导出,你需要将 import 语句更新为如下形式:
```diff
- import { axios } from "axios";
+ import axios from "axios";
```
### 拦截器系统变更
在 v1.x 中,你需要使用 `InternalAxiosRequestConfig` 类型来为 `request` 拦截器的 `config` 参数标注类型。这是因为该参数现在的类型是 `InternalAxiosRequestConfig`,而不再是公开的 `AxiosRequestConfig`
```diff
- axios.interceptors.request.use((config: AxiosRequestConfig) => {
+ axios.interceptors.request.use((config: InternalAxiosRequestConfig) => {
return config;
});
```
### 请求头结构变更
在 v1.x 中,请求头的结构已去除 `common` 属性,你需要按如下方式更新相关代码:
```diff
- if (request.headers?.common?.Authorization) {
- request.headers.common.Authorization = ...
+ if (request.headers?.Authorization) {
+ request.headers.Authorization = ...
```
原本位于 `common``get``post` 等属性下的默认请求头,现在直接设置在 `axios.defaults.headers` 上:
```diff
- axios.defaults.headers.common["Accept"] = "application/json";
+ axios.defaults.headers["Accept"] = "application/json";
```
### Multipart 表单数据
如果请求包含 `FormData` 数据,`Content-Type: multipart/form-data` 请求头现在会被自动设置,请移除手动设置以避免重复:
```diff
- axios.post("/upload", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
+ axios.post("/upload", formData);
```
如果你明确设置了 `Content-Type: application/json`,axios 现在会自动将数据序列化为 JSON。
### 参数序列化
v1.x 对 URL 参数的序列化方式进行了若干破坏性变更,主要包括:
**`params` 默认会进行百分号编码。** 如果你的后端期望接收 qs 风格的原始方括号编码,可能需要配置自定义序列化器:
```js
import qs from 'qs';
axios.create({
paramsSerializer: {
serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' }),
},
});
```
**`params` 中的嵌套对象现在使用方括号表示法**(`foo[bar]=1`)序列化,而不再使用点号表示法。如果你的后端期望点号表示法,请使用自定义序列化器。
**`null``undefined` 参数**的处理方式现在已统一:`null` 值序列化为空字符串,而 `undefined` 值则被完全忽略。
关于参数序列化配置的完整选项,请参阅[请求配置](/pages/advanced/request-config)页面。
### 内部模块不再导出
我们决定不再导出 axios 的内部模块,你需要将代码更新为仅使用 axios 的公开 API。此变更旨在简化 API,缩小 axios 的接口范围,使我们能够在不声明破坏性变更的情况下修改内部实现。
请查阅本站的 [API 参考](/pages/advanced/api-reference),获取最新的公开 API 信息。
### 请求配置
我们对请求配置对象进行了调整,请查阅本站的[配置参考](/pages/advanced/request-config)获取最新信息。
### 遗漏的破坏性变更
本指南并不详尽,可能未涵盖所有破坏性变更。如果你遇到任何问题,欢迎在 [docs GitHub 仓库](https://github.com/axios/docs)提交 issue,并添加 `breaking change` 标签。

Some files were not shown because too many files have changed in this diff Show More