【HTTP】请求和响应

277 阅读8分钟

一、请求与响应模型

  • 服务器(server)是个没有显示器的电脑,拥有一个IP地址和端口。
  • 客户端(浏览器)也拥有一个IP地址。
  • 客户端会发送一个请求给服务器的IP地址的一个端口上,而服务器接收到请求后会在同一端口把响应返回到客户端的IP地址上去。

二、体系化学习HTTP

  1. 必须学会
  • 基础概念:请求+响应
  • 如何调试(用的是Node.js,可以用log / debugger)
  • 在哪查资料(用的是Node.js,看Node.js文档)
  • 标准制定者(HTTP 规格文档: RFC 2612等)
  1. 如何学
  • Copy-抄文档、抄老师
  • Run-放在自己的机器上运行成功
  • Modify-加入一点自己的想法,然后重新运行

三、基础概念

(一)请求Request

1、请求的构成

①请求行Request-Line

请求动词 路径加查询参数 协议名/版本

  • 例如GET / HTTP/1.1
  • 如果路径加查询参数未写,就会自动补上根路径/
  • 请求动词有GET(获取内容)/POST(上传内容)/PUT/PATCH/DELETE等

②请求头Requset Header

  • Host:请求的域名或者IP+端口号
  • Accept:text/html ——告诉服务器我想要的文本类型
  • User-Agent:用户代理,帮你发请求的工具,可以为Chrome或者curl
  • Content-Type:请求体的格式
  • referer:发请求的url

③回车——隔开请求头和请求体

④请求体Request Body

  • 请求体为上面Content-Type的规定的格式的任意内容
  • 请求体在GET请求中一般为空
  • 请求体在POST请求中为上传内容

2、如何发送请求(都是用url,请求的都是url,就算你就写了个域名,也会自动补成url)

(1)用Chrome地址栏发请求

(2)用curl发送请求curl URL

例如curl -v http://127.0.0.1:8888

  1. 设置请求动词
  • 默认是GET
  • 改成POST:添加-X POST(注意大写)
  • 例如 curl -v -X POST http://127.0.0.1:8888
  1. 设置路径和查询参数
  • 直接在url后面加
  • 例如curl -v -X POST http://127.0.0.1:8888/xxxx?wd=hi
  1. 设置请求头
  • -H 'Name: Value'或者--header 'Name: Value'
  • 例如curl -v -H 'Accept: text/html' http://127.0.0.1:8888我想要HTML
  1. 设置请求体
  • -d '内容'或者--data '内容'
  • curl -v -H 'Content-Type: text/plain;charset=utf-8' -d '请求体内容' http://127.0.0.1:8888我要上传的内容是纯文本,上传的内容为“请求体内容”

3、如何查看或读取请求

(1)用Chrome开发者工具查看请求的信息

开发者工具 → Network → 点击要查看的请求 → Headers → Requset Header → view source

(2)用curl发请求时就可看到请求信息

(3)用Node.js读取请求的所有信息

  1. 读取请求动词
console.log("method:");
console.log(method);
  1. 读取路径
  • request.url路径,带查询参数
  • path纯路径,不带查询参数
  • query只有查询参数
console.log("请求路径(带查询参数):");
console.log(pathWithQuery);
  1. 读取请求头
console.log("request.headers");
console.log(request.headers);

request.headers['Accept']

  1. 读取请求体

比较复杂,先不讲

(二)响应

1.响应的构成

①状态行

协议名/版本 状态码 状态字符串

  • 状态码:200表示请求的路径服务器是知道的;404表示请求的路径服务器不知道

②响应头Response Headers

  • Content-Type:响应体的格式“类型/语法”

③回车——隔开响应头响应体

④响应体

  • 响应体为返回给客户端的内容
  • 响应体一般为下载内容

2、用Node.js设置响应

①设置响应状态码

response.statusCode = 200;

②设置响应头

response.setHeader('Content-Type', 'text/html');

③设置响应体

response.write('内容'); 可追加内容

④设置结束响应 response.end()表示响应可以发给用户了

3、如何查看响应

(1)用Chrome开发者工具查看响应的信息

开发者工具 → Network → 点击要查看的请求 → Headers → Reponse Header → view source

(2)用curl发请求时就可看到响应的信息

四、如何做出一个响应--做一个服务器

(一)做法

需用编程,Node.js有一个http模块可以做到。

(二)步骤

这些代码就是服务器代码,就像百度的服务器,就是我们下面这个代码更复杂一点罢了,但是都是放在服务器上,而不是像我们这样放在自己的电脑上。因为我们暂时没有服务器。

1、用VSCode新建文件server.js,并写入以下代码。这时文件server.js相当于一个服务器了。

2、代码如下

var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

  var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`二哈`)
    response.end()
  } else if(path === '/x'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(`body{color: red;}`)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)


3、解释

每次收到请求都会把中间的代码执行一遍

(1)输出请求的路径(带查询参数),具体表现为“有个傻子发请求过来啦!路径(带查询参数)为:/xxxx”

(2)用if else判断路径,并返回相应的响应

①如果是已知路径,一律返回200

  • 如果路径为/,那么状态码是200,响应头为响应体的格式是“text类型html语法,编码方式是utf-8”,响应体的内容也就是返回的内容为“二哈”,响应结束。

  • 如果路径为/x,那么状态码是200,响应头为响应体的格式是“text类型css语法,编码方式是utf-8”,响应体的内容也就是返回的内容为“body{color: red;}”,响应结束。

    ②如果是未知路径,一律返回404

  • 状态码是404,响应头为响应体的格式是“text类型html语法,编码方式是utf-8”,响应体的内容也就是返回的内容为“你输入的路径不存在对应的内容”,结束响应。

4、node server.js 8888来启动服务器

  • 服务器开了一个端口8888,这个端口就被server.js(也就是服务器)监听了。
  • 这时,只要有人请求了8888,就会进入服务器的代码里面
  • 每请求一次,服务器里的代码就会运行一次

5、成为一个完整网页的全过程

  • 一个路径返回HTML字符串,一个路径返回CSS字符串,一个路径返回JS字符串。
  • 在HTML字符串中通过link把CSS字符串和JS字符串的路径结合起来。
  • 当浏览器读到link时就会再去请求CSS字符串的路径和JS字符串的路径
  • 这就是HTML和CSS和JS通过HTTP传送并结合到浏览器成为一个完整网页的全过程。
  • 以下为例子:把上面代码修改了一点
var http = require("http");
var fs = require("fs");
var url = require("url");
var port = process.argv[2];

if (!port) {
  console.log("请指定端口号好不啦?\nnode server.js 8888 这样不会吗?");
  process.exit(1);
}

 var server = http.createServer(function(request, response) {
  var parsedUrl = url.parse(request.url, true);
  var pathWithQuery = request.url;
  var queryString = "";
  if (pathWithQuery.indexOf("?") >= 0) {
    queryString = pathWithQuery.substring(pathWithQuery.indexOf("?"));
  }
  var path = parsedUrl.pathname;
  var query = parsedUrl.query;
  var method = request.method;

  /******** 从这里开始看,上面不要看 ************/

  console.log("有个傻子发请求过来啦!路径(带查询参数)为:" + pathWithQuery);

  if (path === "/") {
    response.statusCode = 200;
    response.setHeader("Content-Type", "text/html;charset=utf-8");
    response.write(`
    <!DOCTYPE html>
    <head>
    <link rel="stylesheet" href="/x">
    </head>
    <body>
    <h1>标题</h1>
    </body>
    </head>
    `);
    response.end();
  } else if (path === "/x") {
    response.statusCode = 200;
    response.setHeader("Content-Type", "text/css;charset=utf-8");
    response.write(`body{color: red;}`);
    response.end();
  } else {
    response.statusCode = 404;
    response.setHeader("Content-Type", "text/html;charset=utf-8");
    response.write(`你输入的路径不存在对应的内容`);
    response.end();
  }

  /******** 代码结束,下面不要看 ************/
});

server.listen(port);
console.log(
  "监听 " +
    port +
    " 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:" +
    port
);

如果路径是/,那么就返回一串HTML字符串,其中有句代码为<link rel="stylesheet" href="/x">。当浏览器渲染这些HTML代码,读到link这句时,就要再去请求路径为/x的CSS字符串。然后CSS就会作用到HTML代码上了。

五、console.log调试大法

  1. 适用于JS
  2. 把你认为正确的语句写进去,看看运行出来是啥样的。

六、小知识点

  1. 代码
  • ``(1的左边)这种字符串里面可以回车
  • ''(Enter的左边)这种字符串里面要回车只能用\n表示
  1. curl不光可以发HTTP请求,它可以完成浏览器的基本功能,比如下载图片等,就是没有可视化。相当于命令行和图形界面的关系
  2. 不管状态码是200还是404,响应体照样会返回。只是平常的404里的响应体都为空
else {
    response.statusCode = 404;
    response.end();

所以我们才会看到“找不到xxx页面”,这是Chrome发现服务器返回了404却没有返回其他内容,于是Chrome就自己做了个网页给我们看。 4. HTTP里所有路径以/开头

七、购买自己的服务器

  • 我们在阿里巴巴上有一个云服务器,里面有两个用户root和frank。
  • root的家目录是/root frank的家目录是/home/frank
  • 在本地用ssh root@IP进入root用户的家目录
  • ssh frank@IP进入frank用户的家目录

(具体见PPT18)

八、常见状态码

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。

HTTP状态码分类

  • 1** ——信息,服务器收到请求,需要请求者继续执行操作
  • 2** ——成功,操作被成功接收并处理
  • 3** ——重定向,需要进一步的操作以完成请求
  • 4** ——客户端错误,请求包含语法错误或无法完成请求
  • 5** ——服务器错误,服务器在处理请求的过程中发生了错误

1xx

2xx

3xx

4xx

5xx