http 模块
引入
import http from 'http'
const http = require('http')
创建服务器
使用 createServer
可以创建一个 Server
实例,可以传入一个回调函数,之后每次请求都会调用这个函数,并传参 req 和 res
const server = http.createServer((req, res) => {
// do
})
也可以监听 request
方法来对每次请求处理
server.on('request', (req, res) => {
// do
})
然后需要监听某个端口号
server.listen(3000, () => {
// do
})
现在你可以访问
localhost:3000
来请求服务器了,但是没有内容,我们还需要响应请求
req
包含了请求时的信息,比如 url
处理 post 请求
let data = ''
req.on('data', chunk => {
data += chunk
})
req.on('end', () => {
console.log(data)
})
res
调用 res.write()
可以返回内容给客户端,最后需要调用 res.end()
来结束返回
响应请求
res.write()
可以返回各种内容
// 返回普通的字符串
res.write('abc')
// 返回html标签
res.write('<b>abc</b>')
// 返回json
res.wirte('[1,2,3]')
res.writeHead()
用来指定响应头
如下,返回了 200 的状态,指定返回类型 html
,编码使用 urf-8
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' })
使用
utf-8
编码可以支持我们返回中文
res.end()
结束返回,你也可以在这里最后返回一些数据
res.end('abc')
根据 url 返回不同的内容
现在你改变路径看到的都是相同的内容,我们可以在每次请求时候根据 url 返回不同内容
首先从 req 中获取 url
const { url } = req
接着就可以根据 url 来做一些事情
下面定义了一个 renderHtml
函数,可以根据传入的 url 返回不同内容
const container = content => `<div>${content}</div>`
const urlCollect = {
'/home': container('this is home'),
'/page': container('this is page'),
'/api/list': '[1,2,3]'
}
const renderHtml = url => {
return urlCollect[url] || container('not found')
}
使用
res.write(renderHtml(url))
有关 url 的更多内容可以查看 url 模块
JSONP
JSONP 是一种跨域手段,主要原理就是利用了 script
标签的 src 请求不受同源限制,去请求一个 js 文件,文件中执行我们指定的方法同时将我们需要的数据作为参数传递进去
现在我们通过 Node.js 去实现一个 JSONP 接口
import http from 'http'
import { URL } from 'url'
const jsonp = fnName => {
const data = {
name: 'mo',
age: 12
}
// 将函数名和数据拼合成执行字符串返回
return `${fnName}(${JSON.stringify(data)})`
}
const server = http.createServer()
server.on('request', (req, res) => {
const { url } = req
const { pathname, searchParams } = new URL(url, 'http://127.0.0.1:3000')
const fnName = searchParams.get('fn')
if (pathname === '/api/aaa' && fnName) {
// 当 url 路径是 /api/aaa 同时有fn参数的的时候返回JSON
res.end(jsonp(fnName))
} else {
res.end('not found')
}
})
server.listen('3000')
接着编写前端的请求
<!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>
</body>
<script>
// 创建script标签并指定src
const script = document.createElement('script')
script.src = 'http://localhost:3000/api/aaa?fn=getData'
document.body.appendChild(script)
// 定义好要执行的函数
const getData = (data) => {
console.log(data)
}
</script>
</html>
然后在不同的端口号上打开页面,可以看到控制台成功输出了数据
CORS
除了 JSONP,也可以在后端直接设置 CORS,解除其他源访问我们 api 的限制
res.writeHead(200, {
'Content-Type': 'application/json;charset=utf-8',
// 设置cors头,允许所有域访问
'access-control-allow-origin': '*'
})
也可以指定某个域名
代理
以上是对自己服务器 api 跨域的处理,而如果在前端想访问其他网站的 api,可以在 Node.js 进行一个代理。用 Node.js 去请求其他接口,然后返回给前端
https
接下来需要用到 https
模块
import https from 'https'
const https = require('https')
get
使用 https.get
来发起 GET 请求
创建一个 get
函数,接收一个回调并将最终的数据传递出去
const get = cb => {
https.get(
// 猫眼网站上的一个api接口
'https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=杭州&ci=50&channelId=4',
res => {
let data = ''
// 监听data事件,把数据流合并到最终的数据中
res.on('data', chunk => {
data += chunk
})
// 在结束的时候调用传进来的回调函数,将最终数据传递出去
res.on('end', () => {
cb(data)
})
使用
get(data => {
res.end(data)
})
request
使用 https.request
来发起 POST 请求
创建一个 request
函数,和 get
函数相同的效果,不过这次多了配置以及用 write()
传入 POST 数据
const request = cb => {
const options = {
hostname: 'api.juejin.cn',
port: '443',
path: '/recommend_api/v1/article/recommend_all_feed?aid=2608&uuid=&spider=0',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}
const req = https.request(options, res => {
let data = ''
res.on('data', chunk => {
data += chunk
})
res.on('end', () => {
cb(data)
})
})
// POST数据在这里传入
req.write(
JSON.stringify({
id_type: 2,
client_type: 2608,
sort_type: 200,
cursor: '0',
limit: 20
})
)
req.end()
}
使用
request(data => {
res.end(data)
})
爬虫
当把 get 中的 api 换成网址后就可以直接获取到 html 文本,接着我们使用 cheerio 这个库对文本进行解析 (当然,如果你想用正则表达式也可以)
const spider = cb => {
https.get('https://www.w2solo.com/', res => {
let data = ''
res.on('data', chunk => {
data += chunk
})
res.on('end', () => {
// 解析html文本
const $ = cheerio.load(data)
// 就像操作jquery一样
const topicList = $('.topic')
const topics = []
// 遍历dom,获取其中的文本并处理
topicList.each((index, val) => {
topics.push(
$(val).find('.title').text().trim().replace(/\s+/, ': ')
)
})
cb(JSON.stringify(topics))
})
})
}
使用
spider(data => {
res.end(data)
})