Node.js express 模块

文档

英文API文档
https://expressjs.com/en/api.html
中文API文档
https://expressjs.com/zh-cn/4x/api.html
https://www.runoob.com/w3cnote/express-4-x-api.html

在 Express 中提供静态文件

提供静态文件不是个简单的事情,比如说对MIME类型Content-Type的识别,但对于express来说就是一句代码的问题:

app.use(express.static('./www'))

要使用多个静态资源目录,可以多次调用 express.static 中间件函数,express根据顺序来查找文件:
同时,绝对路径比较安全:

app.use(express.static(`${__dirname}/www`))
app.use(express.static('/var/www/html'))

要为 express.static 函数提供的文件创建虚拟路径前缀(路径并不实际存在于文件系统中),请为静态目录指定安装路径,如下所示:

app.use('/static', express.static('public'));

现在,可以访问具有 /static 路径前缀的 public 目录中的文件。

http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html

如何处理 404 响应?

在 Express 中,404 响应不是错误的结果,所以错误处理程序中间件不会将其捕获。此行为是因为 404 响应只是表明缺少要执行的其他工作;换言之,Express 执行了所有中间件函数和路由,且发现它们都没有响应。您需要做的只是在堆栈的最底部(在其他所有函数之下)添加一个中间件函数来处理 404 响应:

app.use(function(req, res, next) {
  // res.status(404).send('Sorry cant find that!');
  res.status(404).json({
    msg: "Unknown Request"
  })
});

也可以编写一个404.html页面

<!DOCTYPE HTML>
<html lang="zh">
<metadata charset="utf-8">
<title>404</title>
<h1>404 Unknown Request</h1>
</html>
app.use(function(req, res, next) {
  res.status(404).sendFile(`${__dirname}/404.html`)
});

路由 https://expressjs.com/zh-cn/guide/routing.html

路由表示应用程序端点 (URI) 的定义以及端点响应客户机请求的方式,用于确定应用程序如何响应对特定端点的客户机请求,包含一个 URI(或路径)和一个特定的 HTTP 请求方法(GET、POST 等)。每个路由可以具有一个或多个处理程序函数,这些函数在路由匹配时执行。

Request 和 Response 对象

Request

    req.app:当callback为外部文件时,用req.app访问express的实例
    req.baseUrl:获取路由当前安装的URL路径
    req.body / req.cookies:获得「请求主体」/ Cookies
    req.fresh / req.stale:判断请求是否还「新鲜」
    req.hostname / req.ip:获取主机名和IP地址
    req.originalUrl:获取原始请求URL
    req.params:获取路由的parameters
    req.path:获取请求路径
    req.protocol:获取协议类型
    req.query:获取URL的查询参数串
    req.route:获取当前匹配的路由
    req.subdomains:获取子域名
    req.accepts():检查可接受的请求的文档类型
    req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
    req.get():获取指定的HTTP请求头
    req.is():判断请求头Content-Type的MIME类型

Response

    res.app:同req.app一样
    res.append():追加指定HTTP头
    res.set()在res.append()后将重置之前设置的头
    res.cookie(name,value [,option]):设置Cookie
    opition: domain / expires / httpOnly / maxAge / path / secure / signed
    res.clearCookie():清除Cookie
    res.download():传送指定路径的文件
    res.get():返回指定的HTTP头
    res.json():传送JSON响应
    res.jsonp():传送JSONP响应
    res.location():只设置响应的Location HTTP头,不设置状态码或者close response
    res.redirect():设置响应的Location HTTP头,并且设置状态码302
    res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
    res.send():传送HTTP响应
    res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
    res.set():设置HTTP头,传入object可以一次设置多个头
    res.status():设置HTTP状态码
    res.type():设置Content-Type的MIME类型

路由的一个例子:

#!/usr/bin/env nodemon

/* modules */
const express = require('express')

/* global object */
const config = require(`${__dirname}/config.json`)
const app = express()

/* logic */
app.all('*', (req, res, next) => {
        console.log(`new request -> ${req.url}`)
        next() // pass control to the next handler
})

// static resource
app.use(/* root */ '/', express.static(`${__dirname}/www`))

app.get('/', (req, res) => {
        res.sendFile(`${__dirname}/www/index.html`)
})

// 匹配通配符路径的所有HTTP动词
// app.all()方法路由所有动词
// 路由路径支持通配符* 
app.all('/test/*', (req, res) => {
        res.status(200).json({
                msg: "this is a test msg"
        })  
})

/* 404 */
// 栈底的处理器就是404处理器
app.use(function(req, res, next) {
        res.status(404).sendFile(`${__dirname}/www/404.html`)
});

// listen
app.listen(config.port, config.host, () => console.log(`Application started on http://${config.host}:${config.port}`))

重定向

res.status(302).location('/index.html')
res.end()

或者

res.redirect('/index.html')

详解 (req, res, next) => {}

  • req
    通过req可以访问到的对象有:
    req.protocol 协议
    req.hostname 主机名
    req.url url(带查询字符串)
    req.path uri(所谓path)
    req.headers Header对象,获取单个Header值也可使用函数header(key)
    查询字符串已经被解析为key-value对象req.query,要获取原始查询字符串,使用req._parsedUrl.query,无查询时其值为null
console.log(`URL: ${req.protocol}://${req.hostname}${req.url} path: ${req.path} query: ${req._parsedUrl.query}`);
  • res
    res最重要的角色是方法,这些方法决定你能如何响应HTTP请求:
    普通文本:
    res.end(string | Buffer) // http模块原生方法,不设置Content-Type
    res.write(string) // 同end(), 在end()之前可多次调用
    res.send(string | object) // 该方法自动设置Content-Type, 支持text/html、application/json等
    重定向:
    res.redirect(location: String)
    res.status(301 | 302).location(location: String).send('redirect to /index')
    发送JSON对象、静态文件:
    res.json(string | object) // 强制Content-Type为application/json
    res.sendFile(path: String) // 该方法自动根据文件后缀设置Content-Type, 默认为application/octet-stream
    设置Header:
    res.set(key: String, value: String) OR
    res.set({ key1: value1, key2: value2 }) // 一次性设置多个Header
    当然,使用http模块的res.setHeader(key, value)也是可以的,不过太局限了,添加和移除响应头的顺序可以随意,但一定要在调用 res.write() 或 res.end() 之前。在响应主体的第一部分写入之后,Node会刷新已经设定好的HTTP头。
    删除Header:
    res.removeHeader('X-Powered-By');
    设置响应码:
    res.statusCode = number // http模块原生方式
    res.status(number).use(res) // 链式调用

不确定Content-Length的response

有时在发送响应头时无法预先确定响应体的大小,可以连续调用write()函数,最后调用end()函数结束。
node.js应该主动断开连接,从而结束本次HTTP请求,避免客户端盲等。

END

posted @ 2019-12-29 14:29  develon  阅读(530)  评论(0编辑  收藏  举报