内置模块(1): http模块

  • 官方文档

  • http 模块是 Node.js 官方提供的用来创建 web 服务器的模块

  • 通过 http 模块提供的 http.createServer() 方法,就能方便的把一台普通的电脑,变成一台 Web 服务器,从而对外提供 Web 资源服务。

  • Node.js 中,不需要使用 IISApache(针对php) 等第三方 web 服务器软件(普通的电脑常常安装这些),而是基于 Node.js 提供的 http 模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供 web 服务

基本使用:(两种写法)

  1. server.js
// nodeJS内置模块 : http模块

// 1.首先引入 http 内置模块
const http = require("http")

// 2.创建服务器
http.createServer((req , res)=>{
// 这里以一个函数为参数,用于接收浏览器传的参数,返回渲染的内容

// req:全称request,表示浏览器传来的参数
// res:全程result,表示浏览器渲染的内容
// res.write("Hello! Node-Server!")

// 设置响应头(文本展示类型设置为html格式,以及中文显示)
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"})
// 服务器同样可以展示html标签
res.write(`
<html>
<strong>你好! Node服务器</strong>
</html>
`)

res.end()//切记一定要用end()方法来结束代码!里面也可以传入字符串

}).listen(3000 , ()=>{//设置监听端口号以及服务器运行成功的回调函数
console.log("服务器已启动! 端口号为3000");
})
  1. server.js
var http = require("http")

var server = http.createServer()
server.on("request",(req,res)=>{
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"})
res.write("<h1>你好,世界</h1>")
res.end("结束")
})
server.listen(3000,()=>{
console.log("服务器已启动! 端口号为3000")
})

结果展示:

  • 终端内展示
    image

  • 网页展示
    image

小案例:

  • 要求: 输入对应的url参数,能进入对应的页面,没有该页面则返回404,状态码要与其保持一致
  • url: '/home'对应首页 , '/list'对应详情页

代码展示:

  • server.js
// nodeJS内置模块 : http模块

// 1.首先引入 http 内置模块
const http = require("http")

// 2.创建服务器
http.createServer((req , res)=>{
// 这里以一个函数为参数,用于接收浏览器传的参数,返回渲染的内容

// req:全称request,表示浏览器传来的参数
// res:全程result,表示浏览器渲染的内容

// 设置响应头(文本展示类型设置为html格式)
res.writeHead(renderStatus(req.url),{"Content-Type":"text/html;charset=utf-8"})
// 服务器同样可以展示html标签
res.write(renderHtml(req.url))

res.end()//切记一定要用end()方法来结束代码!里面也可以传入字符串

}).listen(3000 , ()=>{//设置监听端口号以及服务器运行成功的回调函数
console.log("服务器已启动! 端口号为3000");
})

// url渲染函数
function renderHtml(url){
switch (url) {
case "/":
return `
<html>
<strong>你好! Node服务器!!!</strong>
</html>
`
case "/home":
return `
<html>
<strong>首页</strong>
</html>
`
case "/list":
return `
<html>
<strong>详情页</strong>
</html>
`
default:
return `
<html>
<strong>404 not fount!!!</strong>
</html>
`
}
}

// 状态渲染函数(响应码的设置)
function renderStatus(url){
var arr = ['/home','/list','/']
return arr.includes(url)?200:404//判断是否包含对应的参数
}

结果展示:

image

http模块扩展-jsonp

什么是jsonp?

  • 我们在发送Ajax请求的时候会受同源策略的影响而存在跨域请求的问题,不管是静态页面、动态页面、web服务,只要是跨域请求,一律都是不允许的
  • 但是web页面调用js文件则不受跨域的影响(不仅如此,我们还发现凡是拥有“src”这个属性的标签都拥有跨域的能力,比如<\script><\img><\iframe>)。
  • 于是可以判断,当前阶段如果想通过纯web端跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理。
  • 恰巧我们知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。
  • 这样,解决方案就呼之欲出了,web服务端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件,显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装进去。久而久之就形成了一种非正式的传输协议: JSONP(JSON with Padding)

代码展示:(这里结合urlhttp模块的使用)

  • 服务端(json.js)
// 内置模块: http模块 - jsonp解决跨域
// 应用场景: 前端页面请求固定的url并携带参数name,返回数据

// 1.引入http模块和url模块
const http = require('http')
const url = require('url')

// 2.创建服务器
http.createServer((req , res)=>{
// 获取网页url参数种的pathname
var urlObj = url.parse(req.url,true)//设置解析true
console.log(urlObj.query);//获取query参数
switch(urlObj.pathname){
case '/lam':
res.end(`${urlObj.query.name}(${JSON.stringify({
name: 'Cheung Pui Lam',
age: 100
})})`)
break;
default :
res.end('404')
}

}).listen(3000 , ()=>{
console.log('服务器已启动,3000端口正在监听!!!');
})
  • 前端页面(jsonp.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网页请求页面资源(jsonp)</title>
</head>
<body>
<!-- jsonp解决跨域问题 -->
<script>
// 原理: 通过给页面添加script标签并且用其src属性来实现跨域请求

// 1.首先创建script标签
var myScript = document.createElement("script")

// 2.给新建的script标签添加src属性(携带name参数接收数据)
myScript.src = "http://localhost:3000/lam?name=lam"

// 3.将该标签添加到页面当中
document.body.appendChild(myScript)

// 4.创建函数接收参数
function lam(obj){
console.log(obj);
}
</script>
</body>
</html>

结果展示:

  • 服务端展示
    image
    image

  • 前端页面展示
    image

http模块扩展-cors

  • CORS:全称”跨域资源共享”(Cross-origin resource sharing)。
  • 我们可以设置三个响应头来实现跨域请求
    1. 使用res.writeHeader(“Access-Control-Allow-Origin”,"*")
      • 表示允许任何域的请求,如果想要特定的话 * 换成特定 url
    2. Access-Control-Allow-Headers
      • 因为cors仅支持客户端向服务端发送9个请求头,如果超过了就用res.setHeader(“Access-Control-Allow-Headers”,”添加需要的请求头”)
    3. Access-Control-Allow-Methods
      • 默认情况下只支持客户端发起GET POST HEAD ,如果要用其他的比如PUT DELETE就需要使用res.setHeader``(“Access-Control-Allow-Methods”,"*") 添加*就是指添加所有的方法。

代码展示:

  • 服务端(cors.js)
// 内置模块: http模块 - cors解决跨域
// 应用场景: 前端页面请求固定的url并携带参数name,返回数据

// 1.引入http模块和url模块
const http = require('http')
const url = require('url')

// 2.创建服务器
http.createServer((req , res)=>{
// 获取网页url参数种的pathname
var urlObj = url.parse(req.url,true)//设置解析true
console.log(urlObj.query);//获取query参数
// 设置cors请求头跨域问题
res.writeHead(200 , {
//设置文本渲染类型
"Content-Type":"application/json;charset=utf-8",
// 设置允许所有跨域请求的cors请求头
"access-control-allow-origin":"*"
})
switch(urlObj.pathname){
case '/lam':
res.end(JSON.stringify({
name:"Cheung Pui Lam",
age: 100
}))
break;
default :
res.end('404')
}

}).listen(3000 , ()=>{
console.log('服务器已启动,3000端口正在监听!!!');
})
  • 前端页面(cros.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cors解决跨域</title>
</head>
<body>
<script>
// 服务端已设置好跨域,直接发送请求即可(这里使用fetch来发送请求,axios也可以)
fetch("http://localhost:3000/lam?name=lam")
.then(res=>res.json())
.then(res=>{
console.log(res);
})
</script>
</body>
</html>

结果展示:

  • 服务端
    image
    image

  • 前端页面
    image

http模块扩展-get

  • 要知道node不仅可以作为服务端(后端返回数据),更能作为客户端(向另一个后端请求数据)。众所周知,前端页面向服务端发送请求是受同源策略影响的,即存在跨域问题,但是服务器与服务器之前是不受同源策略影响的,即服务器之间相互请求数据是没有跨域问题的,因此当我们向一个没有设置允许跨域请求("access-control-allow-origin")后端服务器请求数据时,是没有办法请求到数据的,但是我们可以通过node作为一个中间件客户端来时用,即前端向node请求数据,node向目标服务器请求数据后再返回给前端,这就能实现即便目标服务器没有设置允许跨域,我们同样能请求到数据。这就是node的一个非常的强大之处。
    image

代码展示:

  • 服务端(get.js)
// 内置模块: http模块 - get模块
// 应用场景: 前端页面通过以node为中间件来向猫眼电影的接口请求数据

// 1.引入http模块和url模块
const http = require('http')
const url = require('url')
const https = require('https')

// 2.创建服务器
http.createServer((req , res)=>{
// 获取网页url参数种的pathname
var urlObj = url.parse(req.url,true)//设置解析true
// 设置cors请求头跨域问题
res.writeHead(200 , {
//设置文本渲染类型
"Content-Type":"application/json;charset=utf-8",
// 设置允许所有跨域请求的cors请求头
"access-control-allow-origin":"*"
})
switch(urlObj.pathname){
case '/maoyan':
httpsget((data)=>{//将形参设置为函数便于携带数据
res.end(data)
})
break;
default :
res.end('404')
}

}).listen(3000 , ()=>{
console.log('服务器已启动,3000端口正在监听!!!');
})

// 设置get请求,向猫眼电影请求数据
function httpsget(cd){
var data = ""//创建数据接收变量
// 使用https模块向猫眼电影的接口请求数据
https.get(`https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E6%B1%9F%E9%97%A8&ci=277&channelId=4`,res=>{
// console.log('111'+ res);//无法直接接收到数据

// 数据接收流程如下:
// 1.设置监听事件来监听数据的接收(数据接收阶段)
res.on("data",(chunk)=>{//接收数据流
data += chunk
})

// 2.数据接收完成发送给前端(数据接收完成)
res.on("end",()=>{//数据接收完毕
console.log(data);
cd(data)
// 切记异步编程不能使用return,使用return返回的是undefined
// 可以使用promise来获取数据
// 后面学习到event模块可以解决
})
})
}
  • 前端页面(get.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>get请求数据(node中间运送数据)</title>
</head>
<body>
<script>
// 服务端已设置好跨域,直接发送请求即可
fetch("http://localhost:3000/maoyan")
.then(res=>res.json())//做json格式的转换,原数据格式为字符串
.then(res=>{
console.log(res);
})
</script>
</body>
</html>

结果展示:

  • 服务端成功输出获取到的数据
    image

  • 前端网页数据也获取成功
    image

http模块扩展-post

  • get很相似,不过与之不一样的是请求参数的携带的地方,get请求是写在url中的,而post请求是写在请求体中的,通过req.write()来写入

代码展示:

  • 服务端(post.js)
// 内置模块: http模块 - post模块
// 应用场景: 前端页面通过以node为中间件来向小米优品的接口请求数据
// 与get相比,发送post请求需要给请求体携带上相对应的参数

// 1.引入http模块和url模块
const http = require('http')
const url = require('url')
const https = require('https')

// 2.创建服务器
http.createServer((req , res)=>{
// 获取网页url参数种的pathname
var urlObj = url.parse(req.url,true)//设置解析true
// 设置cors请求头跨域问题
res.writeHead(200 , {
//设置文本渲染类型
"Content-Type":"application/json;charset=utf-8",
// 设置允许所有跨域请求的cors请求头
"access-control-allow-origin":"*"
})
switch(urlObj.pathname){
case '/xiaomi':
httpspost((data)=>{//将形参设置为函数便于携带数据
res.end(data)
})
break;
default :
res.end('404')
}

}).listen(3000 , ()=>{
console.log('服务器已启动,3000端口正在监听!!!');
})

// 设置get请求,向猫眼电影请求数据
function httpspost(cd){
var data = ""//创建数据接收变量

// 配置请求对象
var options = {
hostname: "m.xiaomiyoupin.com",//域名
port:"443",//端口号
path:"/mtop/mf/resource/data/batchList",//路径
method:"POST",//请求方法
headers:{//设置请求头
"Content-Type":"application/json",//请求数据的格式

}
}
// 使用https模块向小米优品的接口请求数据
var req = https.request(options,res=>{

// 数据接收流程如下:
// 1.设置监听事件来监听数据的接收(数据接收阶段)
res.on("data",(chunk)=>{//接收数据流
data += chunk
})

// 2.数据接收完成发送给前端(数据接收完成)
res.on("end",()=>{//数据接收完毕
console.log(data);
cd(data)
// 切记异步编程不能使用return,使用return返回的是undefined
// 可以使用promise来获取数据
// 后面学习到event模块可以解决
})
})

// 设置请求体的参数(一定要设置这个参数才能响应返回数据)
// 相当于get请求url种携带的一些参数,不过post的这些参数是写在请求体里面的而已
req.write(JSON.stringify([{},["newer_popup_ad","download_options"]]))
req.end()
}
  • 前端页面(post.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>post请求数据(node中间运送数据)</title>
</head>
<body>
<script>
// 服务端已设置好跨域,直接发送请求即可
fetch("http://localhost:3000/xiaomi")
.then(res=>res.json())//做json格式的转换,原数据格式为字符串
.then(res=>{
console.log(res);
})
</script>
</body>
</html>

结果展示:

  • 服务端成功输出获取到的数据
    image

  • 前端网页数据也获取成功
    image