exporess
邵预鸿 Lv5

路由

头部设置

1
2
3
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader("Content-Type", "text/plain;charset=utf-8"); // 原样输出,浏览器不处理
response.setHeader("Content-Type", "text/html;charset=utf-8"); // 浏览器转为html文件展示

一个最简单的配置

1
2
3
4
5
6
7
8
9
10
11
const express = require('express');
const app = express();
const fn1 = (res,req)=>{
req.send({code:200,message:'success',page: 'home'})
}
app.get('/home',fn1);
app.listen(3002,err=>{
if(err){
console.log('启动服务报错',err);
}
})

多个回调处理业务逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const express = require('express');
const app = express();
const fn1 = (res,req,next)=>{
// 通过res挂载属性可以传到next下的处理函数中,以实现传递参数

res.from = "这是fn1处理的参数";
next();
}
const fn2 = (res,req)=>{
req.send({code:200,message:res.from,page: 'home2'})
}
app.get('/home',[fn1,fn2]);
app.listen(3002,err=>{
if(err){
console.log('启动服务报错',err);
}
})

响应code

1
2
3
4
const fn2 = (res,req)=>{
req.status(200).send({code:200,message:res.from,page: 'home2'})
}
app.get('/home',[fn1,fn2]);

正则路由

  • 此路由路径将匹配acdabcd

    1
    2
    3
    app.get('/ab?cd', (req, res) => {
    res.send('ab?cd')
    })
  • 此路由路径将匹配abcdabbcdabbbcd等。

    1
    2
    3
    app.get('/ab+cd', (req, res) => {
    res.send('ab+cd')
    })
  • 此路由路径将匹配abcd, abxcd, abRANDOMcd, ab123cd, 等等。

    1
    2
    3
    app.get('/ab*cd', (req, res) => {
    res.send('ab*cd')
    })
  • 此路由路径将匹配/abe/abcde

    1
    2
    3
    app.get('/ab(cd)?e', (req, res) => {
    res.send('ab(cd)?e')
    })
  • 基于正则表达式的路由路径示例:

    此路由路径将匹配其中带有“a”的任何内容。

    1
    2
    3
    app.get(/a/, (req, res) => {
    res.send('/a/')
    })
  • 此路由路径将匹配butterflyand dragonfly,但不匹配butterflyman, dragonflyman, 等等。

    1
    2
    3
    app.get(/.*fly$/, (req, res) => {
    res.send('/.*fly$/')
    })

获取路由参数

  • 普通url参数,例 xxx.com?name=xiaoming&age=22

    1
    2
    3
    app.get('/home',(res,rep)=>{
    console.log('res:query',res.query);
    })
  • 通过表单格式x-www.form-urlencoded express.urlencoded

    1
    2
    3
    4
    app.use(express.urlencoded({extended: false}))
    app.get('/home',(res,rep)=>{
    console.log('res:body',res.body);
    })
  • 通过json传递的数据express.json()

    1
    2
    3
    4
    app.use(express.json());
    app.get('/home',(res,rep)=>{
    console.log('res:body',res.body);
    })
  • formData传递的数据/上传文件/上传文件格式验证

    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
    47
    48
    49
    50
    51
    52
    53
    const express = require('express');
    const route = express.Router();
    const multer = require('multer');
    const fs = require('fs');
    const storage = multer.diskStorage({
    destination: function (req, file, cb) {
    cb(null, './uploads/')
    },
    filename: function (req, file, cb) {
    cb(null, req.renameFile)
    }
    });

    const getData = ()=>{
    const now = new Date();
    const year = now.getFullYear();
    const month = now.getMonth() + 1;
    const day = now.getDate();
    const hour = now.getHours();
    const minute = now.getMinutes();
    const second = now.getSeconds();
    return `${year}${month}${day}${hour}${minute}${second}`;
    }
    const upload = multer({ storage: storage,fileFilter:(req, file, cb)=>{
    console.log('file-->',file);
    const exts = ['.gif','.png','.jpg','.jpeg','.bmp'];
    const originName = file.originalname;
    const filename = originName.substring(0,originName.lastIndexOf('.'));
    const ext = originName.substring(originName.lastIndexOf('.'));
    const renameFile = filename + '-' + getData()+ext;
    if(exts.includes(ext)){
    req.saveFile = [...(req.saveFile || []),renameFile];
    req.renameFile = renameFile;
    cb(null, true)
    }else{
    req.errFile = [...(req.errFile || []),renameFile];
    req.isSave = 'N';
    cb(null, false)
    }

    }})


    route.post('/upload',upload.any(),(req,res)=>{
    console.log('req.body',req.body);
    if(req.isSave === 'N'){
    res.send('上传失败'+( req.errFile).join(';'));

    }else{
    res.send('上传成功'+( req.saveFile).join(';'))
    }
    })
    module.exports = route;

    请求方式全匹配

1
2
3
4
5
6
7
8
/**
请求路由为/secret
请求方式: get/post/put/delete...
**/
app.all('/secret', (req, res, next) => {
console.log('Accessing the secret section ...')
next() // pass control to the next handler
})

对某个路径需要同时支持多种请求方式

1
2
3
4
5
6
7
8
9
10
app.route('/book')
.get((req, res) => {
res.send('Get a random book')
})
.post((req, res) => {
res.send('Add a book')
})
.put((req, res) => {
res.send('Update the book')
})

res.render()

1
2
3
4
5
6
7
8
9
10
11
res.render('index')

// if a callback is specified, the rendered HTML string has to be sent explicitly
res.render('index', function (err, html) {
res.send(html)
})

// pass a local variable to the view
res.render('user', { name: 'Tobi' }, function (err, html) {
// ...
})

响应信息类型

Method Description 事例
res.download() 文件流 res.download(‘./1.zip’)
res.end() node原生 res.end(JSON.string({name: ‘111’}))
res.json() 发送json数据 res.json({ user: ‘tobi’ })
res.jsonp() Send a JSON response with JSONP support.
res.redirect() Redirect a request.
res.render() 渲染模板,当配置了app.set(‘view’,’./views’)模板引擎目录时,res.render(‘logo’),将找到views/logo.ejs
res.send() Send a response of various types.
res.sendFile() Send a file as an octet stream.
res.sendStatus() Set the response status code and send its string representation as the response body.

中间件

  • 应用级中间件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 进入路由时,先进入全局接口
    app.use((res,resp,next)=>{
    const {user,pwd} = res.body;
    if(user === 'admin' && pwd === '123'){
    next();
    }else{
    resp.send({
    code: '-1',
    message : '验证不通过'
    })
    }
    })
    app.get('/home',[fn1,fn2]);
    app.post('/home',fn3);

    也可以为单独某几个路由增加应用级中间件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    route.use(["/login","/data"],(res,resp,next)=>{
    const { user, pwd} = res.body;
    console.log('user, pwd:',user, pwd);
    if(user === 'admin' && pwd === '123'){
    next();
    }else{
    resp.send({
    code: '-1',
    message: '身份认证失败'
    })
    }
    })
  • cors解决跨域问题

    链接: https://expressjs.com/en/resources/middleware/cors.html

    安装: npm install cors

    1
    2
    var cors = require('cors')
    app.use(cors())
  • rouer模块化 路由级中间件

    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
    /**  ROUTE.js  **/
    const express = require('express');
    const route = express.Router();
    route.use(express.json());
    route.use(express.urlencoded({extended: false}))
    route.use((res,resp,next)=>{
    const { user, pwd} = res.body;
    console.log('user, pwd:',user, pwd);
    if(user === 'admin' && pwd === '123'){
    next();
    }else{
    resp.send({
    code: '-1',
    message: '身份认证失败'
    })
    }
    })
    route.post('/login',(res,resp)=>{
    resp.send({
    code: '200',
    message: '登录成功'
    })
    })
    route.post('/list',(res,resp)=>{
    resp.send({
    code: '200',
    list: Array.from({length:10},(item,index)=>index)
    })
    });
    route.use((err,req,res,next)=>{
    res.send('404')
    })
    module.exports = route;
    1
    2
    3
    4
    5
    6
    const route = require('./Route.js');
    app.use('/api',route);
    /*
    127.0.0.1:3002/api/login
    127.0.0.1:3002/api/list
    **/
  • 错误级中间件

    1
    2
    3
    app.use((req,res)=>{
    res.send('<h1>没有页面 404</h1>')
    })
  • 文件处理中间件

    https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md

    参考例子: formData传递的数据/上传文件/上传文件格式验证

静态资源

1
2
3
4
5
6
7
// url无需写/public,相当于把根目录指向public
// 127.0.0.1/about.html
app.use(express.static('public'))

// url写public
// 127.0.0.1/public/about.html
app.use('/public',express.static('public'));

模板引擎

  • 安装并设置模板引擎目录

    参考: https://expressjs.com/en/guide/using-template-engines.html

    1
    2
    3
    app.set('views', './views')
    app.set('view engine', 'pug/ejs')
    app.engine('html',require('ejs').readerFile); // 将模板中的ejs文件变成html文件
  • 配置路由

    1
    2
    3
    4
    app.get('/login',(req,res)=>{
    res.render('login'); // 找到.views/login.ejs文件并返回
    res.render('about',{title: '关于我',menus: json.menus}); 为about提供参数
    })
  • 修改ejs默认文件类型

    app.engine('html',require('ejs').readerFile); // 将模板中的ejs文件变成html文件

    此时,使用的template就可以是普通的html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!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>
    <%= title %>
    </title>
    </head>
    <body>
    <%- include('./header.html',{show: true}) %>
    <h1> <%= title %></h1>
    <%# 这是注释 %>
    <!-- 这是注释2 -->
    <ul>
    <% for(let i=0;i<menus.length;i++){ %>
    <li><%- menus[i] %></li>
    <% } %>

    </ul>
    </body>
    </html>

ejs语法

  • 普通数据渲染

    1
    2
    3
    4
    5
     <title>
    <%= title %>
    </title>
    <h1> <%= title %></h1>

  • 循环数据

    1
    2
    3
    4
    5
    6
     <ul>
    <% for(let i=0;i<menus.length;i++){ %>
    <li><%= menus[i] %></li>
    <% } %>

    </ul>
  • 富文本

    1
    <div><%- menus[i] %></div>
  • 注释- 注释不解析到页面中

    代码审核元素,无当前注释,只存在于开发环境中

    1
    <%# 这是注释  %>
  • 引用其它模块

    1
    <%- include('./header.ejs',{show: true}) %>

    header.ejs

    1
    2
    3
    4
    5
    6
    <header>
    页面头部
    <% if(show) {%>
    <span>这是图标 </span>
    <% } %>
    </header>

node请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
app.get('/about', (req, res) => {
const options = {
hostname: '127.0.0.1',
port: 3002,
path: '/menu',
method: 'POST'
};

<!-- 请求三方接口代码 -->
const requestFunc = http.request(options, (response) => {
let result = '';
response.on('data', chunk => result += chunk);
response.on('end', () => {
const json = JSON.parse(result);
res.render('about',{title: '关于我',menus: json.menus});
})
});
// 写入数据到请求主体
requestFunc.write(querystring.stringify({
'msg': 'Hello World!'
}));
requestFunc.end();
});

参考链接: https://www.nodeapp.cn/http.html#http_http_request_options_callback

  • 本文标题:exporess
  • 本文作者:邵预鸿
  • 创建时间:2023-03-16 01:47:07
  • 本文链接:/images/logo.jpg2023/03/16/exporess/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!