express 简介

Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。
使用 Express 可以快速地搭建一个完整功能的网站
Express 框架核心特性:

  • 可以设置中间件来响应 HTTP 请求。
  • 定义了路由表用于执行不同的 HTTP 请求动作。
  • 可以通过向模板传递参数来动态渲染 HTML 页面。

    安装 Express

    $ cnpm install express —save

以上命令会将 Express 框架安装在当前目录的 node_modules 目录中, node_modules 目录下会自动创建 express 目录。以下几个重要的模块是需要与 express 框架一起安装的:

  • body-parser - node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据。
  • cookie-parser - 这就是一个解析Cookie的工具。通过req.cookies可以取到传过来的cookie,并把它们转成对象。
  • multer - node.js 中间件,用于处理 enctype=”multipart/form-data”(设置表单的MIME编码)的表单数据。

    $ cnpm install body-parser —save $ cnpm install cookie-parser —save $ cnpm install multer —save

express 常用api

app.get(path, callback [, callback …])

  1. app.get('/', function (req, res) {
  2. res.send('GET request to homepage')
  3. })

app.listen(path, [callback])

  1. var express = require('express')
  2. var app = express()
  3. app.listen(3000)
  4. ------------------
  5. var express = require('express')
  6. var https = require('https')
  7. var http = require('http')
  8. var app = express()
  9. http.createServer(app).listen(80)
  10. https.createServer(options, app).listen(443)

app.post(path, callback [, callback …])

  1. app.post('/', function (req, res) {
  2. res.send('POST request to homepage')
  3. })

app.put(path, callback [, callback …])

  1. app.put('/', function (req, res) {
  2. res.send('PUT request to homepage')
  3. })

app.use([path,] callback [, callback…])

  1. const express = require('express')
  2. const fs = require('fs')
  3. const { getDb, saveDb } = require('./db')
  4. const app = express()
  5. // 配置解析表单请求体:application/json
  6. app.use(express.json())
  7. // 解析表单请求体:application/x-www-form-urlencoded
  8. app.use(express.urlencoded())
  9. app.get('/todos', async (req, res) => {
  10. try {
  11. const { body, query } = req;
  12. console.log(16, body, query);
  13. const db = await getDb()
  14. res.status(200).json(db.todos)
  15. } catch (err) {
  16. res.status(500).json({
  17. error: err.message
  18. })
  19. }
  20. })
  21. app.get('/todos/:id', async (req, res) => {
  22. try {
  23. const db = await getDb()
  24. const todo = db.todos.find(todo => todo.id === Number.parseInt(req.params.id))
  25. if (!todo) {
  26. return res.status(404).end()
  27. }
  28. res.status(200).json(todo)
  29. } catch (err) {
  30. res.status(500).json({
  31. error: err.message
  32. })
  33. }
  34. })
  35. app.post('/todos', async (req, res) => {
  36. try {
  37. // 1. 获取客户端请求体参数
  38. const todo = req.body
  39. // 2. 数据验证
  40. if (!todo.title) {
  41. return res.status(422).json({
  42. error: 'The field title is required.'
  43. })
  44. }
  45. // 3. 数据验证通过,把数据存储到 db 中
  46. const db = await getDb()
  47. const lastTodo = db.todos[db.todos.length - 1]
  48. todo.id = lastTodo ? lastTodo.id + 1 : 1
  49. db.todos.push(todo)
  50. await saveDb(db)
  51. // 4. 发送响应
  52. res.status(201).json(todo)
  53. } catch (err) {
  54. res.status(500).json({
  55. error: err.message + 123
  56. })
  57. }
  58. })
  59. app.patch('/todos/:id', async (req, res) => {
  60. try {
  61. // 1. 获取表单数据
  62. const todo = req.body
  63. // 2. 查找到要修改的任务项
  64. const db = await getDb()
  65. const ret = db.todos.find(todo => todo.id === Number.parseInt(req.params.id))
  66. if (!ret) {
  67. return res.status(404).end()
  68. }
  69. Object.assign(ret, todo)
  70. await saveDb(db)
  71. res.status(200).json(ret)
  72. } catch (err) {
  73. res.status(500).json({
  74. error: err.message
  75. })
  76. }
  77. })
  78. app.delete('/todos/:id', async (req, res) => {
  79. try {
  80. const todoId = Number.parseInt(req.params.id)
  81. const db = await getDb()
  82. const index = db.todos.findIndex(todo => todo.id === todoId)
  83. if (index === -1) {
  84. return res.status(404).end()
  85. }
  86. db.todos.splice(index, 1)
  87. await saveDb(db)
  88. res.status(204).end()
  89. } catch (err) {
  90. res.status(500).json({
  91. error: err.message
  92. })
  93. }
  94. })
  95. app.listen(3000, () => {
  96. console.log(`Server running at http://localhost:3000/`)
  97. })

Request

properties

req.app (当callback为外部文件时,用req.app访问express的实例)

req.baseUrl (获取路由当前安装的URL路径)

  1. var greet = express.Router()
  2. greet.get('/jp', function (req, res) {
  3. console.log(req.baseUrl) // /greet
  4. res.send('Konichiwa!')
  5. })
  6. app.use('/greet', greet) // load the router on '/greet'

req.body (获得「请求主体」)

  1. var express = require('express')
  2. var app = express()
  3. app.use(express.json()) // for parsing application/json
  4. app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded
  5. app.post('/profile', function (req, res, next) {
  6. console.log(req.body)
  7. res.json(req.body)
  8. })

req.cookies ((获得「请求主体」))

// Cookie: name=tj console.dir(req.cookies.name) // => ‘tj’

req.fresh / req.stale:判断请求是否还「新鲜」

req.hostname/ req.ip (获取主机名和IP地址)

// Host: “example.com:3000” console.dir(req.hostname) // => ‘example.com’ console.dir(req.ip) // => ‘host’

req.params (获取路由的parameters)

// GET /file/javascripts/jquery.js
console.dir(req.params[0])
// => ‘javascripts/jquery.js’

req.path (获取请求路径)

// example.com/users?sort=desc console.dir(req.path) // => ‘/users’

req.protocol:获取协议类型

console.dir(req.protocol) // => ‘http’

req.query:获取URL的查询参数串

req.route:获取当前匹配的路由

req.subdomains:获取子域名

// Host: “tobi.ferrets.example.com” console.dir(req.subdomains) // => [‘ferrets’, ‘tobi’]

method

req.accepts():检查可接受的请求的文档类型

// Accept: text/html req.accepts(‘html’) // => “html”


req.accepts(‘png’)

// => false

req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码

req.get():获取指定的HTTP请求头

  1. req.get('Content-Type')
  2. // => "text/plain"
  3. req.get('content-type')
  4. // => "text/plain"
  5. req.get('Something')
  6. // => undefined

req.is():判断请求头Content-Type的MIME类型

  1. // With Content-Type: text/html; charset=utf-8
  2. req.is('html')
  3. // => 'html'
  4. req.is('text/html')
  5. // => 'text/html'
  6. req.is('text/*')
  7. // => 'text/*'
  8. // When Content-Type is application/json
  9. req.is('json')
  10. // => 'json'
  11. req.is('application/json')
  12. // => 'application/json'
  13. req.is('application/*')
  14. // => 'application/*'
  15. req.is('html')
  16. // => false

Response

properties

res.app:同req.app一样

methos

res.append():追加指定HTTP头

res.append(‘Link’, [‘http://localhost/‘, ‘http://localhost:3000/‘]) res.append(‘Set-Cookie’, ‘foo=bar; Path=/; HttpOnly’) res.append(‘Warning’, ‘199 Miscellaneous warning’)

res.set()在res.append()后将重置之前设置的头

res.cookie(name,value [,option]):设置Cookie

opition: domain / expires / httpOnly / maxAge / path / secure / signed

  1. res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true })
  2. res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })
  3. -----------------------
  4. res
  5. .status(201)
  6. .cookie('access_token', 'Bearer ' + token, {
  7. expires: new Date(Date.now() + 8 * 3600000) // cookie will be removed after 8 hours
  8. })
  9. .cookie('test', 'test')
  10. .redirect(301, '/admin')

res.clearCookie():清除Cookie

res.cookie(‘name’, ‘tobi’, { path: ‘/admin’ }) res.clearCookie(‘name’, { path: ‘/admin’ })

res.download():传送指定路径的文件

res.download(‘/report-12345.pdf’) res.download(‘/report-12345.pdf’, ‘report.pdf’) res.download(‘/report-12345.pdf’, ‘report.pdf’, function (err) { if (err) { // Handle error, but keep in mind the response may be partially-sent // so check res.headersSent } else { // decrement a download credit, etc. } })

res.get():返回指定的HTTP头

res.get(‘Content-Type’) // => “text/plain”

res.end()

res.end() res.status(404).end()

res.json():传送JSON响应

res.json(null) res.json({ user: ‘tobi’ }) res.status(500).json({ error: ‘message’ })

res.jsonp():传送JSONP响应

res.location():只设置响应的Location HTTP头,不设置状态码或者close response

res.redirect():设置响应的Location HTTP头,并且设置状态码302

res.redirect(‘/foo/bar’) res.redirect(‘http://example.com‘) res.redirect(301, ‘http://example.com‘) res.redirect(‘../login’)

res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。

// send the rendered view to the client 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) { // … })

res.send():传送HTTP响应

res.send(Buffer.from(‘whoop’)) res.send({ some: ‘json’ }) res.send(‘

some html

‘) res.status(404).send(‘Sorry, we cannot find that!’) res.status(500).send({ error: ‘something blew up’ })

res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type

res.set():设置HTTP头,传入object可以一次设置多个头

res.set(‘Content-Type’, ‘text/plain’) res.set({ ‘Content-Type’: ‘text/plain’, ‘Content-Length’: ‘123’, ETag: ‘12345’ })

res.status():设置HTTP状态码

res.status(403).end() res.status(400).send(‘Bad Request’) res.status(404).sendFile(‘/absolute/path/to/404.png’)

res.type():设置Content-Type的MIME类型

res.type(‘.html’) // => ‘text/html’ res.type(‘html’) // => ‘text/html’ res.type(‘json’) // => ‘application/json’ res.type(‘application/json’) // => ‘application/json’ res.type(‘png’) // => ‘image/png’