1. HTTP #

1.1 请求 #

1.1.1 请求行 #

<method> <request-URI> <version>

1.1.2 请求头 #

请求头 描述
Accept 该头部告诉服务器,客户端可以处理的媒体类型,如text/htmlapplication/json等。
Content-Type 该头部在POST和PUT请求中使用,告诉服务器请求体的媒体类型。常见的值包括application/x-www-form-urlencodedmultipart/form-dataapplication/json等。
User-Agent 该头部包含了关于发起请求的用户代理(通常是浏览器)的信息。
Authorization 该头部用于传递身份验证凭据。
Cookie 该头部携带了由服务器设置的cookie,服务器可以使用它们来识别和跟踪用户。
Referer 该头部指示发起请求的页面的URL,这可以帮助服务器了解哪些页面在链接到其资源。
X-Requested-With 这是一个自定义的HTTP头,最常用于识别Ajax请求。例如,某些框架(如jQuery)会自动添加X-Requested-With: XMLHttpRequest头。

1.1.3 请求体 #

name=zhufeng&age=18
{
  "name": "zhufeng",
  "age": 18
}
POST /upload HTTP/1.1
Host: localhost
Content-Type: multipart/form-data;boundary="boundary"

--boundary
Content-Disposition: form-data; name="field1"

value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"
Content-Type: text/plain

Hello, World!
--boundary--

在HTTP GET请求中,通常没有请求体,因为GET请求用于获取资源,而不是发送数据。数据通常以查询参数(query parameters)的形式附加在URL中

1.2 响应 #

1.2.1 响应行 #

HTTP/1.1 200 OK

状态码

状态码类别 描述
1xx 信息响应:请求已收到,继续处理。
2xx 成功:请求已被服务器接收、理解、并接受。
3xx 重定向:需要进一步的操作以完成请求。通常这些状态码用于URI已经改变的情况。
4xx 客户端错误:请求包含语法错误或无法完成请求。通常这些状态码用于服务器无法完成明显无效的请求。
5xx 服务器错误:服务器在处理请求的过程中发生错误。通常这些状态码用于所有其他错误情况。
状态码 名称 描述
200 OK 请求成功。这通常是对成功GET和PUT请求的响应。
201 Created 请求成功,并创建了新的资源,通常是对POST请求的响应。
204 No Content 请求成功,但没有要返回的表示,通常用于DELETE和PUT请求。
301 Moved Permanently 被请求的资源已永久移动到新位置,并提供了新的URL。
302 Found 被请求的资源临时从不同的URI响应请求。
400 Bad Request 请求无法被服务器理解,由于客户端语法错误。
401 Unauthorized 请求需要用户验证。
403 Forbidden 服务器理解请求,但是拒绝执行它。
404 Not Found 请求的资源在服务器上没有找到。
500 Internal Server Error 服务器遇到了一个未知的错误。
503 Service Unavailable 服务器暂时无法处理请求,通常这是因为过载或维护。

1.2.2 响应头 #

响应头 描述
Content-Type 指定了响应体的媒体类型,如 text/htmlapplication/json等。
Content-Length 指定了响应体的字节数。这可以让客户端知道何时读取完整的响应体。
Set-Cookie 用于向客户端设置cookie。服务器可以使用cookie来识别和跟踪用户。
Cache-Control 指定了缓存策略,告诉客户端是否以及如何缓存响应。
Location 当服务器发送重定向响应(如 301 或 302)时,Location 头指定了重定向的位置。
Server 描述了响应服务器的软件或者版本信息。
WWW-Authenticate 用于401响应,指示客户端如何进行身份验证。
Access-Control-Allow-Origin 用于指定哪些域可以访问资源,用于CORS(跨源资源共享)策略。

1.2.3 响应体 #

2. 请求响应演示 #

2.1 HTTP服务器 #

// 引入所需的模块
const http = require('http');
const url = require('url');
const fs = require('fs');
const path = require('path');
// 创建用户列表
let users = [];
// 创建HTTP服务器并定义请求处理逻辑
const server = http.createServer(async (req, res) => {
  // 解析请求URL
  const parsedUrl = url.parse(req.url, true);
  const { pathname } = parsedUrl;
  const { id } = parsedUrl.query;
  // 判断请求路径并处理
  if (pathname === '/') {
    // 如果请求根路径,返回'hello world'
    res.end('hello world');
  } else if (pathname === '/users') {
    // 如果请求用户列表,根据请求方法进行处理
    switch (req.method) {
      case 'POST':
        // 如果是POST请求,创建新用户并添加到列表
        const newUser = await getRequestBody(req);
        newUser.id = users.length + 1;
        users.push(newUser);
        res.end('用户创建成功');
        break;
      case 'DELETE':
        // 如果是DELETE请求,从用户列表中移除指定的用户
        if (id) {
          users = users.filter(user => user.id !== parseInt(id));
          res.end('用户删除成功');
        }
        break;
      case 'PUT':
        // 如果是PUT请求,更新用户列表中的指定用户信息
        if (id) {
          const updateUser = await getRequestBody(req);
          users = users.map(user => user.id === parseInt(id) ? {
            ...user,
            ...updateUser
          } : user);
          res.end('用户更新成功');
        }
        break;
      case 'GET':
        // 如果是GET请求,返回指定的用户信息或整个用户列表
        if (id) {
          const user = users.find(user => user.id === parseInt(id));
          res.end(JSON.stringify(user));
        } else {
          res.end(JSON.stringify(users));
        }
        break;
      default:
        // 如果请求方法不被支持,返回错误信息
        res.end('很抱歉,暂时不支持该请求方法');
        break;
    }
  } else {
    // 如果请求其他路径,尝试作为文件路径处理并返回文件内容
    const ext = path.extname(pathname);
    const filePath = path.join(__dirname, pathname);
    if (ext === '.html' || ext === '.js' || ext === '.css') {
      // 如果是html、js或css文件,尝试读取并返回
      fs.readFile(filePath, 'utf8', (err, data) => {
        if (err) {
          // 如果文件不存在,返回404错误
          res.statusCode = 404;
          res.end('Not found');
        } else {
          // 如果文件存在,设置正确的Content-Type并返回文件内容
          res.setHeader('Content-Type', getContentType(ext));
          res.end(data);
        }
      });
    } else {
      // 如果路径不是文件路径或用户列表,返回错误信息
      res.end('Invalid path');
    }
  }
});
// 根据文件扩展名返回对应的Content-Type
function getContentType(ext) {
  switch (ext) {
    case '.html':
      return 'text/html';
    case '.js':
      return 'text/javascript';
    case '.css':
      return 'text/css';
    default:
      // 当无匹配扩展名时,返回通用的类型
      return 'text/plain';
  }
}
// 处理请求体,解析为JSON对象
function getRequestBody(req) {
  return new Promise(resolve => {
    // 初始化请求体字符串
    let body = '';
    req.on('data', chunk => {
      // 当有数据到来时,添加到请求体字符串
      body += chunk;
    });
    req.on('end', () => {
      // 当所有数据接收完毕,解析为JSON并返回
      resolve(JSON.parse(body));
    });
  });
}
// 启动服务器并监听3000端口
server.listen(3000, () => console.log(`Server is listening on port 3000`));

2.2 HTTP客户端 #

2.2.1 curl #

2.2.2 创建一个新用户(POST请求) #

curl -v -X POST -H "Content-Type: application/json" -d '{"name":"zhu","age":16}' http://localhost:3000/users

2.2.3 更新用户信息(PUT请求) #

curl -v  -X PUT -H "Content-Type: application/json" -d '{"name":"feng","age":17}' http://localhost:3000/users?id=1

2.2.4 查询用户信息(GET请求) #

curl -v  -X GET http://localhost:3000/users?id=1

2.2.5 删除用户(DELETE请求) #

curl -v  -X DELETE http://localhost:3000/users?id=1

3.1 工作流程 #

const http = require('http');
const server = http.createServer((req, res) => {
  // 读取cookie
  let cookies = req.headers['cookie'];
  console.log('Cookies: ', cookies);
  // 设置cookie
  res.setHeader('Set-Cookie', ['id=1', 'age=18']);
  res.statusCode = 200;
  res.end('hello');
});
server.listen(3000, () => console.log(`Server is listening on port 3000`));