请求响应原理及HTTP协议,请求报文与响应报文

2021-06-28  本文已影响0人  AizawaSayo

一、服务器端基础概念

1.1 网站的组成

网站应用程序主要分为两大部分:客户端和服务器端。
客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序。使用HTML、CSS、JavaScript构建。
服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑。

1.2 Node网站服务器

能够提供网站访问服务的机器就是网站服务器,它能够接收客户端的请求,能够对请求做出响应
一台电脑需要安装Node代码运行环境,使用Nodejs创建一个能接收对象和响应请求的对象,就是Node网站服务器(可以没有显示器鼠标键盘,只有一个主机)
电脑 ➡️ Node ➡️ 响应请求的对象

1.3 IP地址

互联网中设备的唯一标识。
IP是Internet Protocol Address的简写,代表互联网协议地址

1.4 域名

由于IP地址难于记忆,所以我们一般不会使用IP地址直接访问网站。于是产生了域名的概念,所谓域名就是平时上网所使用的网址
http://www.hellocode.com => http://136.168.215.101/
虽然在地址栏中输入的是网址, 但是最终还是会将域名转换为ip才能访问到指定的网站服务器。

1.5 端口

端口是计算机与外界通讯交流的出口,用来区分服务器电脑中提供的不同的服务。(比如web server和email server)

1.6 URL

统一资源定位符,又叫URL(Uniform Resource Locator),是专为标识Internet网上资源位置而设的一种编址方式,我们平时所说的网页地址指的即是URL。
URL的组成
传输协议://服务器IP或域名:端口/资源所在位置标识
https://localhost:8080/news/789.html

PS:TLS是传输层加密协议,前身是SSL协议,由网景公司1995年发布,有时候两者不区分。

1.7 开发过程中客户端和服务器端说明

在开发阶段,客户端和服务器端使用同一台电脑,即开发人员电脑。
客户端:浏览器
服务器端:Node.js
本地域名:localhost
本地IP:127.0.0.1

二、创建Web服务器

// 用于创建网站服务器的模块
const http = require('http');
// 用于处理url地址
const url = require('url');
// app对象就是网站服务器对象
const app = http.createServer();
// 当客户端有请求来的时候
app.on('request', (req, res) => {//req是请求对象 res是响应对象
  // 获取请求方式
  // req.method
  console.log(req.method);
    
  // 获取请求地址
  // req.url
  console.log(req.url);
    
  // 获取请求报文信息
  // req.headers
  console.log(req.headers['accept']);
    
  res.writeHead(200, {
    'content-type': 'text/html;charset=utf8'
  });

  console.log(req.url);
  // 1) 要解析的url地址
  // 2) 将查询参数解析成对象形式
  let { query, pathname } = url.parse(req.url, true);
  console.log(query.name)
  console.log(query.age)

  if (pathname == '/index' || pathname == '/') {
    res.end('<h2>欢迎来到首页</h2>');
  }else if (pathname == '/list') {
    res.end('welcome to listpage');
  }else {
    res.end('not found');
  }
    
  if (req.method == 'POST') {
    res.end('post')
  } else if (req.method == 'GET') {
    res.end('get')
  }

  // res.end('<h2>hello user</h2>');
});
// 监听端口
app.listen(3000);
console.log('网站服务器启动成功');

三、HTTP协议

超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准。

3.1 报文

在 HTTP 请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式(键值对形式)。

请求报文:

请求行(request line)、请求头(header)、空行请求体(body,可选的、包含数据) 组成。一次 HTTP 请求会按顺序依次发送以上四个部分 (get 请求没有请求体)。

我们用谷歌浏览器来对照着查看:

依次点击找到请求报文 点击 View source 请求报文的一般格式

以下列举部分常见属性:

请求头参数 描述
Host 目标服务器的主机名 (ip 地址或域名)
User-Agent 发起请求的客户端应用程序相关信息,如操作系统、浏览器等信息
Referer 当前文档的完整 URL
Accept (Accept) 指定客户端能接收哪些响应信息类型,如:image/jpg, text/html,专业术语称为MIME Type
Accept-Charset (Accept) 指定客户端支持哪些字符集,如 gb2312
Accept-Encoding (Accept) 指定客户端支持接收的内容编码(数据压缩)方式,如 gzip, deflate
Accept-Language (Accept) 指定客户端接受那些语言,如 zh-CN
Authorization (安全相关) 客户端提供给服务端进行权限认证的信息
Cookie (安全相关) 客户端携带的 cookie 信息(通常会存储一个sessionID,通过这个令牌让服务端鉴权)
Content-Type (响应头通用) 内容类型,请求的与实体对应的MIME信息。如果是 post 请求,会有这个参数,默认值为 application/x-www-form-urlencoded,表示请求体内容使用 url 编码
Content-Length (响应头通用) 请求体数据长度
Connection (响应头通用) 指定客户端和服务器之间请求/响应连接的类型,如:Keep-Alive 表示保持 TCP 持久连接
Transfer-Encodeing (响应头通用) 告知接收端为了报文的可靠传输,对报文使用什么样的编码格式
Cache-Control (响应头通用-缓存相关) 指定请求和响应遵循的缓存机制
If-Modified-Since (缓存相关) 服务器会用该值与所请求资源的最后修改时间作对比,如相同返回304和空响应体(节省带宽),告诉客户端资源未修改可直接读取客户端缓存;不同则返回200和最新的资源。值是上一次请求该资源时响应头的 Last-Modified
If-None-Match (缓存相关) 服务器会用该值与所请求资源的 ETag 作比较,匹配会返回304告诉客户端直接使用本地缓存即可;不一致则返回200和新资源(还有新 ETag)。同时存在时,优先级高于 If-Modified-Since

Node 访问请求方法(method)、 请求地址(url) 和 请求头(headers)

const http = require('http');
const app = http.createServer();

app.on('request',(req, res) => {
  // 获取请求方式、请求地址 和请求头
  const { method, url, headers } = req;
  // 获取请求头某个属性信息
  const userAgent = headers['user-agent'];
})
响应报文:

状态行响应头空行响应体(数据) 组成。服务器响应时,会按顺序依次发送以上四个部分。

状态码 描述
1xx 提示信息,服务器收到请求,需要请求者继续执行操作
2xx 成功,请求被成功接收并处理 200
3xx 重定向相关 304--所请求的资源未修改,客户端会直接访问这个资源的缓存,不会返回任何资源
4xx 客户端错误 404--请求的资源没有被找到 400-客户端请求存在语法错误
5xx 服务端错误,500--服务器在处理请求的过程中发生了错误 502/504--充当网关或代理的服务器,从远端服务器接收到了一个无效的请求/未及时从远端服务器获取请求

以下列举部分:
(部分通用属性已经在上面请求头部分列出,不再重复)

响应头参数 描述
Server 服务器软件名,如 Tengine
Content-Encoding 对主体执行的编码方式
Content-Type 响应主体的内容类型和字符集
Location 告知客户端实体实际上位于何处;用于重定向
Set-Cookie (安全相关) 设置和页面关联的Cookie
Proxy-Authenticate (安全相关) 来自代理服务器的质询列表
Vary (协商相关) 一个列表,内容来自于当前请求头的Key,比如Accept-Encoding、User-Agent等,用于发生相同请求的时候决定某个缓存的响应版本是否可以用来发给客户端
ETag (缓存相关) 实体标记。服务端当前资源实体特定版本的唯一标识符,只要资源有变化就会重新生成。下一次请求该资源时会将这个值放入请求头的 If-None-Match 来和服务端的 ETag 作比较。
Expires (缓存相关) 资源缓存过期时间。即客户端在这个时间前获取此资源都直接读取本地缓存,而不再向服务器请求,作用是控制请求的频率。Expires是http1.0的产物,已经被http1.1的 Cache-Control: max-age 替代,仍然存在是为了兼容性
Last-Modified (缓存相关) 这个实体最后一次被修改的时间。与请求头的 If-Modified-Since 配合使用

Vary

  1. Vary的内容来自于当前请求的请求头的Key,如Accept-Encoding、User-Agent等
  2. 缓存服务器进行某接口的请求结果数据缓存时,会将Vary一起缓存;
  3. 服务器缓存的Vary的内容会作为当前缓存数据是否可以作为请求结果返回给客户端的判断依据;
  4. 先通过响应数据中的Vary来判断当前缓存中同请求的数据的Vary是否失效,如果缓存中的Vary与服务器刚拿到的Vary不一致,则可以进行更新。
  5. 当Vary的值为“*”,意味着请求头中的所有信息都不可作为是否从缓存服务器拿数据的判断依据。

Content-Type
响应的内容类型,告知客户端你发送的数据内容类型,浏览器应以什么形式、什么编码读取这个文件(否则可能解析错误而出现乱码)。
文件类型有:text/plain(纯文本)-对应.txt、text/html-对应.html、text/css-对应.css、application/javascript-对应.js、image/jpeg-对应.jpg或.jpeg、image/png-对应.png、application/json-对应.json

res.writeHead(200,{
  'content-type':'application/json; charset=utf-8' 
})

3.2 请求参数

客户端向服务器端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如登录操作。

1. GET 请求参数

参数被放置在浏览器地址栏中,例如:http://localhost:3000/abc/xyz?name=zhangsan&age=20

// 系统模块 url 用来处理 url 地址
const url = require('url')

app.on('request', (req, res) => {
  // `url.parse(req.url)` 将 url 路径的各个部分解析出来并返回对象
  // 第二个参数 true表示把查询参数 (url对象的query属性值) 解析成对象格式
  let { query, pathname } = url.parse(req.url, true); // 解构赋值获取查询参数 query
  console.log(query.name) // zhangsan
  console.log(query.age) // 20
  console.log(pathname) // /abc/xyz
}
2. POST 请求参数
// 导入系统模块querystring 用于将HTTP参数转换为对象格式
const querystring = require('querystring');
app.on('request', (req, res) => {
  let postData = '';
  // 监听参数传输事件
  req.on('data', (chunk) => postData += chunk;);
  // 监听参数传输完毕事件
  req.on('end', () => { 
    console.log(postData);// 字符串
    console.log(querystring.parse(postData));  //把接收到参数字符串转化为对象
  }); 
  res.end('ok');
});

3.2 路由

http://localhost:3000/index
http://localhost:3000/login
路由是指客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么。

// 当客户端发来请求的时候
app.on('request', (req, res) => {
  // 获取请求方式
  const method = req.method.toLowerCase();
  // 获取客户端的请求路径
  // const pathname = url.parse(req.url).pathname;
  let { pathname } = url.parse(req.url);
  if (pathname == '/' || pathname == '/index') {
    res.end('欢迎来到首页');
  } else if (pathname == '/list') {
    res.end('欢迎来到列表页页');
  } else {
    res.end('抱歉, 您访问的页面出游了');
  }
});

3.3 静态资源

服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如 CSS、JavaScript、image文件。
举例:http://localhost:8080/images/logo.png

3.4 动态资源

相同的请求地址不同的响应资源,这种资源就是动态资源。
http://localhost:8080/article?id=123
http://localhost:8080/article?id=456

3.5 客户端请求途径

  1. GET 方式
  1. POST 方式
上一篇下一篇

猜你喜欢

热点阅读