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ột máy chủ thông báo đẩy. Khi kết thúc lớp học lập trình này, bạn sẽ có một máy chủ:

  • Theo dõi các lượt đă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 ứng dụng chọn sử dụng thông báo đẩy), và máy chủ sẽ 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
  • Gửi thông báo đẩy đến 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 qua thực hành và không đề cập nhiều về các khái niệm. Hãy xem phần Thông báo đẩy hoạt động như thế nào? để tìm hiểu về các khái niệm về thông báo đẩy.

Mã ứng dụng 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 ứng dụng thông báo đẩy.

Hãy tham khảo push-notifications-server-codelab-complete (source) để xem mã đầy đủ.

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

Lớp học lập trình này tương thích 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 biết là không hoạt động với các hệ điều hành (hoặc các tổ hợp hệ điều hành và trình duyệt) sau đây:

  • macOS: Brave, Edge, Safari
  • iOS

Ngăn xếp ứng dụng

  • Máy chủ này được xây dựng dựa trên Express.js.
  • Thư viện Node.js web-push sẽ xử lý mọi 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 cần 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 những công nghệ này vì chúng mang đến trải nghiệm đáng tin cậy khi tham gia 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 là Giao diện người dùng Glitch (Giao diện người dùng Glitch) trong suốt lớp học lập trình này.

  1. Nhấp vào Remix để chỉnh sửa (Remix) để chỉnh sửa dự án.

Thiết lập phương thức xác thực

Để 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 bằng các khoá xác thực. Hãy xem bài viết Ký các yêu cầu về giao thức đẩy trên web để tìm hiểu lý do.

  1. Mở cửa sổ dòng lệnh Nhiễu bằng cách nhấp vào Tools (Công cụ) rồi nhấp vào Terminal (Thiết bị đầu cuối).
  2. Trong dòng lệnh, hãy chạy npx web-push generate-vapid-keys. Sao chép khoá riêng tư và các giá trị 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 dấu ngoặc kép. Sau khi cập nhật, tệp .env sẽ có dạng như sau:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. Đóng thiết bị đầu cuối liên quan đến 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ý. Việc máy chủ của bạn cần làm chính là lưu các gói thuê bao 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 báo đến ứng dụng trong tương lai. Xem phần Đăng ký cho ứng dụng nhận thông báo đẩy để biết thêm thông tin 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 View App (Xem ứng dụng), sau đó nhấn vào Fullscreen toàn màn hình (Toàn màn hình).
  1. Nhấp vào Gia nhập 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ý ứng dụng đẩy. Trình duyệt hoặc hệ điều hành của bạn có thể sẽ hỏi 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 Allow (Cho phép) (hoặc bất kỳ cụm từ nào tương đương với cụm từ 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 một thông báo tương tự như sau:
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ụ rồi 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à URL mà ứng dụng gửi yêu cầu POST khi muốn đăng ký nhận thông báo đẩy. Dữ liệu theo sau là thông tin về gói thuê bao của ứng dụ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 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 về 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. Xem lại Nhật ký sự cố. Bạn sẽ thấy /remove-subscription, theo sau là thông tin gói thuê bao 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 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 phần Gửi thông báo đẩy, máy chủ của bạn không thực sự gửi trực tiếp thông báo đẩy đến ứng dụng. Thay vào đó, bạn cần áp dụng dịch vụ đẩy để làm việc đó. Về cơ bản, máy chủ của bạn chỉ khởi động quá trình đẩy thông báo đến ứng dụng khách bằng cách đưa ra các yêu cầu dịch vụ web (yêu cầu giao thức đẩy web) đến một dịch vụ web (dịch vụ đẩy) do nhà cung cấp trình duyệt mà người dùng sử dụng sở hữu.

  1. Cập nhật logic của trình xử lý định tuyến /notify-me bằng 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 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 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 lại vào Đăng ký để nhận thông báo đẩy. Điều 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 thông báo đẩy. Tiêu đề phải là Hello, Notifications! và phần nội dung phải là ID: <ID>, trong đó <ID> là một 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ý nhận thông báo đẩy cho ứng dụng, sau đó nhấp vào nút Thông báo tất cả. Bạn sẽ nhận được cùng một thông báo trên tất cả các thiết bị đã đăng ký của mình (tức là mã nhận dạng trong phần nội dung của thông báo đẩy phải giống nhau).

Các bước tiếp theo

  • Đọc bài viết Tổng quan về thông báo đẩy để hiểu rõ hơn 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: Tạo ứng dụng thông báo đẩy để tìm hiểu cách tạo ứng dụng yêu cầu quyền gửi thông báo, đăng ký thiết bị để nhận thông báo đẩy, đồng thời sử dụng một trình chạy dịch vụ để nhận thông báo đẩy và hiển thị thông báo dưới dạng thông báo.