mở rộng API hiện có với các điểm cuối tùy chỉnh


12

Tôi đang tạo một API cho nhiều khách hàng. Các điểm cuối cốt lõi như /usersđược sử dụng bởi mọi khách hàng nhưng một số điểm cuối dựa trên tùy chỉnh riêng lẻ. Vì vậy, có thể người dùng A muốn có một điểm cuối đặc biệt /groupsvà sẽ không có khách hàng nào khác có tính năng đó. Cũng giống như một sidenote , mỗi khách hàng cũng sẽ sử dụng lược đồ cơ sở dữ liệu của riêng mình vì các tính năng bổ sung đó.

Cá nhân tôi sử dụng NestJs (Express dưới mui xe). Vì vậy, app.modulehiện tại đăng ký tất cả các mô-đun cốt lõi của tôi (với các điểm cuối riêng của họ, v.v.)

import { Module } from '@nestjs/common';

import { UsersModule } from './users/users.module'; // core module

@Module({
  imports: [UsersModule]
})
export class AppModule {}

Tôi nghĩ vấn đề này không liên quan đến NestJs vậy bạn sẽ xử lý vấn đề đó như thế nào?

Về cơ bản tôi cần một cơ sở hạ tầng có thể cung cấp một hệ thống cơ bản. Không có điểm cuối cốt lõi nữa vì mỗi phần mở rộng là duy nhất và /userscó thể thực hiện nhiều lần . Khi phát triển một tính năng mới, ứng dụng cốt lõi không nên chạm vào. Các tiện ích mở rộng nên tự tích hợp hoặc nên được tích hợp khi khởi động. Hệ thống lõi không có điểm cuối nhưng sẽ được mở rộng từ các tệp bên ngoài đó.

Một số ý tưởng nảy ra trong đầu tôi


Cách tiếp cận đầu tiên:

Mỗi phần mở rộng đại diện cho một kho lưu trữ mới. Xác định đường dẫn đến thư mục bên ngoài tùy chỉnh chứa tất cả các dự án mở rộng đó. Thư mục tùy chỉnh này sẽ chứa một thư mục groupsgroups.module

import { Module } from '@nestjs/common';

import { GroupsController } from './groups.controller';

@Module({
  controllers: [GroupsController],
})
export class GroupsModule {}

API của tôi có thể lặp qua thư mục đó và cố gắng nhập từng tệp mô-đun.

  • ưu:

    1. Mã tùy chỉnh được tránh xa kho lưu trữ lõi
  • Nhược điểm:

    1. NestJs sử dụng Typecript nên tôi phải biên dịch mã trước. Làm cách nào để quản lý bản dựng API và bản dựng từ các ứng dụng tùy chỉnh? (Hệ thống cắm và chạy)

    2. Các phần mở rộng tùy chỉnh rất lỏng lẻo vì chúng chỉ chứa một số tệp bản thảo. Do thực tế họ không có quyền truy cập vào thư mục node_modules của API, trình soạn thảo của tôi sẽ hiển thị cho tôi các lỗi vì nó không thể giải quyết các phụ thuộc gói bên ngoài.

    3. Một số tiện ích mở rộng có thể tìm nạp dữ liệu từ tiện ích mở rộng khác. Có thể dịch vụ nhóm cần truy cập dịch vụ người dùng. Mọi thứ có thể trở nên khó khăn ở đây.


Cách tiếp cận thứ hai: Giữ mỗi phần mở rộng bên trong thư mục con của thư mục src của API. Nhưng thêm thư mục con này vào tệp .gitignore. Bây giờ bạn có thể giữ các tiện ích mở rộng của mình bên trong API.

  • ưu:

    1. Trình chỉnh sửa của bạn có thể giải quyết các phụ thuộc

    2. Trước khi triển khai mã của bạn, bạn có thể chạy lệnh xây dựng và sẽ có một bản phân phối

    3. Bạn có thể dễ dàng truy cập các dịch vụ khác ( /groupscần tìm người dùng theo id)

  • Nhược điểm:

    1. Khi phát triển, bạn phải sao chép các tệp lưu trữ của mình bên trong thư mục con đó. Sau khi thay đổi một cái gì đó, bạn phải sao chép các tệp này lại và ghi đè lên các tệp lưu trữ của bạn với các tệp được cập nhật.

Cách tiếp cận thứ ba:

Trong một thư mục tùy chỉnh bên ngoài, tất cả các tiện ích mở rộng đều được API hoàn toàn chính thức. API chính của bạn sẽ chỉ cung cấp công cụ xác thực và có thể hoạt động như một proxy để chuyển hướng các yêu cầu đến tới API mục tiêu.

  • ưu:

    1. Các tiện ích mở rộng mới có thể được phát triển và thử nghiệm dễ dàng
  • Nhược điểm:

    1. Triển khai sẽ là khó khăn. Bạn sẽ có một API chính và n API mở rộng bắt đầu quá trình của riêng mình và lắng nghe một cổng.

    2. Hệ thống proxy có thể khó khăn. Nếu máy khách yêu cầu /usersproxy cần biết API mở rộng nào lắng nghe điểm cuối đó, hãy gọi API đó và chuyển tiếp phản hồi đó cho máy khách.

    3. Để bảo vệ các API mở rộng (xác thực được xử lý bởi API chính), proxy cần chia sẻ bí mật với các API đó. Vì vậy, API tiện ích mở rộng sẽ chỉ chuyển các yêu cầu đến nếu bí mật phù hợp đó được cung cấp từ proxy.


Cách tiếp cận thứ tư:

Dịch vụ vi mô có thể giúp đỡ. Tôi đã lấy một hướng dẫn từ đây https://docs.nestjs.com/microservice/basics

Tôi có thể có một dịch vụ siêu nhỏ để quản lý người dùng, quản lý nhóm, v.v. và sử dụng các dịch vụ đó bằng cách tạo một api / gateway / proxy nhỏ gọi các dịch vụ siêu nhỏ đó.

  • ưu:

    1. Các tiện ích mở rộng mới có thể được phát triển và thử nghiệm dễ dàng

    2. Mối quan tâm riêng biệt

  • Nhược điểm:

    1. Triển khai sẽ là khó khăn. Bạn sẽ có một API chính và n microservice bắt đầu quá trình của riêng họ và lắng nghe một cổng.

    2. Có vẻ như tôi sẽ phải tạo một api cổng mới cho mỗi khách hàng nếu tôi muốn nó có thể tùy chỉnh. Vì vậy, thay vì mở rộng một ứng dụng, tôi sẽ phải tạo API comsuming tùy chỉnh mỗi lần. Điều đó sẽ không giải quyết vấn đề.

    3. Để bảo vệ các API mở rộng (xác thực được xử lý bởi API chính), proxy cần chia sẻ bí mật với các API đó. Vì vậy, API tiện ích mở rộng sẽ chỉ chuyển các yêu cầu đến nếu bí mật phù hợp đó được cung cấp từ proxy.


2
điều này có thể giúp github.com/nestjs/nest/issues/3277
Câu hỏi 3

Cảm ơn các liên kết. Nhưng tôi không nghĩ rằng tôi nên có các tiện ích mở rộng tùy chỉnh trong mã của mình. Tôi sẽ kiểm tra xem microservice có giải quyết được vấn đề docs.nestjs.com/microservice/basics
hrp8sfH4xQ4

Tôi nghĩ vấn đề của bạn liên quan đến ủy quyền hơn là nghỉ ngơi.
adnanmuttaleb

@ adnanmuttaleb bạn có phiền giải thích tại sao =?
hrp8sfH4xQ4

Câu trả lời:


6

Có một số cách tiếp cận này. Những gì bạn cần làm là tìm ra quy trình công việc nào phù hợp nhất cho nhóm, tổ chức và khách hàng của bạn.

Nếu điều này tùy thuộc vào tôi, tôi sẽ xem xét sử dụng một kho lưu trữ cho mỗi mô-đun và sử dụng trình quản lý gói như NPM với các gói phạm vi riêng tư hoặc tổ chức để xử lý cấu hình. Sau đó, thiết lập các đường ống phát hành bản dựng đẩy đến gói repo trên các bản dựng mới.

Bằng cách này, tất cả những gì bạn cần là tệp chính và tệp tệp kê khai gói cho mỗi cài đặt tùy chỉnh. Bạn có thể độc lập phát triển và triển khai các phiên bản mới và bạn có thể tải các phiên bản mới khi bạn cần ở phía máy khách.

Để tăng độ mượt mà, bạn có thể sử dụng tệp cấu hình để ánh xạ các mô-đun tới các tuyến đường và viết một kịch bản trình tạo tuyến đường chung để thực hiện hầu hết các bootstrapping.

Vì một gói có thể là bất cứ thứ gì, các phụ thuộc chéo trong các gói sẽ hoạt động mà không gặp nhiều rắc rối. Bạn chỉ cần có kỷ luật khi nói đến thay đổi và quản lý phiên bản.

Đọc thêm về các gói riêng tại đây: Gói riêng NPM

Bây giờ đăng ký NPM tư nhân tốn tiền, nhưng nếu đó là một vấn đề thì cũng có một số tùy chọn khác. Vui lòng xem lại bài viết này cho một số lựa chọn thay thế - cả miễn phí và trả phí.

Cách để có đăng ký npm riêng của bạn

Bây giờ nếu bạn muốn cuộn trình quản lý của riêng mình, bạn có thể viết một trình định vị dịch vụ đơn giản, chứa tệp cấu hình chứa thông tin cần thiết để lấy mã từ repo, tải lên và sau đó cung cấp một số phương thức để truy xuất ví dụ với nó

Tôi đã viết một triển khai tham chiếu đơn giản cho một hệ thống như vậy:

Khung: định vị dịch vụ đầu máy

Một ví dụ kiểm tra plugin cho palindromes: ví dụ plugin locomotion

Một ứng dụng sử dụng khung để xác định vị trí bổ trợ: ví dụ ứng dụng đầu máy

Bạn có thể giải quyết vấn đề này bằng cách lấy nó từ npm bằng cách sử dụng npm install -s locomotionbạn sẽ cần chỉ định một plugins.jsontệp có lược đồ sau:

{
    "path": "relative path where plugins should be stored",
    "plugins": [
        { 
           "module":"name of service", 
           "dir":"location within plugin folder",
           "source":"link to git repository"
        }
    ]
}

thí dụ:

{
    "path": "./plugins",
    "plugins": [
        {
            "module": "palindrome",
            "dir": "locomotion-plugin-example",
            "source": "https://github.com/drcircuit/locomotion-plugin-example.git"
        }
    ]
}

tải nó như thế này: const loco = Yêu cầu ("đầu máy");

Sau đó, nó trả về một lời hứa sẽ giải quyết đối tượng định vị dịch vụ, có phương thức định vị để giữ các dịch vụ của bạn:

loco.then((svc) => {
    let pal = svc.locate("palindrome"); //get the palindrome service
    if (pal) {
        console.log("Is: no X in Nixon! a palindrome? ", (pal.isPalindrome("no X in Nixon!")) ? "Yes" : "no"); // test if it works :)
    }
}).catch((err) => {
    console.error(err);
});

Xin lưu ý rằng đây chỉ là một triển khai tham chiếu và không đủ mạnh để áp dụng nghiêm túc. Tuy nhiên, mô hình vẫn còn hiệu lực và cho thấy ý chính của việc viết loại khung này.

Bây giờ, điều này sẽ cần được mở rộng với sự hỗ trợ cho cấu hình plugin, khởi tạo, kiểm tra lỗi, có thể thêm hỗ trợ cho việc tiêm phụ thuộc, v.v.


Cảm ơn. Hai vấn đề xuất hiện, có vẻ như chúng tôi dựa vào npm sau đó và phải thiết lập một sổ đăng ký tự lưu trữ. Điều thứ hai là npm riêng không còn miễn phí nữa. Tôi đã hy vọng tìm thấy một giải pháp kỹ thuật cơ bản. Nhưng +1 cho ý tưởng :)
hrp8sfH4xQ4

1
đã thêm một triển khai tham chiếu của một giải pháp thô sơ cho loại hệ thống này.
Espen

3

Tôi sẽ đi cho các tùy chọn gói bên ngoài.

Bạn có thể cấu trúc ứng dụng của bạn để có một packagesthư mục. Tôi sẽ có các bản dựng được biên dịch UMD của các gói bên ngoài trong thư mục đó để bản thảo được biên dịch của bạn sẽ không có bất kỳ vấn đề nào với các gói. Tất cả các gói nên có một index.jstệp trên thư mục gốc của mỗi gói.

Và ứng dụng của bạn có thể chạy một vòng qua thư mục gói bằng cách sử dụng fsrequiretất cả các góiindex.js vào ứng dụng của bạn.

Sau đó, một lần nữa cài đặt phụ thuộc là một cái gì đó bạn phải chăm sóc. Tôi nghĩ rằng một tập tin cấu hình trên mỗi gói cũng có thể giải quyết điều đó. Bạn có thể có một npmtập lệnh tùy chỉnh trên ứng dụng chính để cài đặt tất cả các phụ thuộc gói trước khi khởi động ứng dụng.

Bằng cách này, bạn chỉ có thể thêm các gói mới vào ứng dụng của mình bằng cách sao chép dán gói vào thư mục gói và khởi động lại ứng dụng. Các tệp bản thảo đã biên dịch của bạn sẽ không bị chạm và bạn không phải sử dụng npm riêng cho các gói của riêng mình.


Cảm ơn vì đã trả lời. Tôi nghĩ rằng điều này nghe giống như giải pháp @ Espen đã được đăng, phải không?
hrp8sfH4xQ4

@ hrp8sfH4xQ4 Có, để gia hạn. Tôi đã thêm nó sau khi đọc bình luận của bạn về việc không muốn sử dụngnpm . Trên đây là một giải pháp bạn có thể làm để tránh tài khoản npm riêng tư. Hơn nữa, tôi tin rằng bạn không cần thêm các gói được tạo bởi ai đó bên ngoài tổ chức của mình. Đúng?
Kalesh Kaladharan

btw. nhưng cũng thật tuyệt vời khi hỗ trợ điều đó ... bằng cách nào đó ...
hrp8sfH4xQ4

Nếu bạn cần tùy chọn để thêm các gói của bên thứ ba, thì npm là cách để thực hiện hoặc bất kỳ trình quản lý gói nào khác. Trong những trường hợp như vậy, giải pháp của tôi sẽ không đủ.
Kalesh Kaladharan

Nếu bạn không phiền, tôi muốn chờ đợi để thu thập càng nhiều cách tiếp cận càng tốt
hrp8sfH4xQ4
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.