express
- 1. 使用express创建web服务器:
- 2. 中间件
- 中间件分类:
- 3.解决跨域问题:
- 1. CORS
- 2.JSONP
1. 使用express创建web服务器:
1. 导入express2. 创建web服务器3. 启动web服务器
// 1. 导入express
const express = require('express')// 2. 创建web服务器
const app = express()// 4.监听客户端的GET和POST请求, 并且向用户响应具体内容
app.get('/user', (req, res) => {res.send('请求成功')
})app.post('/user', (req, res) => {// 调用express提供res.send方法,向客户端响应一个JSON对象res.send({name:'ly', age: 18})
})// 3. 启动web服务器
app.listen(8080, () => {console.log(`app listening`);
})
- 获取URL中携带的查询参数 http://127.0.0.1?name=ly&age=18
req.query对象,可以访问到客户端通过查询字符串。
- 获取URL中的动态参数
req.params对象,可以访问到URL中,通过:匹配到的动态参数。
- express.static(root, [options])创建一个静态资源服务器。
root参数指定提供静态资源的根目录。
eg: app.use(express.static(‘public’))
注意: express在指定的静态目录中查找文件,并对外提供资源的访问路径,因此,存放静态文件的目录名不会出现在url中。
-
路由:客户端请求与服务器处理函数之间的映射关系。
创建模块化路由:1. 导入express2. 创建web服务器(1. 导入路由模块2. 注册路由模块)3. 启动服务器
路由模块:
- 导入express
- 创建路由对象(express.Router())
- 挂载具体路由
- 向外导出路由对象
2. 中间件
本质上也是一个function处理函数。
注意: 中间件函数的形参列表中, 必须包含next参数。而路由处理函数只包含req和res。
-
next()实现多个中间件连续调用,表示把流转关系转交给下一个中间件或路由。
-
通过app.use()将中间件函数注册为全局生效的中间件。
中间件作用: 多个中间件之间,共享同一份req和res。基于这样特性,在上游中间件中,统一为req和res对象自定义添加属性和方法,则下游中间件或路由就可以使用。
// 导入express
const express = require('express')const app = express()// 定义中间件
app.use((req, res, next) => {console.log('第一个中间件');next()
})app.use(function(req, res, next) {console.log('第二个中间件');next()
})// 定义路由
app.get('/', (req, res) => {res.send('hhh')
})
app.listen(80, () => {console.log('serve running');
})
- 不使用app.use()定义的中间件—局部生效的中间件。
定义多个局部中间件 : app.get(‘/’, mw1, mw2, (req, res) => { …})或者app.get(‘/’, [mw1, mw2], (req, res) => { …})
注意事项:
- 必须在路由之前 注册中间件
- 客户端发送过来请求,可以连续调用多个中间件
- 执行完中间件业务代码之后,要调用next() 函数
- next()函数后面不要额外写代码
- 多个中间件中,共享req和res
中间件分类:
- 应用级别的中间件
通过app.use(),app.METHOD()绑定到app实例上的中间件—应用级别的中间件。 - 路由级中间件
绑定到express.Router() 实例上的中间件。 - 错误处理的中间件
捕获整个项目中发生的异常错误。— (err, req, res, next) 必须有4个形参
const express = require('express')const app = express()// 定义一个路由
app.get('/', (req, res) => {// 人为抛出异常throw new Error('服务器出错!!')res.send('hhh')
})// 定义一个错误中间件,捕获项目异常,防止程序崩溃
app.use((err, req, res, next) => {console.log('发生了错误' + err.message);res.send('Error' + err.message)
})app.listen(80, () => {console.log('serve running');
})
错误中间件必须注册在路由之后
-
express内置的中间件
- express.static 提供静态资源,例如 HTML 文件、图片等。
- express.json 解析json格式的请求体数据。 注意:适用于 Express 4.16.0+
- express.urlencoded 使解析URL-encoded格式的请求体数据。 注意:适用于 Express 4.16.0+
-
第三方的中间件
编写接口:1. 创建express服务器2. 创建API路由模块3. 编写get, post等接口
get,post接口会出现跨域问题。
3.解决跨域问题:
- CORS
- JSONP (只支持GET)
1. CORS
使用cors中间件解决跨域问题:
1. 下载第三方库 npm install cors 安装中间件
2. const cors = require('cors') 导入中间件
3. 调用app.use(cors())配置中间件
cors由一系列http响应头组成,这些http响应头决定浏览器是否阻止前端JS代码跨域获取资源。
cors在服务器端进行配置。
cors在浏览器中有兼容性。
cors响应头部: -Access-Control-Allow-Origin
响应头部携带一个-Access-Control-Allow-Origin : | * 字段 // origin参数指定了允许访问该资源的外域URL, *通配符,表示任意URL都通过。
res.setHeader(‘-Access-Control-Allow-Origin’,‘http://nim.cn’)
cors响应头部: -Access-Control-Allow-Headers
cors响应头部: -Access-Control-Allow-Methods 指明实际请求所允许使用的http方法。 —cors仅支持GET、POST、HEAD请求。
客户端在请求CORS接口时,根据请求方式和请求头的不同,可以将cors请求分为两大类:
-
简单请求
- 请求方式: GET、POST、HEAD三者之一
- HTTP头部信息不超过以下几种字段: 除了被用户代理自动设置的标头字段(例如 Connection、User-Agent 或其他在 Fetch 规范中定义为禁用标头名称的标头),
允许人为设置的字段为 Fetch 规范定义的对 CORS 安全的标头字段集合。该集合为:
Accept
Accept-Language
Content-Language
Content-Type(需要注意额外的限制)
Range(只允许简单的范围标头值 如 bytes=256- 或 bytes=127-255)
Content-Type 标头所指定的媒体类型的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
-
预检请求:
在浏览器和服务器之间进行通信之前,浏览器会发送OPTION请求进行预检,以获知服务器是否允许该实际请求,所以这一次的OPTION请求称为”预检请求“。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。满足任意一个条件,都需要进行预检请求:- 请求方式为GET,POST,HEAD之外的请求method类型。- 请求头中包含自定义头部字段- 向服务器发送application/json格式的数据。
2.JSONP
: 浏览器通过 script 标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。
- JSONP不属于真正的Ajax请求,因为没有使用XMLHttpRequest这个对象。
- JSONP仅支持GET请求,不支持POST、PUT、DELETE等请求。
必须在配置cors中间件之前,配置jsonp的接口。
实现JSONP接口步骤:1. 获取客户端发送过来的回调函数名字。2. 得到要通过JSONP形式发送给客户端的数据。3. 根据前两步得到的数据,拼接出一个函数调用的字符串。4. 上一步拼接的字符串,响应给客户端<script>标签进行解析执行
app.get('/api/jsonp', (req, res) => {// 得到函数名称const fullName = req.query.callback// 定义要发送给客户端的数据const data = {name : 'ly', age : 18}// 拼接一个函数的调用const scriptStr = `${fullName}(${JSON.stringify(data)})`// 拼接的字符串, 响应给客户端res.send(scriptStr)
})