Lớp học lập trình: Xây dựng máy chủ thông báo đẩy

Kate Jeffreys
Kate Jeffreys

Lớp học lập trình này sẽ hướng dẫn bạn từng bước xây dựng máy chủ thông báo đẩy. Khi kết thúc lớp học lập trình, bạn sẽ có một máy chủ:

  • Theo dõi đăng ký thông báo đẩy (tức là máy chủ tạo một bản ghi cơ sở dữ liệu mới khi khách hàng chọn nhận thông báo đẩy xoá bản ghi cơ sở dữ liệu hiện có khi ứng dụng chọn không sử dụng)
  • Gửi thông báo đẩy đến một ứng dụng khách
  • Gửi thông báo đẩy cho tất cả khách hàng đã đăng ký

Lớp học lập trình này tập trung vào việc giúp bạn học hỏi bằng cách thực hiện và chưa chúng ta thường nói nhiều về các khái niệm. Trả phòng Thông báo đẩy hoạt động như thế nào? để tìm hiểu về các khái niệm thông báo đẩy.

Mã ứng dụng khách của lớp học lập trình này đã hoàn tất. Bạn sẽ chỉ triển khai máy chủ trong lớp học lập trình này. Để tìm hiểu cách triển khai ứng dụng thông báo đẩy, hãy xem Lớp học lập trình: Tạo thông báo đẩy khách hàng.

Hãy tham khảo trang push-notifications-server-codelab-complete (nguồn) để xem mã hoàn chỉnh.

Khả năng tương thích với trình duyệt

Lớp học lập trình này hoạt động với các tổ hợp hệ điều hành và trình duyệt sau đây:

  • Windows: Chrome, Edge
  • macOS: Chrome, Firefox
  • Android: Chrome, Firefox

Lớp học lập trình này được xác định là không hoạt động với các hệ điều hành sau (hoặc kết hợp hệ điều hành và trình duyệt):

  • macOS: Brave, Edge, Safari
  • iOS

Ngăn xếp ứng dụng

  • Máy chủ được xây dựng dựa trên Express.js.
  • Thư viện Node.js web-push xử lý tất cả logic thông báo đẩy.
  • Dữ liệu gói thuê bao được ghi vào tệp JSON bằng lowdb.

Bạn không phải sử dụng bất kỳ công nghệ nào trong số này để triển khai thông báo đẩy. Chúng tôi chọn các công nghệ này vì chúng mang lại một trải nghiệm đáng tin cậy cho lớp học lập trình.

Thiết lập

Nhận bản sao có thể chỉnh sửa của mã

Trình soạn thảo mã mà bạn thấy ở bên phải các hướng dẫn này sẽ được gọi Giao diện người dùng gặp sự cố trong suốt lớp học lập trình này.

  1. Nhấp vào Phối lại để chỉnh sửa để có thể chỉnh sửa dự án.

Thiết lập tính năng xác thực

Để có thể làm cho thông báo đẩy hoạt động, bạn cần thiết lập máy chủ và ứng dụng khách của bạn bằng các khoá xác thực. Xem bài viết Ký yêu cầu giao thức đẩy web để tìm hiểu lý do.

  1. Mở cửa sổ dòng lệnh Glitch bằng cách nhấp vào Tools (Công cụ), sau đó nhấp vào Terminal.
  2. Trong cửa sổ dòng lệnh, hãy chạy npx web-push generate-vapid-keys. Sao chép khoá riêng tư và khoá công khai.
  3. Mở .env rồi cập nhật VAPID_PUBLIC_KEYVAPID_PRIVATE_KEY. Đặt VAPID_SUBJECT thành mailto:test@test.test. Tất cả các giá trị này phải được đặt trong gói trong dấu ngoặc kép. Sau khi cập nhật, tệp .env của bạn sẽ có dạng tương tự như sau:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. Đóng cửa sổ dòng lệnh nhiễu.
  1. Mở public/index.js.
  2. Thay thế VAPID_PUBLIC_KEY_VALUE_HERE bằng giá trị của khoá công khai.

Quản lý gói thuê bao

Khách hàng của bạn xử lý hầu hết quy trình đăng ký. Chính những việc máy chủ của bạn cần làm là lưu các đăng ký thông báo đẩy mới và xoá các gói thuê bao cũ. Các gói thuê bao này cho phép bạn đẩy thông điệp đến khách hàng trong tương lai. Xem phần Đăng ký cho khách hàng nhận thông báo đẩy để biết thêm bối cảnh về quy trình đăng ký.

Lưu thông tin về gói thuê bao mới

  1. Để xem trước trang web, hãy nhấn vào Xem ứng dụng. Sau đó nhấn Toàn màn hình toàn màn hình.
  1. Nhấp vào Đăng ký trình chạy dịch vụ trong thẻ ứng dụng. Trong hộp trạng thái, bạn sẽ thấy một thông báo tương tự như sau:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. Trong thẻ ứng dụng, hãy nhấp vào Đăng ký để đẩy. Trình duyệt hoặc hệ điều hành của bạn có thể sẽ hỏi bạn xem bạn có muốn cho phép trang web gửi thông báo đẩy cho bạn không. Nhấp vào Cho phép (hoặc tùy chọn khác) cụm từ tương đương mà trình duyệt/hệ điều hành của bạn sử dụng). Trong hộp trạng thái, bạn sẽ thấy thông báo tương tự vào việc này:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. Quay lại mã của bạn bằng cách nhấp vào Xem nguồn trong giao diện người dùng Glitch.
  2. Mở Nhật ký sự cố bằng cách nhấp vào Công cụ, sau đó nhấp vào Nhật ký. Bạn sẽ thấy /add-subscription theo sau là một số dữ liệu. /add-subscription là mà khách hàng gửi SAU KHI TRIỂN KHAI cho đến khi họ muốn đăng ký nhận thông báo đẩy. Dữ liệu mà sau là thông tin gói thuê bao của khách hàng mà bạn cần lưu.
  3. Mở server.js.
  4. Cập nhật logic của trình xử lý định tuyến /add-subscription bằng đoạn mã sau:
app.post('/add-subscription', (request, response) => {
  console.log('/add-subscription');
  console.log(request.body);
  console.log(`Subscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .push(request.body)
    .write();
  response.sendStatus(200);
});

Xoá thông tin gói thuê bao cũ

  1. Quay lại thẻ ứng dụng.
  2. Nhấp vào Huỷ đăng ký nhận thông báo đẩy.
  3. Hãy xem lại Nhật ký sự cố. Bạn sẽ thấy /remove-subscription được theo dõi thông tin đăng ký của khách hàng.
  4. Cập nhật logic của trình xử lý định tuyến /remove-subscription bằng đoạn mã sau:
app.post('/remove-subscription', (request, response) => {
  console.log('/remove-subscription');
  console.log(request.body);
  console.log(`Unsubscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .remove({endpoint: request.body.endpoint})
    .write();
  response.sendStatus(200);
});

Gửi thông báo

Như giải thích trong Gửi thông báo đẩy, máy chủ của bạn không thực sự gửi thông báo đẩy trực tiếp đến máy khách. Thay vào đó, hệ thống dựa vào một dịch vụ đẩy để thực hiện việc đó. Về cơ bản, máy chủ của bạn chỉ bắt đầu quá trình gửi thông điệp đến khách hàng bằng cách tạo ra yêu cầu dịch vụ (yêu cầu giao thức đẩy web) đến một dịch vụ web (dịch vụ đẩy) thuộc sở hữu của nhà cung cấp trình duyệt mà người dùng sử dụng.

  1. Cập nhật logic của trình xử lý định tuyến /notify-me bằng đoạn mã sau:
app.post('/notify-me', (request, response) => {
  console.log('/notify-me');
  console.log(request.body);
  console.log(`Notifying ${request.body.endpoint}`);
  const subscription = 
      db.get('subscriptions').find({endpoint: request.body.endpoint}).value();
  sendNotifications([subscription]);
  response.sendStatus(200);
});
  1. Cập nhật hàm sendNotifications() bằng đoạn mã sau:
function sendNotifications(subscriptions) {
  // TODO
  // Create the notification content.
  const notification = JSON.stringify({
    title: "Hello, Notifications!",
    options: {
      body: `ID: ${Math.floor(Math.random() * 100)}`
    }
  });
  // Customize how the push service should attempt to deliver the push message.
  // And provide authentication information.
  const options = {
    TTL: 10000,
    vapidDetails: vapidDetails
  };
  // Send a push message to each client specified in the subscriptions array.
  subscriptions.forEach(subscription => {
    const endpoint = subscription.endpoint;
    const id = endpoint.substr((endpoint.length - 8), endpoint.length);
    webpush.sendNotification(subscription, notification, options)
      .then(result => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Result: ${result.statusCode}`);
      })
      .catch(error => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Error: ${error} `);
      });
  });
}
  1. Cập nhật logic của trình xử lý định tuyến /notify-all bằng đoạn mã sau:
app.post('/notify-all', (request, response) => {
  console.log('/notify-all');
  response.sendStatus(200);
  console.log('Notifying all subscribers');
  const subscriptions =
      db.get('subscriptions').cloneDeep().value();
  if (subscriptions.length > 0) {
    sendNotifications(subscriptions);
    response.sendStatus(200);
  } else {
    response.sendStatus(409);
  }
});
  1. Quay lại thẻ ứng dụng.
  2. Nhấp vào Huỷ đăng ký nhận thông báo đẩy rồi nhấp vào Đăng ký nhận thông báo đẩy một lần nữa. Việc này chỉ cần thiết vì, như đã đề cập trước đó, Glitch sẽ khởi động lại dự án mỗi khi bạn chỉnh sửa mã và dự án được định cấu hình để xoá cơ sở dữ liệu khi khởi động.
  3. Nhấp vào Thông báo cho tôi. Bạn sẽ nhận được một thông báo đẩy. Tiêu đề nên là Hello, Notifications! và phần nội dung phải là ID: <ID>, trong đó <ID> là số ngẫu nhiên.
  4. Mở ứng dụng của bạn trên các trình duyệt hoặc thiết bị khác rồi thử đăng ký chúng để nhận thông báo đẩy sau đó nhấp vào nút Notify all (Thông báo cho tất cả). Bạn sẽ nhận được thông báo tương tự vào tất cả các thiết bị đã đăng ký (tức là mã nhận dạng trong phần nội dung của thông báo đẩy) y như cũ).

Các bước tiếp theo

  • Đọc bài viết Tổng quan về thông báo đẩy để tìm hiểu sâu hơn về mặt khái niệm về cách hoạt động của thông báo đẩy.
  • Hãy tham khảo Lớp học lập trình: Xây dựng ứng dụng thông báo đẩy tìm hiểu cách tạo một ứng dụng yêu cầu quyền gửi thông báo, hãy đăng ký thiết bị để nhận thông báo đẩy và sử dụng một trình chạy dịch vụ để nhận đẩy thông báo và hiển thị tin nhắn dưới dạng thông báo.