如何在 Ubuntu 18.04 上使用 Node.js 和 Express 创建 CRUD API
CodeTips致力于帮助零基础或经验很少的初学者学习编程。
我们确实会将文章交叉发布到其他网站以覆盖更广泛的受众,但为什么不订阅我们的新闻通讯,直接在您的邮箱中获取最新文章呢?
本文内容最初来源于CodeTips。原始内容会保持更新,但其他来源的内容可能不是最新版本。
介绍
API(应用程序编程接口)是一种通过一系列预定义的请求与服务进行交互的方式。
Express 是一个基于 Node.js 的开源 Web 框架,旨在简化网站、Web 应用程序和 API 的开发。
在本教程中,您将在一台 Ubuntu 18.04 服务器上创建一个简单的 CRUD API。该 API 将通过公共 IP 地址访问,因此您可以从任何有互联网连接的地方访问它。
立即使用此推荐链接注册 Digital Ocean ,即可获得 100 美元信用额度!
先决条件
- 按照 Ubuntu 18.04 服务器初始设置指南中的说明,进行 Ubuntu 18.04 服务器设置。您应该拥有一个具有 sudo 权限的非 root 用户和一个已启用的防火墙。
- 按照如何在 Ubuntu 18.04 上设置用于生产的 Node.js 应用程序中的说明,在您的 Ubuntu 18.04 服务器上安装了 Node.js 和 PM2 。
- 对 CURL 的基本了解
步骤 1 — 创建一个简单的 Express 应用,提供“Hello World”程序。
在这一步中,我们将创建一个非常简单的 API,只有一个端点,然后在后续步骤中以此为基础进行构建。
首先,在您选择的位置创建一个新目录,并package.json通过在终端中运行以下命令来创建一个默认文件:
npm init -y
在同一终端中,安装express依赖项:
npm i express
接下来,在您选择的代码编辑器中打开项目并创建一个新server.js文件。
在新文件中,添加以下代码:
const express = require('express')
const app = express()
const port = 3000
app.get('/hello', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`App listening on port ${port}!`))
使用该express应用程序,我们定义一个/hello端点,该端点将返回文本Hello World!,并在端口上运行我们的应用程序3000。
请注意,该/hello端点仅匹配 GET 请求,因为我们已使用该app.get方法对其进行了定义。
在终端中运行以下命令来启动应用程序:
node index.js
你应该会看到以下输出结果:
$ node index.js
App listening on port 3000!
现在打开你常用的浏览器,并访问localhost:3000/hello。如果一切顺利,Hello World!浏览器中应该会显示 。
恭喜!您已创建了一个 API,现在可以通过端点与之通信/hello。接下来,我们将在此基础上进行扩展,使我们的 API 更加完善!
步骤 2 — 扩展应用程序以从内存状态获取属性。
目前我们只有一个端点,/hello它会返回文本Hello World!。虽然我们创建了一个 API,这很棒,但就功能而言,它并不十分有用。
在这一步中,我们将使用 API 并使其返回一些有用的数据。我们将以员工详细信息为例。
首先,让我们在应用程序中添加另一个端点,用于检索记录。
const express = require('express')
const app = express()
const port = 3000
app.get('/hello', (req, res) => res.send('Hello World!'))
app.get('/employee/:id', (req, res) => {
console.log(req.params.id)
res.sendStatus(200)
})
app.listen(port, () => console.log(`App listening on port ${port}!`))
我们定义了一个新的/employee端点,就像我们之前对/hello端点所做的那样,但我们也使用了查询参数。
查询参数使用冒号定义,前面的文本用于引用该参数。在我们的/employee端点中,我们定义了一个名为 `<parameter_name>` 的查询参数id,以下console.log语句展示了我们如何引用该参数的值。
停止并启动应用程序,以便新的代码更改生效,打开浏览器并导航到http://localhost:3000/employee/wiggly。
结果,您应该在终端中看到以下输出:
$ node index.js
App listening on port 3000!
wiggly
注意wiggly终端输出的内容,也就是我们在 URL 中使用的内容(/employee/wiggly)。wiggly你可以将其更改为任何你想要的内容,并查看终端输出。
这项技术的强大之处在于,我们只需定义一条路由,即可用于多种不同的场景。例如,我们可以创建一个端点,使用唯一标识符检索员工的详细信息,而这正是我们现在要做的事情!
让我们创建一个对象,作为应用程序的内存状态,并添加一些虚拟员工:
/**
We'll use the Object key as the unique identifier, made up of the
first letter of the employees first name and whole of their last name.
*/
const employees = {
'sbrown': {
firstName: 'Steve',
lastName: 'Brown',
department: 'Engineering'
},
'jsmith': {
firstName: 'Janine',
lastName: 'Smith',
department: 'Marketing'
},
'kjones': {
firstName: 'Karen',
lastName: 'Jones',
department: 'Sales'
},
'bwilliams': {
firstName: 'Ben',
lastName: 'Williams',
department: 'Administration'
}
}
现在,我们不再记录id参数值,而是从对象中返回员工详细信息:
app.get('/employee/:id', (req, res) => {
res.json(employees[req.params.id])
})
由于我们将返回一个 JSON 对象,因此我们使用该res.json方法,该方法除其他事项外,还会设置所有正确的标头并以 JSON 格式返回响应。
http://localhost:3000/employee/kjones重启应用程序,然后在浏览器中访问。
您应该在浏览器中看到以下响应:
{"firstName":"Karen","lastName":"Jones","department":"Sales"}
尝试将对象kjones中的任何其他唯一标识符更改为其他标识符,employees并查看返回值的变化。
现在,尝试在浏览器中将值更改id为不存在的值(例如http://localhost:3000/employee/wiggly)。不会返回任何内容,这是正确的,但我们没有向用户提供任何原因的提示;是出了什么问题,还是该员工根本不存在?
让我们更新端点,检查给定的员工是否id存在,如果不存在,则返回一个404 Not Found响应;否则,返回员工详细信息。
app.get('/employee/:id', (req, res) => {
const employee = employees[req.params.id]
if (!employee) {
return res.sendStatus(404)
}
res.json(employee)
})
重启应用程序,然后在浏览器中尝试相同的 URL。现在应该会得到更详细的响应Not Found,这对用户来说信息更丰富。
在这一步中,我们把一个非常简单且不太实用的 API 改造成了一个可以使用查询参数查询数据的 API。我们还学习了如何处理查询不存在的员工信息的情况。
步骤 2 — 扩展应用程序,以从内存状态中添加/删除属性。
我们现在有一个可以根据员工 ID 检索员工的 API,但是如果员工加入/离开公司怎么办?我们需要一种方法来将他们添加到员工列表中/从员工列表中删除,这就是我们将在这一步中实现的目标。
我们先来关注新员工入职的情况。当有人入职时,我们希望将他们添加到我们的employees对象中,以便以后可以查询他们。
为此,我们将使用POST请求,其声明方式与上面的请求相同GET。
app.post('/employee', (req, res) => {
res.sendStatus(200)
})
请重启应用程序以应用我们的代码更改。
我们的新路由除了返回状态之外什么也不做,200 OK因为在编写逻辑之前,我想先谈谈我们如何发出POST请求。
当你在浏览器中输入地址时,就像我们在前面的步骤中所做的那样(例如http://localhost:3000/hello),我们就是在通过发出请求来请求资源GET。
我们不能使用相同的机制来发出任何其他类型的请求(POST例如PUT,DELETE等等),那么我们如何访问这些端点呢?有很多不同的方法,但我们只关注其中一种——CURL。
要POST使用 CURL 向我们的新端点发出请求,请在终端中运行以下命令:
curl -X POST 'http://localhost:3000/employee'
我们在新端点中添加的唯一功能是返回200 OK状态,也就是您应该在终端中看到的响应。
$ curl -X POST 'http://localhost:3000/employee'
OK
让我们构建这个逻辑,将一名员工添加到我们的employees对象中。
我们首先需要做的是获取新员工的详细信息。如果我们查看现有员工的信息,我们需要三项信息—— firstName,lastName和department。
上一节中,我们使用req.params属性提取了idURL 参数。处理请求时POST,我们还可以使用请求体。
使用 CURL,我们可以结合 Header ( -H) 标志来指定内容类型,该标志会告知服务器请求内容的格式,以及 Data ( --data) 标志来传递 JSON 对象。
我们将发送一个 JSON 对象,因此我们将设置一个Content-Type标头或application/json,告诉服务器我们正在发送 JSON,并将我们的新员工指定为数据:
CURL -X POST 'http://localhost:3000/employee' -H 'content-type: application/json' --data '{"firstName": "John", "lastName": "Doe", "department": "engineering"}'
我们现在向 发出POST请求,http://localhost:3000/employee并将上述 JSON 对象作为请求正文。
默认情况下,我们的 Express 应用程序不会解析此 JSON 对象,因此我们需要启用一些中间件来启用它。
const express = require('express')
const app = express()
const port = 3000
/**
-- Employee object
*/
/**
Middleware that looks at requests with an application/json
Content-Type header and stores the request body, as JSON,
in req.body
*/
app.use(express.json())
/**
-- Other endpoints
*/
app.post('/employee', (req, res) => {
console.log(req.body)
res.sendStatus(200)
})
在定义任何路由之前,请先告知您的系统app使用express.json中间件。然后,在新端点中记录请求正文。
重启应用程序,然后使用 CURL 发送请求,请求体为 JSON 格式。运行应用程序的终端应该会输出以下信息:
$ node index.js
App listening on port 3000!
{ firstName: 'John', lastName: 'Doe', department: 'engineering' }
现在我们可以从新的POST端点接收一个新的员工对象,所以让我们构建逻辑以确保我们获得所有三个必需字段(firstName,lastName和),根据和department构造,然后将其添加到我们的对象中(如果该对象尚未被使用)。idfirstNamelastNameemployeeid
app.post('/employee', (req, res) => {
const { firstName, lastName, department } = req.body
if (!firstName || !lastName || !department) {
// 400 = bad request. It indicates to the user that
// there was something wrong with their request.
return res.status(400).send('One or more required fields are missing')
}
const id = (firstName[0] + lastName).toLowerCase()
if (employees[id]) {
// Provide a custom message so the user knows what the
// problem with the request is.
return res.status(400).send('A user with that id already exists')
}
// We set the employee properties explicitly, just in case
// the user sends other fields through that we're not interested
// in storing.
employees[id] = { firstName, lastName, department }
res.sendStatus(200)
})
重启应用程序并尝试以下场景:
- 提交
POST请求时,请省略一个或多个必填字段。 - 发出一个
POST带有 a 的请求firstName,lastName该请求会创建一个id已经存在的 a(例如,Sarah Brown这将与 a 冲突Steve Brown)。 - 先发出一个
POST请求并获得成功,然后再发出一个GET请求来检索新员工的详细信息。
现在,让我们运用目前所学的知识创建一个新的DELETE端点,该端点接收一个员工id并将其从我们的对象中移除employees。
app.delete('/employee/:id', (req, res) => {
const employee = employees[req.params.id]
if (!employee) {
return res.sendStatus(404)
}
delete employees[req.params.id];
res.sendStatus(200)
})
你会注意到这与我们的员工端点非常相似GET;我们使用 URL 参数,检查员工是否存在,200如果一切顺利则返回状态。唯一的区别是我们通过员工employees的id.
使用CURL 发出请求与我们上面看到的请求DELETE非常相似:POST
curl -X DELETE 'http://localhost:3000/employee/sbrown'
重启应用程序并尝试以下操作:
DELETE使用现有员工id(例如)向我们的新端点发出请求http://localhost:3000/employees/sbrown。GET使用同一员工id(例如)向我们的员工端点发出请求,http://localhost:3000/employees/sbrown并查看您现在是否收到404 Not Found响应。
恭喜——您已创建了一个 CRUD API!
POST在这一步中,我们真正将 API 提升到了一个新的水平,允许用户添加和删除员工,并且我们通过启用中间件学习了如何处理数据express.json。
步骤 3 — 将 API 部署到 Digital Ocean
我们现在有了一个可以创建、删除和检索员工信息的API。目前为止我们取得的成果非常棒,但它只存在于我们的笔记本电脑上。为了将我们的应用程序提升到一个新的水平,我们需要将其托管在一个可以公开访问的服务器上,以便我们可以从世界任何地方访问它。
根据我们的前提条件,您需要一台 Digital Ocean 服务器。首先,请在您的服务器上创建一个新目录。
$ mkdir ~/simple-crud
接下来,在本地项目目录下的终端中,运行以下命令,将必要的文件复制到服务器:
$ scp package-lock.json package.json server.js ubuntu@YOUR_IP:./simple-crud/
将 `<user>`替换ubuntu为您创建的用户,并将YOUR_IP` 替换为您的服务器公网 IP 地址。
我们现在已经将我们的文件复制package-lock.json到package.json服务器上的server.js新文件夹中。simple-crud
simple-crud接下来,在服务器上的文件夹中,安装应用程序的依赖项:
`
$ npm i
`
最后,使用 PM2 启动应用程序:
`
$ pm2 start server.js --name "simple-crud"
`
为确保应用程序已正确启动,您可以运行该pm2 logs程序并确保看到以下日志行:
`
$ pm2 logs
0|simple-c | App listening on port 3000!
`
接下来,我们将修改默认的 NGINXserver代码块,将所有请求转发到我们的应用程序。
用于vi编辑默认配置:
`
$ sudo vi /etc/nginx/sites-available/default
`
然后,将根位置(location /)替换为以下代码,该代码会将所有 HTTP 请求转发到我们的应用程序。
`
location / {
proxy_pass http://localhost:3000 ;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $
}
`
在这一步中,我们将应用程序从只能在笔记本电脑上运行,升级到在 Digital Ocean 服务器上运行,这意味着我们的应用程序可以从世界任何地方访问!
步骤 4 — 使用我们托管在 Digital Ocean 上的新 API,而不是本地主机。
我们现在有一个运行在 Digital Ocean 服务器上的应用程序,可以从世界任何地方访问。我们知道如何在本地访问我们的 API,但现在我们该如何与它交互呢?
我们只需localhost在 CURL 命令中将地址替换为我们的公网 IP 地址即可:
`
$ curl -X GET ' http://157.245.243.1/employee/sbrown '
{"firstName":"Steve","lastName":"Brown","department":"Engineering"}
$ curl -X POST ' http://157.245.243.1/employee ' -H 'content-type: application/json' --data '{"firstName": "John", "lastName": "Doe", "department": "engineering"}'
OK
curl -X DELETE ' http://157.245.243.1/employee/jsmith '
OK
`
结论
您已成功创建了一个具有内存状态的 CRUD API,并将其部署到 Digital Ocean 服务器,这意味着您可以使用公共 IP 地址从任何地方与其交互。
CodeTips致力于帮助零基础或经验很少的初学者学习编程。
我们确实会将文章交叉发布到其他网站以覆盖更广泛的受众,但为什么不订阅我们的新闻通讯,直接在您的邮箱中获取最新文章呢?
本文内容最初来源于CodeTips。原始内容会保持更新,但其他来源的内容可能不是最新版本。
文章来源:https://dev.to/codetips/how-to-create-a-crud-api-using-node-js-and-express-on-ubuntu-18-04-24h8
