HolyZheng / holyZheng-blog

草稿
36 stars 0 forks source link

express build RESTful APIs #28

Open HolyZheng opened 5 years ago

HolyZheng commented 5 years ago

定义

express是一个node的框架,对node进行了封装,提供了http method等多个api,request和respond等对象和router等中间件。一个简单的例子:

const express = require('express')
let app = express()

app.get('/', (req, res) => {
  res.send('hello !')
})

app.get('/api/courses', (req, res) => {
  res.send([1, 2, 3])
})

app.listen(3000, () => {
  console.log('start!')
})

nodemon

用来监视文件改动,自动重启服务的工具。

nodemon index.js

环境变量

可以通过process对象来访问环境变量,来动态的决定一些变量的值。

const express = require('express')
const app = express()

const port = process.env.PORT || 3000

app.listen(port, () => {
  console.log(`listen on port ${port}`)
})

然后启动时动态设置PORT的值。但是不同平台有不同的语法。

For just one run (from the unix shell prompt):

$ PORT=1234 node app.js
More permanently:

$ export PORT=1234
$ node app.js
In Windows:

set PORT=1234
In Windows PowerShell:

$env:PORT = 1234

可以使用 cross-env 这个库来解决不同操作系统间语法不一致问题。

$ cross-env PORT=5000  node index.js
listen on port 5000

要注意的是,两个语句要放一起不能分开或用&&连接,因为这样会划分为两个环境变量,后一句启动的服务无法访问到前面设置的环境变量。

请求参数

获取 RESTful api 的 url 中的参数。

const express = require('express')
const app = express()

app.get('/api/courses/:id/:name', (req, res) => {
  res.send(req.params)
})

const port = process.env.PORT || 3000

app.listen(port, () => {
  console.log(`listen on port ${port}`)
})
// http://localhost:3000/api/courses/1/holyzheng
{
id: "1",
name: "holyzheng"
}
// http://localhost:3000/api/courses/1/holyzheng?year=2018

app.get('/api/courses/:id/:name', (req, res) => {
  res.send(`
    params: ${JSON.stringify(req.params)},
    query: ${JSON.stringify(req.query)}
  `)
})

// params: {"id":"1","name":"holyzheng"}, query: {"year":"2018"}

一个较完整的app

// 用于校验 req.body
const Joi = require('joi')
const express = require('express')
const app = express()

app.use(express.json())

// mock数据
const courses = [
  {id: 1, name: 'course1'},
  {id: 2, name: 'course2'},
  {id: 3, name: 'course3'}
]

app.get('/', (req, res) => {
  res.send('Hello World')
})

app.get('/api/courses', (req, res) => {
  res.send(courses)
})

// 查询某一条数据
app.get('/api/courses/:id', (req, res) => {
  const course = courses.find(c => c.id === parseInt(req.params.id))
  if (!course) return res.status(404).send('The course with the given ID was not exit!')
  res.send(course)
})

// 增加数据
app.post('/api/courses', (req, res) => {

  const {error} = validateCourse(req.body)
  if (error) return res.status(400).send(error.message)

  const course = {
    id: courses.length + 1,
    name: req.body.name
  }
  courses.push(course)
  res.send(course)
})

// 更新某一条数据
app.put('/api/courses/:id', (req, res) => {
  const course = courses.find(c => c.id === parseInt(req.params.id))
  if (!course) return res.status(404).send('The course with the given ID was not exit!')

  const {error} = validateCourse(req.body)
  if (error) {
    res.status(400).send(error.message)
    return
  }

  course.name = req.body.name
  res.send(course)
})

// 删除某一条数据
app.delete('/api/courses/:id', (req, res) => {
  const course = courses.find(c => c.id === parseInt(req.params.id))
  if (!course) return res.status(404).send('The course with the given ID was not exit!')

  const index = courses.indexOf(course)
  courses.splice(index, 1)

  res.send(course)
})

// 利用 Joi 校验参数
function validateCourse(course) {
  const schema = {
    name: Joi.string().min(3).required()
  }

  return Joi.validate(course, schema)
}

const port = process.env.PORT || 3000

app.listen(port, () => {
  console.log(`listen on port ${port}`)
})