新手向:使用Express搭建HTTP服务器并实现API

394 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

1273867169.jpg

之前的文章中曾用原生Node.js,也就是内置的http模块,搭建了一个简易的服务器,最直观的体验就是处理路由时非常复杂,并且需要自己指定状态码和头部信息

本文就使用Node.js的简易框架Express来解决以上问题,并简单做一下延伸,通过阅读本文,你将初步学会使用Express来:

  1. 搭建简易服务器,实现基本的路由导航
  2. API发送GET请求,使用路由参数,将本地JSON数据发送到客户端
  3. 利用中间件向API发送POST请求,从而往JSON文件添加内容

开发工具

nodemon

建议大家先安装一下Nodemon,它之于index.js,类似于Live Server之于index.html

以往要执行一个脚本,需要使用node index.js命令,如果index.js中的文件内容发生了变化,就需要重新执行一次,安装Nodemon之后,只需要使用nodemon index.js命令运行一次,之后如果脚本内容发生变化,nodemon会自动帮助我们重新运行。

安装命令如下:

npm install nodemon --save-dev -g

建议全局安装,这样在其它项目中也能使用

Postman

为了方便调试API接口,建议安装Postman,从官网下载安装包,一路Next完成安装

Express搭建服务器

在以下代码中,我们使用Express搭建了一个简易HTTP服务器,并定义了GET请求和POST请求的响应内容:

// index.js
const express = require('express');

const app = express();

app.get('/', (req, res) => {
  res
    .status(200)
    .json({ message: 'Hello from the server side!', app: 'Natours' }); 
});
app.post('/', (req, res) => {
  res.send('You can post to this endpoint');
});

const port = 3000;

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

在命令行输入nodemon index.js,可以看到每次index.js有所改动时,nodemon都会自动帮我们启动服务器:

image.png

代码解读

  • 我们首先用 express() 函数创建一个服务器对象
  • 然后用路由定义方法 app.get 和app.post定义了主页 / 的路由:res.status用于设置状态码,res.json用于向客户端发送JSON文件,将Content-type设置为application/json
  • 最后调用 listen 方法在3000端口开启服务器

接口测试:下面用Postman测试下接口,可以看到响应内容和状态码都对着呢:

image.png

image.png

GET请求

下面我们来使用GET请求获取本地的JSON数据:

const express = require('express');
const fs = require('fs');

const app = express();

const tours = JSON.parse(
  fs.readFileSync(`${__dirname}/dev-data/data/tours-simple.json`)
);

app.get('/api/v1/tours', (req, res) => {
  res.status(200).json({
    status: 'success',
    results: tours.length,
    data: {
      tours,
    },
  });
});

const port = 3000;

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

可以看到跟上面那个例子相比,没有特殊的地方,只是增加了使用fs模块来读取本地JSON文件的部分,在Postman中测试接口127.0.0.1:3000/api/v1/tours的结果如下:

image.png

上面获取的是全部的JSON数据,实际开发中,我们可能只是按需获取JSON文件中的部分数据,比如接口/api/v1/tours/1返回的是一组数据,/api/v1/tours/5返回的又是另一组数据,下面将用路由参数实现这个需求

......
app.get('/api/v1/tours/:id', (req, res) => {
  const id = req.params.id * 1; // 字符串转换成数字
  const tour = tours.find(el => el.id === id);
  if (!tour) {
    return res.status(404).json({
      status: 'fail',
      message: 'Invalid ID',
    });
  }
  res.status(200).json({
    status: 'success',
    data: {
      tour,
    },
  });
});
......

代码解读

  • 通过在路由中使用冒号:就可以定义变量,并使用req.params来获取变量值。在上面的代码中,定义的变量是id,它的值由接口决定,需要注意的是req.params.id获取的数据格式是字符串,这里利用运算将其转换成了数字
  • 利用数组的.find方法来匹配id的值与JSON内容,最后得到对应的数据tour,返回给客户端
  • 针对JSON文件中没有的数据,将状态码设置为404,并返回相关的错误信息

接口测试

image.png

image.png

POST请求

仅仅获取数据怎么能满足我们的需求呢,下面我们用中间件和POST请求来向JSON文件中添加数据,代码如下:

const express = require('express');
const fs = require('fs');

const app = express();
// 中间件
app.use(express.json());

const tours = JSON.parse(
  fs.readFileSync(`${__dirname}/dev-data/data/tours-simple.json`)
);

app.post('/api/v1/tours', (req, res) => {

  const newId = tours[tours.length - 1].id + 1;
  const newTour = Object.assign({ id: newId }, req.body);

  tours.push(newTour);

  fs.writeFile(
    `${__dirname}/dev-data/data/tours-simple.json`,
    JSON.stringify(tours),
    () => {
      res.status(201).json({
        status: 'success',
        data: {
          tours,
        },
      });
    }
  );
});

const port = 3000;

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

代码解读:

  • 中间件express.json()的中间,指的是请求和响应的中间。这个案例中我们仅仅需要知道发送POST请求时需要app.use(express.json());这么一行代码就行了,关于中间件的详细介绍笔者后面会专门写一篇文章
  • 这里为添加的内容为newId和请求头,即req.body的内容,使用Object.assign()将内容合并到一个对象中,通过fs.writeFile写入到本地JSON文件中,并将最新的数据返回给客户端

接口测试: 下面在Postman中发送一个POST请求,来验证代码:

image.png Body中我们选中数据格式为JSON,并添加了nameduration两个属性值,发送POST请求之后,可以看到响应体中增加了写入的内容,并且状态码为201 Created🍺🍺🍺

总结

文本循序渐进向大家演示了如何使用Express创建HTTP服务器以及定义路由,然后结合Postman展示了如何使用路由参数来发送GET请求以获取本地JSON数据,以及如何利用中间件发送POST请求来添加数据。