Xây dựng API REST với Node.js và Express:Kết nối cơ sở dữ liệu
Trong hướng dẫn đầu tiên, Tìm hiểu về các API RESTful, chúng ta đã tìm hiểu kiến trúc REST là gì, các phương thức và phản hồi yêu cầu HTTP là gì cũng như cách hiểu điểm cuối RESTful API. Trong hướng dẫn thứ hai, Cách thiết lập Máy chủ API Express, chúng ta đã học cách xây dựng máy chủ với cả http
tích hợp sẵn của Node mô-đun và khung Express cũng như cách định tuyến ứng dụng mà chúng tôi đã tạo đến các điểm cuối URL khác nhau.
Hiện tại, chúng tôi đang sử dụng dữ liệu tĩnh để hiển thị thông tin người dùng dưới dạng nguồn cấp dữ liệu JSON khi điểm cuối API được nhấn bằng GET
yêu cầu. Trong hướng dẫn này, chúng tôi sẽ thiết lập cơ sở dữ liệu MySQL để lưu trữ tất cả dữ liệu, kết nối với cơ sở dữ liệu từ ứng dụng Node.js của chúng tôi và cho phép API sử dụng GET
, POST
, PUT
và DELETE
các phương pháp để tạo một API hoàn chỉnh.
Cài đặt
Cho đến thời điểm này, chúng tôi chưa sử dụng cơ sở dữ liệu để lưu trữ hoặc thao tác bất kỳ dữ liệu nào, vì vậy chúng tôi sẽ thiết lập một cơ sở dữ liệu. Hướng dẫn này sẽ sử dụng MySQL và nếu bạn đã cài đặt MySQL trên máy tính của mình, bạn sẽ sẵn sàng chuyển sang bước tiếp theo.
Nếu bạn chưa cài đặt MySQL, bạn có thể tải xuống MAMP cho macOS và Windows, cung cấp cơ sở dữ liệu và môi trường máy chủ cục bộ miễn phí. Khi bạn đã tải xuống phần mềm này, hãy mở chương trình và nhấp vào Khởi động máy chủ để khởi động MySQL.
Ngoài việc tự thiết lập MySQL, chúng tôi sẽ muốn phần mềm GUI để xem cơ sở dữ liệu và bảng. Đối với Mac, tải xuống SequelPro và đối với Windows tải xuống SQLyog. Khi bạn đã tải xuống và chạy MySQL, bạn có thể sử dụng SequelPro hoặc SQLyog để kết nối với localhost
với tên người dùng root
và mật khẩu root
trên cổng 3306
.
Khi mọi thứ đã được thiết lập ở đây, chúng ta có thể chuyển sang thiết lập cơ sở dữ liệu cho API của mình.
Thiết lập cơ sở dữ liệu
Trong phần mềm xem cơ sở dữ liệu của bạn, hãy thêm một cơ sở dữ liệu mới và gọi nó là api
. Đảm bảo MySQL đang chạy, nếu không bạn sẽ không thể kết nối với localhost
.
Khi bạn có api
cơ sở dữ liệu được tạo, di chuyển vào đó và chạy truy vấn sau để tạo bảng mới.
CREATE TABLE `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT '', `email` varchar(50) DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Truy vấn SQL này sẽ tạo cấu trúc của users
của chúng tôi bàn. Mỗi người dùng sẽ có một id tăng dần tự động, tên và địa chỉ email.
Chúng tôi cũng có thể điền vào cơ sở dữ liệu với cùng một dữ liệu mà chúng tôi hiện đang hiển thị thông qua một mảng JSON tĩnh bằng cách chạy INSERT
truy vấn.
INSERT INTO users (name, email) VALUES ('Richard Hendricks', '[email protected]'), ('Bertram Gilfoyle', '[email protected]');
Không cần nhập id
, vì nó đang tự động tăng dần. Tại thời điểm này, chúng tôi có cấu trúc của bảng cũng như một số dữ liệu mẫu để làm việc.
Kết nối với MySQL
Quay lại ứng dụng của chúng tôi, chúng tôi phải kết nối với MySQL từ Node.js để bắt đầu làm việc với dữ liệu. Trước đó, chúng tôi đã cài đặt mysql
mô-đun npm và bây giờ chúng ta sẽ sử dụng nó.
Tạo một thư mục mới có tên là dữ liệu và tạo config.js tệp.
Chúng tôi sẽ bắt đầu bằng cách yêu cầu mysql
mô-đun trong data / config.js .
const mysql = require('mysql');
Hãy tạo một config
đối tượng chứa máy chủ, người dùng, mật khẩu và cơ sở dữ liệu. Điều này nên tham khảo api
cơ sở dữ liệu chúng tôi đã tạo và sử dụng cài đặt máy chủ cục bộ mặc định.
// Set database connection credentials const config = { host: 'localhost', user: 'root', password: 'root', database: 'api', };
Để đạt hiệu quả, chúng tôi sẽ tạo một nhóm MySQL, cho phép chúng tôi sử dụng nhiều kết nối cùng một lúc thay vì phải mở và đóng nhiều kết nối theo cách thủ công.
// Create a MySQL pool const pool = mysql.createPool(config);
Cuối cùng, chúng tôi sẽ xuất nhóm MySQL để ứng dụng có thể sử dụng nó.
// Export the pool module.exports = pool;
Bạn có thể xem tệp cấu hình cơ sở dữ liệu hoàn chỉnh trong kho GitHub của chúng tôi.
Bây giờ chúng tôi đang kết nối với MySQL và cài đặt của chúng tôi đã hoàn tất, chúng tôi có thể chuyển sang tương tác với cơ sở dữ liệu từ API.
Lấy dữ liệu API từ MySQL
Hiện tại, routes.js
của chúng tôi tệp đang tạo một mảng người dùng JSON theo cách thủ công, trông giống như thế này.
const users = [{ ...
Vì chúng tôi sẽ không sử dụng dữ liệu tĩnh nữa, chúng tôi có thể xóa toàn bộ mảng đó và thay thế nó bằng một liên kết đến nhóm MySQL của chúng tôi.
// Load the MySQL pool connection const pool = require('../data/config');
Trước đây, GET
cho /users
đường dẫn đang gửi users
tĩnh dữ liệu. Thay vào đó, mã cập nhật của chúng tôi sẽ truy vấn cơ sở dữ liệu cho dữ liệu đó. Chúng tôi sẽ sử dụng truy vấn SQL để SELECT
tất cả từ users
bảng trông như thế này.
SELECT * FROM users
Đây là những gì /users
mới của chúng tôi lấy tuyến sẽ như thế nào, bằng cách sử dụng pool.query()
phương pháp.
// Display all users app.get('/users', (request, response) => { pool.query('SELECT * FROM users', (error, result) => { if (error) throw error; response.send(result); }); });
Ở đây, chúng tôi đang chạy SELECT
truy vấn và sau đó gửi kết quả dưới dạng JSON đến máy khách qua /users
điểm cuối. Nếu bạn khởi động lại máy chủ và điều hướng đến /users
, bạn sẽ thấy dữ liệu giống như trước đây, nhưng bây giờ là dữ liệu động.
Sử dụng Tham số URL
Cho đến nay, các điểm cuối của chúng tôi là các đường dẫn tĩnh — /
root hoặc /users
—Nhưng còn khi chúng ta chỉ muốn xem dữ liệu về một người dùng cụ thể thì sao? Chúng tôi sẽ cần sử dụng một điểm cuối có thể thay đổi.
Đối với người dùng của chúng tôi, chúng tôi có thể muốn truy xuất thông tin về từng người dùng riêng lẻ dựa trên id duy nhất của họ. Để làm điều đó, chúng tôi sẽ sử dụng dấu hai chấm (:
) để biểu thị rằng đó là một tham số tuyến đường.
// Display a single user by ID app.get('/users/:id', (request, response) => { ... }); });
Chúng tôi có thể truy xuất tham số cho đường dẫn này bằng request.params
bất động sản. Vì của chúng tôi được đặt tên là id
, đó sẽ là cách chúng tôi đề cập đến nó.
const id = request.params.id;
Bây giờ chúng ta sẽ thêm một WHERE
mệnh đề SELECT
của chúng tôi câu lệnh để chỉ nhận kết quả có id
được chỉ định .
Chúng tôi sẽ sử dụng ?
như một trình giữ chỗ để tránh việc đưa vào SQL và chuyển id qua dưới dạng một tham số, thay vì xây dựng một chuỗi được nối, sẽ kém an toàn hơn.
pool.query('SELECT * FROM users WHERE id = ?', id, (error, result) => { if (error) throw error; response.send(result); });
Mã đầy đủ cho tài nguyên người dùng cá nhân của chúng tôi bây giờ trông giống như sau:
// Display a single user by ID app.get('/users/:id', (request, response) => { const id = request.params.id; pool.query('SELECT * FROM users WHERE id = ?', id, (error, result) => { if (error) throw error; response.send(result); }); });
Bây giờ bạn có thể khởi động lại máy chủ và điều hướng đến https://localhost/users/2
để chỉ xem thông tin cho Gilfoyle. Nếu bạn gặp lỗi như Cannot GET /users/2
, điều đó có nghĩa là bạn cần khởi động lại máy chủ.
Đi đến URL này sẽ trả về một kết quả duy nhất.
[{ id: 2, name: "Bertram Gilfoyle", email: "[email protected]" }]
Nếu đó là những gì bạn thấy, xin chúc mừng:bạn đã thiết lập thành công thông số tuyến đường động!
Gửi yêu cầu ĐĂNG
Cho đến nay, mọi thứ chúng tôi đang làm đều sử dụng GET
các yêu cầu. Các yêu cầu này an toàn, có nghĩa là chúng không làm thay đổi trạng thái của máy chủ. Chúng tôi chỉ đơn giản là đang xem dữ liệu JSON.
Bây giờ chúng ta sẽ bắt đầu làm cho API thực sự năng động bằng cách sử dụng POST
yêu cầu thêm dữ liệu mới.
Tôi đã đề cập trước đó trong bài viết Hiểu về REST rằng chúng ta không sử dụng các động từ như add
hoặc delete
trong URL để thực hiện các hành động. Để thêm người dùng mới vào cơ sở dữ liệu, chúng tôi sẽ POST
đến cùng một URL mà chúng tôi xem chúng, nhưng chỉ cần thiết lập một tuyến đường riêng cho nó.
// Add a new user app.post('/users', (request, response) => { ... });
Lưu ý rằng chúng tôi đang sử dụng app.post()
thay vì app.get()
bây giờ.
Vì chúng tôi đang tạo thay vì đọc, chúng tôi sẽ sử dụng INSERT
truy vấn ở đây, giống như chúng ta đã làm lúc khởi tạo cơ sở dữ liệu. Chúng tôi sẽ gửi toàn bộ request.body
thông qua truy vấn SQL.
pool.query('INSERT INTO users SET ?', request.body, (error, result) => { if (error) throw error;
Chúng tôi cũng sẽ chỉ định trạng thái của phản hồi là 201
, viết tắt của Created
. Để lấy id của mục được chèn cuối cùng, chúng tôi sẽ sử dụng insertId
tài sản.
response.status(201).send(`User added with ID: ${result.insertId}`);
Toàn bộ POST
của chúng tôi mã nhận được sẽ giống như thế này.
// Add a new user app.post('/users', (request, response) => { pool.query('INSERT INTO users SET ?', request.body, (error, result) => { if (error) throw error; response.status(201).send(`User added with ID: ${result.insertId}`); }); });
Bây giờ chúng tôi có thể gửi một POST
yêu cầu thông qua. Thông thường khi bạn gửi POST
yêu cầu, bạn đang làm điều đó thông qua một biểu mẫu web. Chúng ta sẽ tìm hiểu cách thiết lập điều đó ở cuối bài viết này, nhưng cách nhanh nhất và dễ nhất để gửi bài kiểm tra POST
là với cURL, sử dụng -d (--data)
cờ.
Chúng tôi sẽ chạy curl -d
, theo sau là một chuỗi truy vấn chứa tất cả các cặp khóa / giá trị và điểm cuối yêu cầu.
curl -d "name=Dinesh Chugtai&[email protected]" http://localhost:3002/users
Khi bạn gửi yêu cầu này qua, bạn sẽ nhận được phản hồi từ máy chủ.
User added with ID: 3
Nếu bạn điều hướng đến http://localhost/users
, bạn sẽ thấy mục nhập mới nhất được thêm vào danh sách.
Gửi yêu cầu PUT
POST
hữu ích cho việc thêm người dùng mới, nhưng chúng tôi sẽ muốn sử dụng PUT
để sửa đổi một người dùng hiện có. PUT
là Idempotent, nghĩa là bạn có thể gửi cùng một yêu cầu qua nhiều lần và chỉ một hành động sẽ được thực hiện. Điều này khác với POST
, bởi vì nếu chúng tôi gửi yêu cầu người dùng mới của mình nhiều lần, nó sẽ tiếp tục tạo ra những người dùng mới.
Đối với API của chúng tôi, chúng tôi sẽ thiết lập PUT
để có thể xử lý việc chỉnh sửa một người dùng, vì vậy chúng tôi sẽ sử dụng :id
tham số tuyến lần này.
Hãy tạo một UPDATE
và đảm bảo rằng nó chỉ áp dụng cho id được yêu cầu với WHERE
mệnh đề. Chúng tôi đang sử dụng hai ?
trình giữ chỗ và các giá trị chúng tôi chuyển sẽ đi theo thứ tự tuần tự.
// Update an existing user app.put('/users/:id', (request, response) => { const id = request.params.id; pool.query('UPDATE users SET ? WHERE id = ?', [request.body, id], (error, result) => { if (error) throw error; response.send('User updated successfully.'); }); });
Đối với thử nghiệm của chúng tôi, chúng tôi sẽ chỉnh sửa người dùng 2
và cập nhật địa chỉ email từ [email protected] thành [email protected]. Chúng ta có thể sử dụng lại cURL với [-X (--request)]
cờ, để chỉ định rõ ràng rằng chúng tôi đang gửi một yêu cầu PUT qua.
curl -X PUT -d "name=Bertram Gilfoyle" -d "[email protected]" http://localhost:3002/users/2
Đảm bảo khởi động lại máy chủ trước khi gửi yêu cầu, nếu không bạn sẽ nhận được Cannot PUT /users/2
lỗi.
Bạn sẽ thấy điều này:
User updated successfully.
Dữ liệu người dùng với id 2
bây giờ sẽ được cập nhật.
Gửi Yêu cầu XÓA
Nhiệm vụ cuối cùng của chúng tôi để hoàn thành chức năng CRUD của API là tạo một tùy chọn để xóa người dùng khỏi cơ sở dữ liệu. Yêu cầu này sẽ sử dụng DELETE
Truy vấn SQL với WHERE
và nó sẽ xóa một người dùng riêng lẻ được chỉ định bởi một tham số tuyến đường.
// Delete a user app.delete('/users/:id', (request, response) => { const id = request.params.id; pool.query('DELETE FROM users WHERE id = ?', id, (error, result) => { if (error) throw error; response.send('User deleted.'); }); });
Chúng ta có thể sử dụng -X
một lần nữa với cURL để gửi xóa thông qua. Hãy xóa người dùng mới nhất mà chúng tôi đã tạo.
curl -X DELETE http://localhost:3002/users/3
Bạn sẽ thấy thông báo thành công.
User deleted.
Điều hướng đến http://localhost:3002
và bạn sẽ thấy rằng bây giờ chỉ có hai người dùng.
Xin chúc mừng! Tại thời điểm này, API đã hoàn tất. Truy cập repo GitHub để xem mã hoàn chỉnh cho route.js .
Gửi yêu cầu thông qua request
Mô-đun
Ở phần đầu của bài viết này, chúng tôi đã cài đặt bốn phần phụ thuộc và một trong số chúng là request
mô-đun. Thay vì sử dụng các yêu cầu cURL, bạn có thể tạo một tệp mới với tất cả dữ liệu và gửi nó qua. Tôi sẽ tạo một tệp có tên post.js điều đó sẽ tạo người dùng mới qua POST
.
const request = require('request'); const json = { "name": "Dinesh Chugtai", "email": "[email protected]", }; request.post({ url: 'http://localhost:3002/users', body: json, json: true, }, function (error, response, body) { console.log(body); });
Chúng ta có thể gọi điều này bằng cách sử dụng node post.js
trong một cửa sổ đầu cuối mới trong khi máy chủ đang chạy và nó sẽ có tác dụng tương tự như khi sử dụng cURL. Nếu có điều gì đó không hoạt động với cURL, request
mô-đun hữu ích vì chúng tôi có thể xem lỗi, phản hồi và nội dung.
Gửi yêu cầu qua biểu mẫu web
Thông thường, POST
và các phương thức HTTP khác làm thay đổi trạng thái của máy chủ được gửi bằng các biểu mẫu HTML. Trong ví dụ rất đơn giản này, chúng tôi có thể tạo index.html gửi ở bất cứ đâu và tạo một trường cho tên và địa chỉ email. Hành động của biểu mẫu sẽ trỏ đến tài nguyên, trong trường hợp này là http//localhost:3002/users
và chúng tôi sẽ chỉ định phương thức là post
.
Tạo index.html và thêm mã sau vào nó:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Node.js Express REST API</title> </head> <body> <form action="http://localhost:3002/users" method="post"> <label for="name">Name</label> <input type="text" name="name"> <label for="email">Email</label> <input type="email" name="email"> <input type="submit"> </form> </body> </html>
Mở tệp HTML tĩnh này trong trình duyệt của bạn, điền vào và gửi tệp đó trong khi máy chủ đang chạy trong thiết bị đầu cuối. Bạn sẽ thấy phản hồi của User added with ID: 4
và bạn sẽ có thể xem danh sách người dùng mới.