开发博客项目之接口(1)

http-概述

开发接口(不用任何框架)

nodejs处理http请求
搭建开发环境
开发接口(暂不连接数据库,暂不考虑登录)

HTTP请求概述(从输入url到页面显示都经历了什么)

  1. 客户端(浏览器)
    DNS解析:通过输入的域名解析到一个IP地址;
    建立TCP连接(三次握手);
    发送http请求
  2. 服务端
    server接收到http请求,处理,并返回。(处理过程在下面“nodejs处理HTTP请求”中)(res返回的都是字符串,只是形式不同,通过content
    -type来决定,比如html或者json)
  3. 客户端(浏览器)
    接收到服务端返回的数据,处理数据(如渲染页面,执行js)

实例演示

  1. 客户端(浏览器)进行DNS解析:浏览器或者操作系统本身是有缓存的,如果是缓存过期或者没有缓存又或者是第一次访问,浏览器或者操作系统就会去域名工程商去通过域名去DNS服务器换取IP地址。(更多详情需要复习 计算机网络 )
    server端就是这个IP地址的服务器!!
    DNS解析
    (百度比较大,全国各地使用人数多,看到的IP地址不一样是正常的,就算是自己今天看到的和昨天看到的不一样也是很正常的)
  2. 客户端找到IP地址之后就会和这个IP地址的服务器(server端)进行TCP连接(三次握手)
握手 作用
第1次 客户端(浏览器)询问服务器(server端):“你是否可以使用?”
第2次 服务器(server端)回答客户端(浏览器):“我可以用。”
第3次 客户端(浏览器)告诉服务器(server端):“我知道啦,接下来我会访问你哦。”
  1. 客户端(浏览器)发送http请求:客户端(浏览器)通过url使用get方法向服务端发送http请求,头部包含了请求信息,他们告诉了服务端这个客户端(浏览器)是什么样子的以及有什么要求。
    发送http请求
    (注意:请求req都是客户端发起的,而回复res都是服务端做的。)

我们已经清楚:server端就是这个IP地址的服务器
4. server端会通过Response Headers 告诉客户端:我反回的是html代码而不是纯文本
server端回复的信息
server端反回的html代码

  1. 客户端(浏览器)接收到server端返回的数据后就会解析这些html代码,解析完之后就会去渲染,渲染完后就会显示页面,页面显示之后就会加载图片、加载js、加载jquery、加载css等,这些又是另外的HTTP请求。
    (可能会通过一个网页产生很多的HTTP请求,当然请求越少性能越好)

nodejs处理HTTP请求

nodejs作为server端处理HTTP请求,这也是“从输入url到页面显示都经历了什么”中的第二个步骤。

主要讲解

  • get请求和querystring(客户端要向server端获取(索取)数据
  • post请求和postdata(客户端要向服务端传递数据
  • 路由(接口地址)

总结
无论是GET还是POST,nodejs处理HTTP请求的最基本思路就是我们(客户端)向服务端传递一些信息(我想向你获取/传递数据),然后服务端进行处理以后再返回给我们

概括HTTP请求的代码流程

  1. 所有的HTTP请求都需要在开头引用node自带的http模块(const http = require("http"))
  2. 在中间通过http.createServer()创建一个服务器http.createServer()参数为一个函数,该函数通过 request, response 2个参数来接收和响应数据(参数名可自定义)
  3. 最后在结尾监听端口服务器名.listen(8000)).

request(req)和response(res)的属性/方法

  • 创建服务器http.createServer()的参数(回调函数)拥有两个参数:request和response(参数名可自定义,第一参数为请求,第二参数为响应)
  • request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。
  • response 对象表示 HTTP 响应,即在接收到请求时向客户端(浏览器)发送的 HTTP 响应数据。
  • 有不了解的属性可到nodejs文档中查询。

用到的request 对象的属性:

  • **request.method**:客户端是用什么方法请求的(GET/POST)。
  • request.url:获取完整的url
  • request.headers:客户端(浏览器)向服务端发送的请求中的头中的信息。request.headers["content-type"]:请求的数据类型是什么(比如JSON)。
  • request.setHeader(name, value):为请求头对象设置单个请求头的值。 (例子

用到的response 对象的属性:

  • response.end()中要返回一个字符串【必须在每个响应上调用response.end()此方法向服务器发出信号,表明已发送所有响应头和主体,该服务器应该视为此消息已完成。用于让响应的代码结束。(文档解释
  • response.setHeader(name, value):设置单个响应头的值。假设我们通过response.setHeader('Content-Type', 'application/json'); 将响应头的内容类型设置为JSON了,那么response.end()返回的虽然还是一个字符串,但这个字符串是JSON类型的(比如'{"name":"shily","sex":"女","age":"23"}';//json字符串)。(文档解释

复习:string的split()将字符串转换为数组

  • split()可把一个字符串分割成字符串数组
  • stringObject.split(separator)
  • separator:必需,分隔符.(分隔符可以使字符串)
  • 在下面“处理get请求”例子中有所应用。

node自带的querystring模块

  • querystring和http一样也是node自带的一个模块。
  • a=querystring.parse()可将()中的字符串转换为对象后赋值给a
  • 在下面“处理get请求”例子中有所应用。

处理get请求

  1. get请求,即客户端要向server端获取(索取)数据,如查询博客列表
  2. 客户端通过querystring来向服务端传递数据(也就是url参数),如a.html?a=100&b=200也就是a=100&b=200传给了服务端,服务端收到后进行处理再返回相应的数据给到客户端
  3. 浏览器直接访问,发送的就是get请求(像上面的“实例演示”中访问百度就是get请求)

例子

新建文件夹“http-test”,在vscode中打开,因为不知道接下来会不会需要加载其他包,所以可以在终端先npm init -y初始化npm环境,初始化后会得到package.json,
package.json
将首页改为app.js后新建主页

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const http = require("http")
//querystring也是node自带的一个模块
const querystring = require ("querystring")

const server = http.createServer((req,res)=>{
//GET,req.method:客户端是用什么方法请求的
console.log("method:",req.method)
const url = req.url
console.log("url:",url)
//split()把 字符串 分割成 字符串数组,取第2个数组元素(`?`后的字符串)
// 使用querystring.parse()可将()中的字符串转换为对象后赋值给req.query
req.query = querystring.parse(url.split("?")[1])
console.log("query:",req.query)
//`end()`中要返回一个字符串,使用`stringify()`将JSON对象转换为字符串
res.end(
JSON.stringify(req.query)
)
})
//使用8000端口监听server对象
server.listen(8000)
console.log("OK")//返回一个OK证明监听成功

在终端测试,输入node app.js后得到OK说明监听成功
app.js
打开http://localhost:8000/得到的是一个空对象,这是因为query就是一个对象,而我们没有往里面放东西:
打开`http://localhost:8000/`
输入http://localhost:8000/api/blog/list?author=hlz&keyword=hahaha,也就是通过url参数(?后即url参数)往query里面放东西以后
输入 http://localhost:8000/api/blog/list?author=hlz&keyword=hahaha
可以看到终端返回的内容也有所变化
vscode终端内容
补充:终端中的url: /favicon.ico是浏览器默认的请求,主要是向服务端请求一个页面标志:
url: /favicon.ico


处理post请求

post请求,即客户端要向服务端传递数据,如新建博客
也就是客户端通过post data向服务端传递数据,服务端接收以后会进行处理。
浏览器无法直接模拟,需要手写js,或者使用postman(不能像上面get请求一样直接通过浏览器访问某个页面来模拟)

安装postman

postman可用于调试、发送HTTP请求。
以前可以进入Google搜索postman chrome,或者可以点击这个链接进行postman插件的添加。
现在只能直接去官网下载postman app。


数据流(获取数据的方式)

  • nodejs中获取由客户端post请求发送过来的数据是采取数据流的方法,并不是传完再获取,是一边传一遍获取(可以想象为一根水管连着木桶)
  • 三种处理数据流的方法on()有三个可选的第一个参数:data, end,error
  • 在下面“POST请求的例子”中有所使用。

例子:
假设readerStream是我们要读取的一大段数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 处理流事件 --> data, end, and error
//当接受到一点数据时就执行一次data(传入一次chunk),逐次累加在 allData 上
let allData = "";
readerStream.on('data', function(chunk) {
allData += chunk;
});

//数据传输结束,执行end
readerStream.on('end',function(){
console.log(allData);
});

readerStream.on('error', function(err){
console.log(err.stack);
});

console.log("程序执行完毕");

可参考菜鸟教程


post请求的例子

注意:每次修改nodejs代码内容后都需要在终端输入node app.js来重启node。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const http = require("http")

const server = http.createServer((req, res) => {
if (req.method === "POST") {
//req 数据类型,目前只处理JSON,比较方便
console.log("req content-type", req.headers["content-type"])
//接收数据
let postData = ""
//on()可参考上面“数据流”笔记
//每接受一点数据就执行一次data,chunk为接受的数据
req.on("data", chunk => {
postData += chunk.toString()
})
//接收完毕执行end
req.on("end", () => {
console.log("postData:", postData)
res.end("hello world!")
})
}
})
//监听8000端口
server.listen(8000)
console.log("OK")//返回一个OK证明监听成功

在postman上的操作流程
在postman上的操作流程
postman接收到了hello world!说明服务端接收到了返回(res)。
回到vscode终端可以看到(记得修改nodejs代码内容后需要在终端输入node app.js):
成功
说明我们通过postman发送的数据真正到了node文件中,并且他是一个post请求,且它被我们通过data、on、end的方式被接收到了。


nodejs处理路由

路由:代表了url资源唯一的标识。
以github为例讲解一下路由:
例子

例子

1
2
3
4
5
6
7
8
9
const http = require("http")
const server = http.createServer((req, res) => {
const url = req.url
const path = url.split("?")[0]
res.end(path);//返回路由
});

server.listen(8000)
console.log("OK")//返回一个OK证明监听成功

访问http://localhost:8000/api/blog/list?author=hlz&keyword=hahaha
结果


处理http请求的综合示例

总结:无论是GET还是POST,nodejs处理HTTP请求的最基本思路就是我们向服务端传递了什么,然后服务端进行处理以后再返回给我们

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const http = require("http")
const querystring = require("querystring")

const server = http.createServer((req, res) => {
const method = req.method
const url = req.url
const path = url.split("?")[0]
const query = querystring.parse(url.split("?")[1])

//设置返回的字符串格式为JSON
res.setHeader("Content-type", "application/json")

//返回的数据
const resData = {
method,
url,
path,
query
}

//返回
if (method === "GET") {
res.end(
//res.end()返回的一定是字符串,而上面设置的Content-type返回类型为json
JSON.stringify(resData)
)
}
if (method === "POST") {
let postData = ""
req.on("data", chunk => {
//把post过来的数据都放进postData中
postData += chunk.toString()
})
req.on("end", () => {
//postData中的数据必须返回才能显示,所以放入resData中
resData.postData = postData
//返回
res.end(
JSON.stringify(resData)
)
})
}
})

server.listen(8000)
console.log("OK")//返回一个OK证明监听成功

测试GET

直接在网页测试GET请求,客户端通过querystring向服务端传递后的query数据(也就是url参数),然后服务端将它们通过res返回到客户端,也就显示在页面上了:
测试GET

测试POST

在postman中进行POST请求的测试,客户端通过 postData 向服务端传递了两条数据(博客标题、博客内容),我们写的nodejs给予的处理是将 postData 放入 resData 中通过 res 返回到页面上,如图所示:
测试POST