pin_drop当前位置:知识文库 ❯ 图文

后端通信:HTTP状态码 - 从入门到实践详解

教程简介

HTTP状态码是服务器对客户端请求的响应状态标识,由三位数字组成,是前后端通信中判断请求成功与否、定位问题的关键依据。理解HTTP状态码的语义,能够帮助开发者快速判断请求处理结果、正确处理错误场景、设计规范的API响应。

本教程将全面讲解HTTP状态码的分类体系、各类状态码的含义与使用场景、自定义状态码处理、错误页面设计,以及前后端如何基于状态码实现健壮的错误处理机制。

核心概念

1. 状态码分类

HTTP状态码分为5大类,由第一位数字决定:

类别 范围 含义 是否常用
1xx 100-199 信息性状态码 较少使用
2xx 200-299 成功状态码 非常常用
3xx 300-399 重定向状态码 常用
4xx 400-499 客户端错误状态码 非常常用
5xx 500-599 服务器错误状态码 常用

2. 1xx 信息性状态码

1xx状态码表示请求已被接收,继续处理。

状态码 名称 说明
100 Continue 继续发送请求体,用于大文件上传前的确认
101 Switching Protocols 切换协议,WebSocket握手时使用
102 Processing 服务器正在处理请求,但尚未完成
103 Early Hints 在最终响应前预发送资源提示

100 Continue 的工作流程

客户端发送带有Expect: 100-continue头部的请求时,服务器先返回100,客户端再发送请求体:

代码示例

客户端 → 服务器:
POST /upload HTTP/1.1
Expect: 100-continue
Content-Length: 10485760

服务器 → 客户端:
HTTP/1.1 100 Continue

客户端 → 服务器:
(发送请求体数据)

服务器 → 客户端:
HTTP/1.1 201 Created

101 Switching Protocols 在WebSocket升级时使用:

代码示例

客户端 → 服务器:
GET /ws HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

服务器 → 客户端:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

3. 2xx 成功状态码

2xx状态码表示请求已成功被服务器接收、理解并处理。

状态码 名称 说明 典型场景
200 OK 请求成功 GET获取资源、PUT更新成功
201 Created 资源创建成功 POST创建新资源
202 Accepted 请求已接受但未完成 异步任务提交
203 Non-Authoritative Information 非权威信息 代理修改了响应
204 No Content 成功但无返回内容 DELETE删除成功
205 Reset Content 重置内容 表单提交后清空表单
206 Partial Content 部分内容 范围请求/断点续传

常用2xx状态码详解

  • 200 OK:最通用的成功状态码,适用于大多数成功响应

  • 201 Created:资源创建成功,响应应包含Location头部指向新资源

  • 204 No Content:操作成功但不需要返回内容,常用于DELETE和PUT

  • 206 Partial Content:配合Range头部实现断点续传

4. 3xx 重定向状态码

3xx状态码表示需要客户端采取进一步操作才能完成请求。

状态码 名称 永久/临时 保留方法 典型场景
301 Moved Permanently 永久 可能变为GET 域名迁移
302 Found 临时 可能变为GET 临时维护跳转
303 See Other 临时 变为GET POST后重定向到结果页
307 Temporary Redirect 临时 保留原方法 临时跳转保持POST
308 Permanent Redirect 永久 保留原方法 永久跳转保持POST

重要区别

  • 301 vs 302:301是永久重定向,浏览器会缓存;302是临时的,每次都请求原URL

  • 302 vs 307:302可能将POST变为GET(历史原因),307保证保持原方法

  • 301 vs 308:308是301的改进版,保证保持原HTTP方法

304 Not Modified:虽然属于3xx,但不是重定向,而是缓存相关:

代码示例

客户端 → 服务器:
GET /api/data HTTP/1.1
If-None-Match: "abc123"

服务器 → 客户端:
HTTP/1.1 304 Not Modified
ETag: "abc123"
(无响应体)

5. 4xx 客户端错误状态码

4xx状态码表示客户端发送的请求有错误。

状态码 名称 说明 典型场景
400 Bad Request 请求语法错误 参数验证失败
401 Unauthorized 未认证 未登录/Token过期
403 Forbidden 已认证但无权限 权限不足
404 Not Found 资源不存在 URL错误/资源已删除
405 Method Not Allowed 方法不允许 对只读资源使用DELETE
408 Request Timeout 请求超时 服务器等待请求超时
409 Conflict 请求冲突 重复创建/版本冲突
410 Gone 资源已永久删除 资源曾经存在但已移除
413 Payload Too Large 请求体过大 上传文件超过限制
415 Unsupported Media Type 不支持的媒体类型 Content-Type错误
422 Unprocessable Entity 无法处理的实体 数据验证失败
429 Too Many Requests 请求过多 触发限流

401 vs 403 的区别

  • 401 Unauthorized:客户端未提供有效的身份认证凭据。响应应包含WWW-Authenticate头部

  • 403 Forbidden:客户端已认证,但没有权限访问该资源。即使重新认证也无法获得权限

400 vs 422 的区别

  • 400 Bad Request:请求格式本身有问题(语法错误、缺少必要参数)

  • 422 Unprocessable Entity:请求格式正确,但数据语义有问题(验证失败)

6. 5xx 服务器错误状态码

5xx状态码表示服务器在处理请求时发生了错误。

状态码 名称 说明 典型场景
500 Internal Server Error 服务器内部错误 代码异常/未捕获错误
501 Not Implemented 功能未实现 请求的方法服务器不支持
502 Bad Gateway 网关错误 上游服务器返回无效响应
503 Service Unavailable 服务不可用 服务器过载/维护中
504 Gateway Timeout 网关超时 上游服务器响应超时

502 vs 504 的区别

  • 502 Bad Gateway:网关/代理收到了上游服务器的无效响应

  • 504 Gateway Timeout:网关/代理等待上游服务器响应超时

语法与用法

前端基于状态码的处理模式

代码示例

async function apiRequest(url, options = {}) {
    const response = await fetch(url, options);

    // 根据状态码分类处理
    if (response.status >= 200 && response.status < 300) {
        // 2xx 成功
        if (response.status === 204) return null;
        return await response.json();
    }

    if (response.status === 401) {
        // 未认证,跳转登录
        window.location.href = '/login';
        throw new Error('请先登录');
    }

    if (response.status === 403) {
        throw new Error('权限不足');
    }

    if (response.status === 404) {
        throw new Error('请求的资源不存在');
    }

    if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After');
        throw new Error(`请求过于频繁,请${retryAfter}秒后重试`);
    }

    if (response.status >= 500) {
        throw new Error('服务器错误,请稍后重试');
    }

    throw new Error(`请求失败: ${response.status}`);
}

代码示例

示例1:HTTP状态码速查工具

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTTP状态码速查工具</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: 'Segoe UI', system-ui, sans-serif;
            background: #f0f2f5;
            padding: 20px;
            color: #333;
        }
        .container { max-width: 1000px; margin: 0 auto; }
        h1 { text-align: center; color: #1a73e8; margin-bottom: 24px; font-size: 28px; }
        .search-box {
            width: 100%;
            padding: 14px 20px;
            border: 2px solid #dadce0;
            border-radius: 12px;
            font-size: 16px;
            margin-bottom: 20px;
        }
        .search-box:focus {
            outline: none;
            border-color: #1a73e8;
            box-shadow: 0 0 0 3px rgba(26,115,232,0.15);
        }
        .category-section { margin-bottom: 24px; }
        .category-header {
            padding: 12px 20px;
            border-radius: 10px;
            font-weight: 700;
            font-size: 16px;
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .cat-1xx { background: #e3f2fd; color: #1565c0; }
        .cat-2xx { background: #e8f5e9; color: #2e7d32; }
        .cat-3xx { background: #fff3e0; color: #ef6c00; }
        .cat-4xx { background: #fce4ec; color: #c62828; }
        .cat-5xx { background: #ffebee; color: #b71c1c; }
        .code-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
            gap: 10px;
        }
        .code-card {
            background: #fff;
            border-radius: 10px;
            padding: 16px;
            cursor: pointer;
            transition: all 0.2s;
            box-shadow: 0 1px 4px rgba(0,0,0,0.06);
            border-left: 4px solid transparent;
        }
        .code-card:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
        }
        .code-card.type-1xx { border-left-color: #1565c0; }
        .code-card.type-2xx { border-left-color: #2e7d32; }
        .code-card.type-3xx { border-left-color: #ef6c00; }
        .code-card.type-4xx { border-left-color: #c62828; }
        .code-card.type-5xx { border-left-color: #b71c1c; }
        .code-number {
            font-size: 22px;
            font-weight: 800;
            margin-bottom: 4px;
        }
        .code-name {
            font-size: 13px;
            color: #666;
        }
        .detail-modal {
            display: none;
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(0,0,0,0.5);
            z-index: 1000;
            align-items: center;
            justify-content: center;
        }
        .detail-modal.show { display: flex; }
        .detail-content {
            background: #fff;
            border-radius: 16px;
            padding: 32px;
            max-width: 600px;
            width: 90%;
            max-height: 80vh;
            overflow-y: auto;
        }
        .detail-code {
            font-size: 48px;
            font-weight: 800;
            margin-bottom: 8px;
        }
        .detail-name {
            font-size: 20px;
            font-weight: 600;
            margin-bottom: 16px;
            color: #555;
        }
        .detail-desc {
            font-size: 15px;
            line-height: 1.8;
            color: #555;
            margin-bottom: 16px;
        }
        .detail-section {
            margin-bottom: 16px;
        }
        .detail-section h4 {
            font-size: 14px;
            color: #888;
            margin-bottom: 8px;
        }
        .detail-code-block {
            background: #1e1e1e;
            color: #d4d4d4;
            padding: 14px;
            border-radius: 8px;
            font-family: 'Consolas', monospace;
            font-size: 13px;
            line-height: 1.7;
            white-space: pre-wrap;
        }
        .close-btn {
            position: absolute;
            top: 16px;
            right: 16px;
            width: 36px;
            height: 36px;
            border-radius: 50%;
            border: none;
            background: #f0f0f0;
            font-size: 18px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>HTTP状态码速查工具</h1>
        <input type="text" class="search-box" id="searchBox" placeholder="搜索状态码或名称,如:404、Not Found、未找到...">

        <div id="statusCodes"></div>
    </div>

    <div class="detail-modal" id="detailModal">
        <div class="detail-content" style="position:relative;">
            <button class="close-btn" onclick="closeDetail()">×</button>
            <div id="detailBody"></div>
        </div>
    </div>

    <script>
        const statusCodes = {
            '1xx': {
                name: '信息性状态码',
                codes: [
                    { code: 100, name: 'Continue', desc: '服务器已收到请求的起始部分,客户端应继续发送剩余部分。通常用于大文件上传场景,客户端先发送Expect: 100-continue头部,服务器确认后再发送请求体。', example: '客户端:POST /upload\\nExpect: 100-continue\\n\\n服务器:HTTP/1.1 100 Continue\\n\\n客户端:(发送请求体)' },
                    { code: 101, name: 'Switching Protocols', desc: '服务器同意切换协议。WebSocket连接建立时,服务器返回101状态码表示协议升级成功。', example: '客户端:GET /ws HTTP/1.1\\nUpgrade: websocket\\nConnection: Upgrade\\n\\n服务器:HTTP/1.1 101 Switching Protocols\\nUpgrade: websocket' },
                    { code: 103, name: 'Early Hints', desc: '在最终响应之前,服务器可以先发送一些资源提示,让浏览器预加载关键资源。', example: '服务器:HTTP/1.1 103 Early Hints\\nLink: </style.css>; rel=preload; as=style\\n\\n(稍后发送最终响应)' }
                ]
            },
            '2xx': {
                name: '成功状态码',
                codes: [
                    { code: 200, name: 'OK', desc: '请求成功。GET请求返回资源,POST请求返回创建结果,PUT请求返回更新结果。是最常用的成功状态码。', example: 'HTTP/1.1 200 OK\\nContent-Type: application/json\\n\\n{"id":1,"name":"张三"}' },
                    { code: 201, name: 'Created', desc: '资源创建成功。POST请求创建新资源后返回,响应应包含Location头部指向新资源的URI。', example: 'HTTP/1.1 201 Created\\nLocation: /api/users/5\\n\\n{"id":5,"name":"新用户"}' },
                    { code: 202, name: 'Accepted', desc: '请求已接受但尚未处理完成。用于异步操作场景,客户端需要通过其他方式查询处理结果。', example: 'HTTP/1.1 202 Accepted\\n\\n{"taskId":"abc123","status":"processing"}' },
                    { code: 204, name: 'No Content', desc: '请求成功但无返回内容。常用于DELETE请求和不需要返回数据的PUT/PATCH请求。', example: 'HTTP/1.1 204 No Content\\n(无响应体)' },
                    { code: 206, name: 'Partial Content', desc: '返回部分内容。配合Range请求头使用,实现断点续传和分块下载。', example: 'HTTP/1.1 206 Partial Content\\nContent-Range: bytes 0-1023/10240\\n\\n(部分数据)' }
                ]
            },
            '3xx': {
                name: '重定向状态码',
                codes: [
                    { code: 301, name: 'Moved Permanently', desc: '资源已永久移动到新URL。浏览器会缓存此重定向,SEO权重会转移到新URL。注意:301重定向可能将POST请求变为GET。', example: 'HTTP/1.1 301 Moved Permanently\\nLocation: https://new-domain.com/page' },
                    { code: 302, name: 'Found', desc: '资源临时移动到新URL。浏览器不会缓存此重定向。历史原因,302可能将POST变为GET。', example: 'HTTP/1.1 302 Found\\nLocation: /maintenance.html' },
                    { code: 304, name: 'Not Modified', desc: '资源未修改,使用缓存版本。不是重定向,而是缓存协商的结果。服务器不返回响应体。', example: 'HTTP/1.1 304 Not Modified\\nETag: "abc123"\\n(无响应体)' },
                    { code: 307, name: 'Temporary Redirect', desc: '临时重定向,保证保持原HTTP方法。POST请求重定向后仍然是POST。', example: 'HTTP/1.1 307 Temporary Redirect\\nLocation: /new-endpoint' },
                    { code: 308, name: 'Permanent Redirect', desc: '永久重定向,保证保持原HTTP方法。是301的改进版,POST重定向后仍然是POST。', example: 'HTTP/1.1 308 Permanent Redirect\\nLocation: https://new-api.example.com/users' }
                ]
            },
            '4xx': {
                name: '客户端错误状态码',
                codes: [
                    { code: 400, name: 'Bad Request', desc: '请求语法错误或参数无效。客户端应修改请求后重试。常用于参数验证失败的场景。', example: 'HTTP/1.1 400 Bad Request\\n\\n{"error":"参数验证失败","details":{"email":"邮箱格式不正确"}}' },
                    { code: 401, name: 'Unauthorized', desc: '未提供有效的身份认证凭据。响应应包含WWW-Authenticate头部。与403不同,401表示"未认证"。', example: 'HTTP/1.1 401 Unauthorized\\nWWW-Authenticate: Bearer realm="api"\\n\\n{"error":"Token已过期"}' },
                    { code: 403, name: 'Forbidden', desc: '已认证但没有权限访问该资源。即使重新认证也无法获得权限。与401不同,403表示"已认证但无权限"。', example: 'HTTP/1.1 403 Forbidden\\n\\n{"error":"您没有权限访问此资源"}' },
                    { code: 404, name: 'Not Found', desc: '请求的资源不存在。可能是URL错误或资源已被删除。是最常见的客户端错误码。', example: 'HTTP/1.1 404 Not Found\\n\\n{"error":"用户ID 999不存在"}' },
                    { code: 405, name: 'Method Not Allowed', desc: '请求的HTTP方法不被允许。响应应包含Allow头部,列出该资源支持的方法。', example: 'HTTP/1.1 405 Method Not Allowed\\nAllow: GET, POST\\n\\n{"error":"不支持DELETE方法"}' },
                    { code: 409, name: 'Conflict', desc: '请求与服务器当前状态冲突。常用于重复创建、版本冲突等场景。', example: 'HTTP/1.1 409 Conflict\\n\\n{"error":"用户名已存在","conflictField":"username"}' },
                    { code: 422, name: 'Unprocessable Entity', desc: '请求格式正确但语义错误,无法处理。常用于数据验证失败。与400不同,422表示语法正确但数据不合法。', example: 'HTTP/1.1 422 Unprocessable Entity\\n\\n{"error":"数据验证失败","errors":{"age":"年龄必须大于0"}}' },
                    { code: 429, name: 'Too Many Requests', desc: '请求频率超过限制。响应应包含Retry-After头部,告知客户端何时可以重试。', example: 'HTTP/1.1 429 Too Many Requests\\nRetry-After: 60\\n\\n{"error":"请求过于频繁,请60秒后重试"}' }
                ]
            },
            '5xx': {
                name: '服务器错误状态码',
                codes: [
                    { code: 500, name: 'Internal Server Error', desc: '服务器内部错误。是最通用的服务器错误状态码,表示服务器遇到了未预期的错误。', example: 'HTTP/1.1 500 Internal Server Error\\n\\n{"error":"服务器内部错误,请稍后重试"}' },
                    { code: 502, name: 'Bad Gateway', desc: '网关或代理服务器从上游服务器收到了无效响应。通常表示后端服务崩溃或返回了错误。', example: 'HTTP/1.1 502 Bad Gateway\\n\\n{"error":"上游服务不可用"}' },
                    { code: 503, name: 'Service Unavailable', desc: '服务器暂时无法处理请求。通常是因为服务器过载或正在维护。响应应包含Retry-After头部。', example: 'HTTP/1.1 503 Service Unavailable\\nRetry-After: 300\\n\\n{"error":"服务维护中,预计5分钟后恢复"}' },
                    { code: 504, name: 'Gateway Timeout', desc: '网关或代理服务器等待上游服务器响应超时。通常表示后端服务响应过慢。', example: 'HTTP/1.1 504 Gateway Timeout\\n\\n{"error":"上游服务响应超时"}' }
                ]
            }
        };

        function renderCodes(filter = '') {
            const container = document.getElementById('statusCodes');
            container.innerHTML = '';
            const lowerFilter = filter.toLowerCase();

            for (const [category, data] of Object.entries(statusCodes)) {
                const filteredCodes = data.codes.filter(c =>
                    !filter ||
                    c.code.toString().includes(filter) ||
                    c.name.toLowerCase().includes(lowerFilter) ||
                    c.desc.includes(filter)
                );

                if (filteredCodes.length === 0) continue;

                container.innerHTML += `
                    <div class="category-section">
                        <div class="category-header cat-${category}">
                            <span>${category}</span>
                            <span>${data.name}</span>
                        </div>
                        <div class="code-grid">
                            ${filteredCodes.map(c => `
                                <div class="code-card type-${category}" onclick="showDetail(${c.code})">
                                    <div class="code-number">${c.code}</div>
                                    <div class="code-name">${c.name}</div>
                                </div>
                            `).join('')}
                        </div>
                    </div>
                `;
            }
        }

        function showDetail(code) {
            for (const [category, data] of Object.entries(statusCodes)) {
                const found = data.codes.find(c => c.code === code);
                if (found) {
                    const colorClass = `type-${category}`;
                    document.getElementById('detailBody').innerHTML = `
                        <div class="detail-code ${colorClass}" style="color:${
                            category === '1xx' ? '#1565c0' :
                            category === '2xx' ? '#2e7d32' :
                            category === '3xx' ? '#ef6c00' :
                            category === '4xx' ? '#c62828' : '#b71c1c'
                        }">${found.code}</div>
                        <div class="detail-name">${found.name}</div>
                        <div class="detail-desc">${found.desc}</div>
                        <div class="detail-section">
                            <h4>示例</h4>
                            <div class="detail-code-block">${found.example}</div>
                        </div>
                    `;
                    document.getElementById('detailModal').classList.add('show');
                    break;
                }
            }
        }

        function closeDetail() {
            document.getElementById('detailModal').classList.remove('show');
        }

        document.getElementById('searchBox').addEventListener('input', (e) => {
            renderCodes(e.target.value);
        });

        document.getElementById('detailModal').addEventListener('click', (e) => {
            if (e.target === e.currentTarget) closeDetail();
        });

        renderCodes();
    </script>
</body>
</html>

示例2:API响应状态码处理器

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API响应状态码处理器</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: 'Segoe UI', system-ui, sans-serif;
            background: #f0f2f5;
            padding: 20px;
            color: #333;
        }
        .container { max-width: 900px; margin: 0 auto; }
        h1 { text-align: center; color: #1a73e8; margin-bottom: 24px; font-size: 28px; }
        .card {
            background: #fff;
            border-radius: 12px;
            padding: 24px;
            margin-bottom: 20px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.08);
        }
        .card h2 {
            font-size: 18px;
            color: #1a73e8;
            margin-bottom: 16px;
            padding-bottom: 8px;
            border-bottom: 2px solid #e8eaed;
        }
        .scenario-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 10px;
            margin-bottom: 20px;
        }
        .scenario-btn {
            padding: 14px;
            border: 2px solid #e8eaed;
            border-radius: 10px;
            background: #fff;
            cursor: pointer;
            text-align: center;
            transition: all 0.2s;
        }
        .scenario-btn:hover {
            border-color: #1a73e8;
            transform: translateY(-2px);
        }
        .scenario-btn.active {
            border-color: #1a73e8;
            background: #e3f2fd;
        }
        .scenario-code {
            font-size: 24px;
            font-weight: 800;
            margin-bottom: 4px;
        }
        .scenario-name { font-size: 13px; color: #666; }
        .response-area {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 16px;
        }
        .response-box {
            padding: 16px;
            border-radius: 8px;
            font-family: 'Consolas', monospace;
            font-size: 13px;
            line-height: 1.7;
        }
        .raw-response { background: #1e1e1e; color: #d4d4d4; }
        .processed-response { background: #f8f9fa; }
        .handler-code {
            background: #1e1e1e;
            color: #d4d4d4;
            padding: 16px;
            border-radius: 8px;
            font-family: 'Consolas', monospace;
            font-size: 13px;
            line-height: 1.7;
            margin-top: 16px;
            white-space: pre-wrap;
        }
        .status-indicator {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-weight: 700;
            font-size: 14px;
            margin-bottom: 12px;
        }
        .status-success { background: #e8f5e9; color: #2e7d32; }
        .status-redirect { background: #fff3e0; color: #ef6c00; }
        .status-client-error { background: #fce4ec; color: #c62828; }
        .status-server-error { background: #ffebee; color: #b71c1c; }
        .action-list {
            list-style: none;
            margin-top: 12px;
        }
        .action-list li {
            padding: 8px 12px;
            border-bottom: 1px solid #f0f0f0;
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 14px;
        }
        .action-icon {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 11px;
            flex-shrink: 0;
        }
        .action-check { background: #e8f5e9; color: #2e7d32; }
        .action-warn { background: #fff3e0; color: #ef6c00; }
        .action-error { background: #fce4ec; color: #c62828; }
    </style>
</head>
<body>
    <div class="container">
        <h1>API响应状态码处理器</h1>

        <div class="card">
            <h2>选择响应场景</h2>
            <div class="scenario-grid">
                <div class="scenario-btn" onclick="showScenario(200)">
                    <div class="scenario-code" style="color:#2e7d32">200</div>
                    <div class="scenario-name">GET 成功</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(201)">
                    <div class="scenario-code" style="color:#2e7d32">201</div>
                    <div class="scenario-name">POST 创建成功</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(304)">
                    <div class="scenario-code" style="color:#ef6c00">304</div>
                    <div class="scenario-name">缓存命中</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(400)">
                    <div class="scenario-code" style="color:#c62828">400</div>
                    <div class="scenario-name">参数错误</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(401)">
                    <div class="scenario-code" style="color:#c62828">401</div>
                    <div class="scenario-name">未认证</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(403)">
                    <div class="scenario-code" style="color:#c62828">403</div>
                    <div class="scenario-name">无权限</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(404)">
                    <div class="scenario-code" style="color:#c62828">404</div>
                    <div class="scenario-name">资源不存在</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(429)">
                    <div class="scenario-code" style="color:#c62828">429</div>
                    <div class="scenario-name">请求过多</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(500)">
                    <div class="scenario-code" style="color:#b71c1c">500</div>
                    <div class="scenario-name">服务器错误</div>
                </div>
                <div class="scenario-btn" onclick="showScenario(503)">
                    <div class="scenario-code" style="color:#b71c1c">503</div>
                    <div class="scenario-name">服务不可用</div>
                </div>
            </div>
        </div>

        <div id="resultArea"></div>
    </div>

    <script>
        const scenarios = {
            200: {
                raw: 'HTTP/1.1 200 OK\nContent-Type: application/json\nCache-Control: max-age=3600\n\n{"id":1,"name":"张三","email":"zhangsan@example.com"}',
                statusClass: 'status-success',
                statusText: '请求成功',
                actions: [
                    { type: 'check', text: '解析JSON响应体' },
                    { type: 'check', text: '更新UI显示数据' },
                    { type: 'check', text: '根据Cache-Control缓存响应' }
                ],
                handler: `async function handleResponse(response) {\n  const data = await response.json();\n  // 更新UI\n  updateUI(data);\n  // 缓存数据\n  if (response.headers.get('Cache-Control')) {\n    cacheData(response.url, data);\n  }\n  return data;\n}`
            },
            201: {
                raw: 'HTTP/1.1 201 Created\nLocation: /api/users/5\nContent-Type: application/json\n\n{"id":5,"name":"新用户","email":"new@example.com"}',
                statusClass: 'status-success',
                statusText: '资源创建成功',
                actions: [
                    { type: 'check', text: '解析JSON获取新资源数据' },
                    { type: 'check', text: '从Location头部获取新资源URI' },
                    { type: 'check', text: '更新列表或跳转到详情页' },
                    { type: 'check', text: '显示创建成功提示' }
                ],
                handler: `async function handleCreated(response) {\n  const data = await response.json();\n  const location = response.headers.get('Location');\n  // 显示成功提示\n  showToast('创建成功');\n  // 跳转或更新列表\n  if (location) navigateTo(location);\n  return data;\n}`
            },
            304: {
                raw: 'HTTP/1.1 304 Not Modified\nETag: "abc123"\nCache-Control: max-age=3600\n\n(无响应体)',
                statusClass: 'status-redirect',
                statusText: '缓存命中,使用本地缓存',
                actions: [
                    { type: 'check', text: '不解析响应体(无内容)' },
                    { type: 'check', text: '使用浏览器缓存的数据' },
                    { type: 'check', text: '更新ETag/Last-Modified缓存标识' }
                ],
                handler: `async function handleNotModified(response) {\n  // 304无响应体,使用缓存数据\n  const cachedData = getFromCache(response.url);\n  // 更新缓存标识\n  const etag = response.headers.get('ETag');\n  updateCacheHeaders(response.url, { etag });\n  return cachedData;\n}`
            },
            400: {
                raw: 'HTTP/1.1 400 Bad Request\nContent-Type: application/json\n\n{"error":"参数验证失败","details":{"email":"邮箱格式不正确","age":"年龄必须大于0"}}',
                statusClass: 'status-client-error',
                statusText: '请求参数错误',
                actions: [
                    { type: 'error', text: '解析错误详情' },
                    { type: 'error', text: '在表单对应字段显示错误信息' },
                    { type: 'warn', text: '不自动重试,需用户修正后重新提交' }
                ],
                handler: `async function handleBadRequest(response) {\n  const error = await response.json();\n  // 在表单字段旁显示错误\n  if (error.details) {\n    Object.entries(error.details).forEach(([field, msg]) => {\n      showFieldError(field, msg);\n    });\n  }\n  throw new Error(error.error);\n}`
            },
            401: {
                raw: 'HTTP/1.1 401 Unauthorized\nWWW-Authenticate: Bearer realm="api"\nContent-Type: application/json\n\n{"error":"Token已过期","code":"TOKEN_EXPIRED"}',
                statusClass: 'status-client-error',
                statusText: '未认证,需要登录',
                actions: [
                    { type: 'error', text: '清除本地存储的Token' },
                    { type: 'error', text: '尝试使用Refresh Token刷新' },
                    { type: 'warn', text: '刷新失败则跳转到登录页' }
                ],
                handler: `async function handleUnauthorized(response) {\n  const error = await response.json();\n  // 尝试刷新Token\n  const refreshed = await tryRefreshToken();\n  if (refreshed) {\n    // 重试原请求\n    return retryOriginalRequest();\n  }\n  // 跳转登录\n  clearAuth();\n  redirectToLogin();\n}`
            },
            403: {
                raw: 'HTTP/1.1 403 Forbidden\nContent-Type: application/json\n\n{"error":"您没有权限执行此操作","requiredRole":"admin"}',
                statusClass: 'status-client-error',
                statusText: '权限不足',
                actions: [
                    { type: 'error', text: '显示权限不足提示' },
                    { type: 'warn', text: '不自动重试,重新登录也无法解决' },
                    { type: 'warn', text: '可提供申请权限的入口' }
                ],
                handler: `async function handleForbidden(response) {\n  const error = await response.json();\n  // 显示权限不足提示\n  showForbiddenMessage(error.error);\n  // 不重试,即使重新认证也无法获得权限\n  throw new Error('权限不足');\n}`
            },
            404: {
                raw: 'HTTP/1.1 404 Not Found\nContent-Type: application/json\n\n{"error":"请求的资源不存在","resource":"User","id":999}',
                statusClass: 'status-client-error',
                statusText: '资源不存在',
                actions: [
                    { type: 'error', text: '显示"未找到"页面或提示' },
                    { type: 'warn', text: '不自动重试' },
                    { type: 'warn', text: '提供返回首页或列表的链接' }
                ],
                handler: `async function handleNotFound(response) {\n  const error = await response.json();\n  // 显示404页面或提示\n  showNotFoundMessage(error.error);\n  // 提供导航\n  showNavigationOptions({\n    back: true,\n    home: true\n  });\n}`
            },
            429: {
                raw: 'HTTP/1.1 429 Too Many Requests\nRetry-After: 60\nContent-Type: application/json\n\n{"error":"请求过于频繁","limit":"100次/分钟","retryAfter":60}',
                statusClass: 'status-client-error',
                statusText: '请求频率超限',
                actions: [
                    { type: 'warn', text: '读取Retry-After头部' },
                    { type: 'warn', text: '等待指定时间后自动重试' },
                    { type: 'warn', text: '显示倒计时提示用户' }
                ],
                handler: `async function handleTooManyRequests(response) {\n  const retryAfter = parseInt(\n    response.headers.get('Retry-After') || '60'\n  );\n  // 显示倒计时\n  showCountdown(retryAfter);\n  // 延迟后重试\n  await sleep(retryAfter * 1000);\n  return retryOriginalRequest();\n}`
            },
            500: {
                raw: 'HTTP/1.1 500 Internal Server Error\nContent-Type: application/json\n\n{"error":"服务器内部错误","requestId":"req-abc123"}',
                statusClass: 'status-server-error',
                statusText: '服务器内部错误',
                actions: [
                    { type: 'error', text: '显示友好的错误提示' },
                    { type: 'warn', text: '可自动重试1-2次' },
                    { type: 'warn', text: '记录requestId用于问题排查' },
                    { type: 'warn', text: '上报错误到监控系统' }
                ],
                handler: `async function handleServerError(response) {\n  const error = await response.json().catch(() => ({}));\n  // 上报错误\n  reportError({\n    url: response.url,\n    status: 500,\n    requestId: error.requestId\n  });\n  // 显示友好提示\n  showErrorMessage('服务器开小差了,请稍后重试');\n  throw new Error('服务器错误');\n}`
            },
            503: {
                raw: 'HTTP/1.1 503 Service Unavailable\nRetry-After: 300\nContent-Type: application/json\n\n{"error":"服务维护中","estimatedRecovery":"2026-04-22T12:00:00Z"}',
                statusClass: 'status-server-error',
                statusText: '服务暂时不可用',
                actions: [
                    { type: 'error', text: '显示维护通知页面' },
                    { type: 'warn', text: '根据Retry-After延迟重试' },
                    { type: 'warn', text: '显示预计恢复时间' }
                ],
                handler: `async function handleServiceUnavailable(response) {\n  const error = await response.json();\n  const retryAfter = response.headers.get('Retry-After');\n  // 显示维护页面\n  showMaintenancePage({\n    message: error.error,\n    estimatedRecovery: error.estimatedRecovery\n  });\n  // 后台定时重试\n  scheduleRetry(parseInt(retryAfter) * 1000);\n}`
            }
        };

        function showScenario(code) {
            document.querySelectorAll('.scenario-btn').forEach(b => b.classList.remove('active'));
            event.currentTarget.classList.add('active');

            const s = scenarios[code];
            document.getElementById('resultArea').innerHTML = `
                <div class="card">
                    <h2>响应处理方案</h2>
                    <span class="status-indicator ${s.statusClass}">${code} ${s.statusText}</span>
                    <div class="response-area">
                        <div>
                            <h4 style="margin-bottom:8px;color:#555;">原始响应</h4>
                            <div class="response-box raw-response">${s.raw}</div>
                        </div>
                        <div>
                            <h4 style="margin-bottom:8px;color:#555;">前端处理步骤</h4>
                            <ul class="action-list">
                                ${s.actions.map(a => `
                                    <li>
                                        <span class="action-icon action-${a.type}">${a.type === 'check' ? '' : a.type === 'warn' ? '!' : ''}</span>
                                        ${a.text}
                                    </li>
                                `).join('')}
                            </ul>
                        </div>
                    </div>
                    <h4 style="margin-top:20px;margin-bottom:8px;color:#555;">推荐处理代码</h4>
                    <div class="handler-code">${s.handler}</div>
                </div>
            `;
        }
    </script>
</body>
</html>

示例3:自定义错误页面设计

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义错误页面设计</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: 'Segoe UI', system-ui, sans-serif;
            background: #f0f2f5;
            padding: 20px;
            color: #333;
        }
        .container { max-width: 900px; margin: 0 auto; }
        h1 { text-align: center; color: #1a73e8; margin-bottom: 24px; font-size: 28px; }
        .tabs {
            display: flex;
            gap: 8px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        .tab-btn {
            padding: 10px 20px;
            border: 2px solid #dadce0;
            border-radius: 8px;
            background: #fff;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.2s;
        }
        .tab-btn.active { background: #1a73e8; color: #fff; border-color: #1a73e8; }
        .error-page {
            display: none;
            min-height: 400px;
            border-radius: 16px;
            overflow: hidden;
        }
        .error-page.active { display: block; }
        .ep-404 {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: #fff;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 60px 20px;
            text-align: center;
        }
        .ep-404 .error-code {
            font-size: 120px;
            font-weight: 900;
            line-height: 1;
            opacity: 0.3;
            margin-bottom: -30px;
        }
        .ep-404 h2 { font-size: 28px; margin-bottom: 12px; }
        .ep-404 p { font-size: 16px; opacity: 0.8; margin-bottom: 24px; max-width: 400px; }
        .ep-404 .search-box {
            display: flex;
            gap: 8px;
            margin-bottom: 20px;
        }
        .ep-404 input {
            padding: 12px 20px;
            border: none;
            border-radius: 8px;
            font-size: 15px;
            width: 280px;
        }
        .ep-404 button {
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            background: #fff;
            color: #764ba2;
            font-weight: 700;
            cursor: pointer;
        }
        .ep-404 .links { display: flex; gap: 16px; }
        .ep-404 .links a {
            color: #fff;
            text-decoration: underline;
            opacity: 0.8;
        }
        .ep-500 {
            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
            color: #fff;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 60px 20px;
            text-align: center;
        }
        .ep-500 .icon { font-size: 80px; margin-bottom: 20px; }
        .ep-500 h2 { font-size: 28px; margin-bottom: 12px; }
        .ep-500 p { font-size: 16px; opacity: 0.8; margin-bottom: 24px; max-width: 400px; }
        .ep-500 .retry-btn {
            padding: 14px 32px;
            border: 2px solid #fff;
            border-radius: 8px;
            background: transparent;
            color: #fff;
            font-weight: 700;
            font-size: 16px;
            cursor: pointer;
            transition: all 0.2s;
        }
        .ep-500 .retry-btn:hover { background: #fff; color: #f5576c; }
        .ep-403 {
            background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
            color: #333;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 60px 20px;
            text-align: center;
        }
        .ep-403 .lock-icon { font-size: 80px; margin-bottom: 20px; }
        .ep-403 h2 { font-size: 28px; margin-bottom: 12px; }
        .ep-403 p { font-size: 16px; opacity: 0.7; margin-bottom: 24px; max-width: 400px; }
        .ep-403 .contact-btn {
            padding: 14px 32px;
            border: none;
            border-radius: 8px;
            background: #333;
            color: #fff;
            font-weight: 700;
            font-size: 16px;
            cursor: pointer;
        }
        .ep-maintenance {
            background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%);
            color: #333;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 60px 20px;
            text-align: center;
        }
        .ep-maintenance .tool-icon { font-size: 80px; margin-bottom: 20px; }
        .ep-maintenance h2 { font-size: 28px; margin-bottom: 12px; }
        .ep-maintenance p { font-size: 16px; opacity: 0.7; margin-bottom: 8px; max-width: 400px; }
        .ep-maintenance .countdown {
            font-size: 32px;
            font-weight: 800;
            margin: 16px 0;
            color: #6a1b9a;
        }
        .ep-maintenance .progress-bar {
            width: 300px;
            height: 8px;
            background: rgba(0,0,0,0.1);
            border-radius: 4px;
            overflow: hidden;
            margin-top: 16px;
        }
        .ep-maintenance .progress-fill {
            height: 100%;
            background: #6a1b9a;
            border-radius: 4px;
            transition: width 1s;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>自定义错误页面设计</h1>

        <div class="tabs">
            <div class="tab-btn active" onclick="showPage('404')">404 未找到</div>
            <div class="tab-btn" onclick="showPage('500')">500 服务器错误</div>
            <div class="tab-btn" onclick="showPage('403')">403 禁止访问</div>
            <div class="tab-btn" onclick="showPage('503')">503 维护中</div>
        </div>

        <div class="error-page ep-404 active" id="page-404">
            <div class="error-code">404</div>
            <h2>页面走丢了</h2>
            <p>抱歉,您访问的页面不存在或已被移除。请检查URL是否正确,或尝试搜索您需要的内容。</p>
            <div class="search-box">
                <input type="text" placeholder="搜索内容...">
                <button>搜索</button>
            </div>
            <div class="links">
                <a href="#">返回首页</a>
                <a href="#">帮助中心</a>
                <a href="#">联系客服</a>
            </div>
        </div>

        <div class="error-page ep-500" id="page-500">
            <div class="icon">⚠</div>
            <h2>服务器开小差了</h2>
            <p>我们的服务器遇到了一些问题,技术团队正在紧急修复中。请稍后再试。</p>
            <button class="retry-btn" onclick="this.textContent='正在重试...';setTimeout(()=>this.textContent='重试',1500)">重试</button>
        </div>

        <div class="error-page ep-403" id="page-403">
            <div class="lock-icon">🔒</div>
            <h2>访问受限</h2>
            <p>您没有权限访问此页面。如果您认为这是一个错误,请联系管理员申请权限。</p>
            <button class="contact-btn">联系管理员</button>
        </div>

        <div class="error-page ep-maintenance" id="page-503">
            <div class="tool-icon">🔧</div>
            <h2>系统维护中</h2>
            <p>我们正在进行系统升级维护,预计恢复时间:</p>
            <div class="countdown" id="countdown">05:00</div>
            <div class="progress-bar">
                <div class="progress-fill" id="progressFill" style="width:60%"></div>
            </div>
        </div>
    </div>

    <script>
        function showPage(code) {
            document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
            document.querySelectorAll('.error-page').forEach(p => p.classList.remove('active'));
            event.currentTarget.classList.add('active');
            document.getElementById('page-' + code).classList.add('active');
        }

        // 倒计时
        let totalSeconds = 300;
        function updateCountdown() {
            const minutes = Math.floor(totalSeconds / 60).toString().padStart(2, '0');
            const seconds = (totalSeconds % 60).toString().padStart(2, '0');
            document.getElementById('countdown').textContent = `${minutes}:${seconds}`;
            const progress = ((300 - totalSeconds) / 300) * 100;
            document.getElementById('progressFill').style.width = progress + '%';
            if (totalSeconds > 0) totalSeconds--;
        }
        setInterval(updateCountdown, 1000);
    </script>
</body>
</html>

浏览器兼容性

特性 Chrome Firefox Safari Edge 说明
1xx状态码 全版本 全版本 全版本 全版本 浏览器自动处理
2xx状态码 全版本 全版本 全版本 全版本 正常处理
3xx重定向 全版本 全版本 全版本 全版本 浏览器自动跟随重定向
4xx/5xx 全版本 全版本 全版本 全版本 fetch不会reject
206 Partial 全版本 全版本 全版本 全版本 需要Range头部
103 Early Hints 93+ 不支持 不支持 93+ 较新特性
CORS预检 全版本 全版本 全版本 全版本 自动发送OPTIONS

注意事项与最佳实践

1. 状态码选择原则

  • 使用最具体的状态码,而非笼统的200或500

  • 201用于资源创建,204用于无内容成功

  • 401和403不要混用,401是未认证,403是无权限

  • 400用于语法错误,422用于语义/验证错误

2. 前端处理原则

  • fetch API不会因为4xx/5xx状态码而reject,必须手动检查response.okresponse.status

  • 为每种状态码提供用户友好的提示信息

  • 5xx错误可以自动重试,4xx错误不应自动重试

  • 401错误应触发Token刷新或登录跳转

3. 错误页面设计

  • 错误页面应保持与网站一致的视觉风格

  • 提供有用的导航选项(返回首页、搜索、联系客服)

  • 避免技术术语,使用用户易懂的语言

  • 503维护页面应显示预计恢复时间

4. API响应格式规范

代码示例

// 成功响应
{
    "status": "success",
    "data": { ... }
}

// 错误响应
{
    "status": "error",
    "error": {
        "code": "VALIDATION_ERROR",
        "message": "参数验证失败",
        "details": {
            "email": "邮箱格式不正确"
        }
    }
}

代码规范示例

统一的HTTP响应处理器

代码示例

class HttpResponseHandler {
    static async handle(response) {
        const status = response.status;

        // 2xx 成功
        if (status >= 200 && status < 300) {
            if (status === 204) return null;
            return await response.json();
        }

        // 304 未修改
        if (status === 304) {
            return { _cached: true };
        }

        // 解析错误响应体
        let errorData;
        try {
            errorData = await response.json();
        } catch {
            errorData = { message: `HTTP Error ${status}` };
        }

        // 401 未认证
        if (status === 401) {
            await this.handleUnauthorized();
            throw new UnauthorizedError(errorData);
        }

        // 403 无权限
        if (status === 403) {
            throw new ForbiddenError(errorData);
        }

        // 404 未找到
        if (status === 404) {
            throw new NotFoundError(errorData);
        }

        // 429 请求过多
        if (status === 429) {
            const retryAfter = response.headers.get('Retry-After');
            throw new RateLimitError(errorData, retryAfter);
        }

        // 4xx 客户端错误
        if (status >= 400 && status < 500) {
            throw new ClientError(status, errorData);
        }

        // 5xx 服务器错误
        throw new ServerError(status, errorData);
    }

    static async handleUnauthorized() {
        const refreshed = await refreshToken();
        if (!refreshed) {
            window.location.href = '/login';
        }
    }
}

常见问题与解决方案

问题1:fetch不因4xx/5xx状态码reject

问题描述:fetch API即使收到404或500状态码,Promise也不会reject,只有网络错误才会reject。

解决方案

代码示例

async function safeFetch(url, options) {
    const response = await fetch(url, options);
    if (!response.ok) {
        const error = await response.json().catch(() => ({}));
        throw new HttpError(response.status, error);
    }
    return response;
}

问题2:重定向导致POST变GET

问题描述:302重定向可能将POST请求变为GET请求,丢失请求体数据。

解决方案:使用307(临时)或308(永久)重定向,它们保证保持原HTTP方法。

问题3:401和403混淆使用

问题描述:很多API将权限不足也返回401,导致前端处理混乱。

解决方案

  • 401:未提供认证凭据或凭据无效 → 跳转登录

  • 403:已认证但权限不足 → 显示权限不足提示

问题4:500错误信息泄露

问题描述:500错误响应中包含堆栈跟踪等敏感信息。

解决方案:生产环境返回通用错误信息,详细信息只记录在服务器日志中:

代码示例

// 生产环境
{"error": "服务器内部错误", "requestId": "req-abc123"}

// 开发环境
{"error": "服务器内部错误", "stack": "...", "requestId": "req-abc123"}

总结

HTTP状态码是前后端通信的重要信号系统,正确理解和使用状态码对于构建健壮的Web应用至关重要:

  1. 1xx信息性:请求处理中的中间状态,如100 Continue和101 Switching Protocols

  2. 2xx成功:请求处理成功的各种情况,201创建、204无内容、206部分内容

  3. 3xx重定向:301/308永久重定向、302/307临时重定向、304缓存命中

  4. 4xx客户端错误:400参数错误、401未认证、403无权限、404未找到、429限流

  5. 5xx服务器错误:500内部错误、502网关错误、503服务不可用、504网关超时

前端开发者必须掌握的关键点:fetch不会因HTTP错误状态码reject、401与403的区别、重定向状态码对HTTP方法的影响、以及如何为每种状态码设计合适的用户提示和错误处理策略。

常见问题

fetch不因4xx/5xx状态码reject

请参考教程中的详细说明和代码示例。

重定向导致POST变GET

- 401:未提供认证凭据或凭据无效 → 跳转登录 - 403:已认证但权限不足 → 显示权限不足提示

什么是HTTP状态码?

HTTP状态码是HTML5开发中的重要技术,本教程详细介绍了其核心概念和实践方法。

如何学习HTTP状态码的实际应用?

教程中提供了完整的代码示例和实践指导,建议结合示例代码动手练习。

HTTP状态码有哪些注意事项?

常见注意事项包括兼容性、性能优化等,教程的注意事项与最佳实践部分有详细说明。

HTTP状态码适合初学者吗?

本教程从基础概念讲起,循序渐进,适合有一定HTML和JavaScript基础的初学者。

HTTP状态码的核心要点是什么?

核心要点包括教程简介等内容,建议按教程顺序逐步学习。

标签: Promise HTTP头部 表单提交 OAuth 响应码 async await 场景管理 JWT

本文由小确幸生活整理发布,转载请注明出处

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: 后端通信:HTTP请求方法 - 从入门到实践详解 下一篇: 后端通信:HTTP头部详解 - 从入门到实践详解

poll相关推荐