网络请求相关知识

101 阅读6分钟

HTTP协议基础

HTTP(HyperText Transfer Protocol)是用于传输超文本的应用层协议,它是万维网数据通信的基础。HTTP协议基于TCP/IP协议,默认端口为80(HTTPS为443)。

HTTP工作原理

  1. 客户端(通常是浏览器)向服务器发送HTTP请求
  2. 服务器接收请求并处理
  3. 服务器返回HTTP响应
  4. 客户端接收响应并处理

常见的HTTP请求方法

方法描述
GET请求指定的资源,只用于获取数据
POST向指定资源提交数据,通常会导致服务器状态变化
PUT替换目标资源的所有当前表示
DELETE删除指定的资源
HEAD类似于GET请求,但只返回响应头,不返回响应体
PATCH对资源进行部分修改
OPTIONS返回服务器支持的HTTP方法
CONNECT建立到目标资源的隧道
TRACE回显服务器收到的请求,主要用于测试或诊断

HTTP请求结构

一个典型的HTTP请求包含以下部分:

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
  • 请求行:方法 + URL + HTTP版本
  • 请求头:多个键值对
  • 空行
  • 请求体(可选)

HTTP响应结构

一个典型的HTTP响应包含以下部分:

HTTP/1.1 200 OK
Date: Mon, 23 May 2022 22:38:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 138
Last-Modified: Wed, 08 Jan 2022 23:11:55 GMT
Server: Apache/2.4.1 (Unix)

<html>
  <head>
    <title>Example Page</title>
  </head>
  <body>
    <p>Hello World!</p>
  </body>
</html>
  • 状态行:HTTP版本 + 状态码 + 状态消息
  • 响应头:多个键值对
  • 空行
  • 响应体

常见的HTTP请求头

请求头描述
Accept客户端能够接收的内容类型
Accept-Charset客户端能够显示的字符集
Accept-Encoding客户端能够处理的编码方式
Accept-Language客户端期望的语言
Authorization认证信息
Cache-Control缓存机制
Connection连接方式(keep-alive等)
Content-Length请求体的长度
Content-Type请求体的MIME类型
Cookie客户端cookie
Host请求的服务器域名和端口号
Referer请求来源页面的URL
User-Agent客户端信息(浏览器类型、版本等)
If-Modified-Since资源修改时间比对
If-None-MatchETag比对

常见的HTTP响应头

响应头描述
Access-Control-Allow-Origin指定哪些网站可以跨域资源共享
Cache-Control缓存机制
Content-Encoding响应体的编码方式
Content-Length响应体的长度
Content-Type响应体的MIME类型
Date响应生成的日期和时间
ETag资源的特定版本标识符
Expires响应过期时间
Last-Modified资源最后修改时间
Location重定向目标URL
Server服务器信息
Set-Cookie设置HTTP Cookie
StatusHTTP状态码

HTTP状态码

HTTP状态码分为5类:

1xx 信息性状态码

  • 100 Continue:客户端应继续请求
  • 101 Switching Protocols:服务器同意切换协议

2xx 成功状态码

  • 200 OK:请求成功
  • 201 Created:资源创建成功
  • 202 Accepted:请求已接受但未处理完成
  • 204 No Content:请求成功但无内容返回

3xx 重定向状态码

  • 301 Moved Permanently:资源永久移动
  • 302 Found:资源临时移动
  • 304 Not Modified:资源未修改(使用缓存)

4xx 客户端错误状态码

  • 400 Bad Request:请求语法错误
  • 401 Unauthorized:需要认证
  • 403 Forbidden:服务器拒绝请求
  • 404 Not Found:资源不存在
  • 405 Method Not Allowed:请求方法不被允许

5xx 服务器错误状态码

  • 500 Internal Server Error:服务器内部错误
  • 502 Bad Gateway:网关错误
  • 503 Service Unavailable:服务不可用
  • 504 Gateway Timeout:网关超时

XMLHttpRequest (XHR)

XHR是浏览器提供的API,用于在后台与服务器交换数据。

基本用法

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseText);
  }
};
xhr.send();

readyState值

  • 0: 未初始化(未调用open)
  • 1: 已打开(已调用open)
  • 2: 已发送(已调用send)
  • 3: 接收中(已接收部分响应)
  • 4: 完成(全部响应接收完毕)

简易封装AJAX

function ajax(options) {
  const { url, method = 'GET', data = null, headers = {}, success, error } = options;
  
  const xhr = new XMLHttpRequest();
  xhr.open(method, url, true);
  
  // 设置请求头
  for (const key in headers) {
    xhr.setRequestHeader(key, headers[key]);
  }
  
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        success && success(xhr.responseText);
      } else {
        error && error(xhr.status, xhr.statusText);
      }
    }
  };
  
  xhr.onerror = function() {
    error && error(xhr.status, xhr.statusText);
  };
  
  xhr.send(data);
}

// 使用示例
ajax({
  url: 'https://api.example.com/data',
  method: 'POST',
  data: JSON.stringify({ key: 'value' }),
  headers: {
    'Content-Type': 'application/json'
  },
  success: function(response) {
    console.log('Success:', response);
  },
  error: function(status, statusText) {
    console.error('Error:', status, statusText);
  }
});

Fetch API

Fetch是现代浏览器提供的更简洁的API,基于Promise。

基本用法

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

带选项的Fetch

fetch('https://api.example.com/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token'
  },
  body: JSON.stringify({ key: 'value' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

响应类型及数据

响应类型

可以通过response.type获取:

  • basic: 同源请求
  • cors: 跨域请求
  • opaque: 对非同源资源的请求,且服务器未返回CORS头
  • opaqueredirect: 重定向响应

数据处理方法

  • response.text(): 获取文本
  • response.json(): 获取JSON对象
  • response.blob(): 获取Blob对象
  • response.arrayBuffer(): 获取ArrayBuffer
  • response.formData(): 获取FormData对象

服务器接收数据类型

服务器通常通过Content-Type头识别客户端发送的数据类型:

  1. application/x-www-form-urlencoded: 表单默认编码

    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: 'key1=value1&key2=value2'
    });
    
  2. multipart/form-data: 用于文件上传

    const formData = new FormData();
    formData.append('file', fileInput.files[0]);
    formData.append('username', 'user1');
    
    fetch(url, {
      method: 'POST',
      body: formData
    });
    
  3. application/json: JSON数据

    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'value' })
    });
    
  4. text/plain: 纯文本

  5. application/xml: XML数据

服务器返回数据类型

服务器通过Content-Type响应头指定返回数据类型:

  1. text/html: HTML文档
  2. text/plain: 纯文本
  3. application/json: JSON数据
  4. application/xml: XML数据
  5. image/jpeg, image/png: 图片
  6. application/pdf: PDF文档
  7. application/octet-stream: 二进制流数据(文件下载)

跨域资源共享 (CORS)

当请求不同源的资源时,浏览器会实施同源策略限制。CORS机制允许服务器声明哪些源可以访问资源。

简单请求

满足以下条件的请求:

  • 方法为GET、HEAD或POST
  • 有限的头(Accept, Accept-Language, Content-Language, Content-Type等)
  • Content-Type为application/x-www-form-urlencoded, multipart/form-datatext/plain

预检请求 (Preflight)

不满足简单请求条件的请求会先发送OPTIONS请求进行预检。

CORS相关头

  • Access-Control-Allow-Origin: 允许的源
  • Access-Control-Allow-Methods: 允许的方法
  • Access-Control-Allow-Headers: 允许的头
  • Access-Control-Allow-Credentials: 是否允许发送凭据
  • Access-Control-Max-Age: 预检请求缓存时间

WebSocket

WebSocket提供了全双工通信机制,适合实时应用。

const socket = new WebSocket('wss://example.com/socket');

socket.onopen = function(e) {
  console.log('Connection established');
  socket.send('Hello Server!');
};

socket.onmessage = function(event) {
  console.log('Message from server:', event.data);
};

socket.onclose = function(event) {
  if (event.wasClean) {
    console.log('Connection closed cleanly');
  } else {
    console.log('Connection died');
  }
};

socket.onerror = function(error) {
  console.log('Error:', error.message);
};