Tworzę interfejs API dla wielu klientów. Podstawowe punkty końcowe, takie jak, /users
są używane przez każdego klienta, ale niektóre punkty końcowe zależą od indywidualnego dostosowania. Być może więc użytkownik A chce specjalnego punktu końcowego /groups
i żaden inny klient nie będzie miał tej funkcji. Podobnie jak sidenote , każdy klient używałby również własnego schematu bazy danych z powodu tych dodatkowych funkcji.
Osobiście używam NestJs (Express pod maską). Tak więc app.module
obecnie rejestruje wszystkie moje podstawowe moduły (z własnymi punktami końcowymi itp)
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module'; // core module
@Module({
imports: [UsersModule]
})
export class AppModule {}
Myślę, że ten problem nie jest związany z NestJ, więc jak poradziłbyś sobie z tym w teorii?
Zasadniczo potrzebuję infrastruktury, która jest w stanie zapewnić podstawowy system. Nie ma już podstawowych punktów końcowych, ponieważ każde rozszerzenie jest unikalne i /users
możliwe może być wiele implementacji. Podczas opracowywania nowej funkcji nie należy dotykać podstawowej aplikacji. Rozszerzenia powinny się integrować lub powinny zostać zintegrowane podczas uruchamiania. System podstawowy jest dostarczany bez punktów końcowych, ale zostanie rozszerzony z tych plików zewnętrznych.
Niektóre pomysły przychodzą mi na myśl
Pierwsze podejście:
Każde rozszerzenie reprezentuje nowe repozytorium. Zdefiniuj ścieżkę do niestandardowego folderu zewnętrznego zawierającego wszystkie projekty rozszerzeń. Ten niestandardowy katalog zawierałby folder groups
z plikiemgroups.module
import { Module } from '@nestjs/common';
import { GroupsController } from './groups.controller';
@Module({
controllers: [GroupsController],
})
export class GroupsModule {}
Mój interfejs API może przechodzić przez ten katalog i próbować importować każdy plik modułu.
plusy:
- Kod niestandardowy jest trzymany z dala od głównego repozytorium
Cons:
NestJs używa Typescript, więc najpierw muszę skompilować kod. Jak zarządzałbym kompilacją API i kompilacjami z niestandardowych aplikacji? (System plug and play)
Niestandardowe rozszerzenia są bardzo luźne, ponieważ zawierają tylko niektóre pliki maszynopisu. Ponieważ nie mają dostępu do katalogu node_modules API, mój edytor pokaże mi błędy, ponieważ nie może rozwiązać zależności zewnętrznych pakietów.
Niektóre rozszerzenia mogą pobierać dane z innego rozszerzenia. Może usługa grup musi mieć dostęp do usługi użytkowników. Tutaj może być trudniej.
Drugie podejście: przechowuj każde rozszerzenie w podfolderze folderu src interfejsu API. Ale dodaj ten podfolder do pliku .gitignore. Teraz możesz przechowywać rozszerzenia w interfejsie API.
plusy:
Twój edytor jest w stanie rozwiązać zależności
Przed wdrożeniem kodu możesz uruchomić polecenie kompilacji i mieć jedną dystrybucję
Możesz łatwo uzyskać dostęp do innych usług (
/groups
musi znaleźć użytkownika według identyfikatora)
Cons:
- Podczas programowania musisz skopiować pliki repozytorium w tym podfolderze. Po zmianie czegoś musisz skopiować te pliki z powrotem i zastąpić pliki repozytorium zaktualizowanymi plikami.
Trzecie podejście:
W zewnętrznym folderze niestandardowym wszystkie rozszerzenia są pełnoprawnymi samodzielnymi interfejsami API. Twój główny interfejs API po prostu zapewnia uwierzytelnianie i może działać jako serwer proxy, aby przekierowywać przychodzące żądania do docelowego interfejsu API.
plusy:
- Nowe rozszerzenia można łatwo opracowywać i testować
Cons:
Wdrożenie będzie trudne. Będziesz miał główny interfejs API oraz API rozszerzeń n, rozpoczynający własny proces i nasłuchujący na porcie.
System proxy może być trudny. Jeśli klient zażąda,
/users
aby serwer proxy wiedział, które rozszerzenie API nasłuchuje dla tego punktu końcowego, wywołuje ten interfejs API i przekazuje tę odpowiedź z powrotem do klienta.Aby chronić interfejsy API rozszerzeń (uwierzytelnianie jest obsługiwane przez główny interfejs API), serwer proxy musi udostępnić klucz tajny tym interfejsom API. Zatem interfejs API rozszerzenia będzie przekazywał przychodzące żądania tylko wtedy, gdy ten pasujący klucz tajny zostanie dostarczony z serwera proxy.
Czwarte podejście:
Mikrousługi mogą pomóc. Wziąłem stąd przewodnik https://docs.nestjs.com/microservices/basics
Mogę mieć mikrousługę do zarządzania użytkownikami, zarządzania grupami itp. I korzystać z tych usług, tworząc mały interfejs API / bramę / proxy, który wywołuje te mikrousługi.
plusy:
Nowe rozszerzenia można łatwo opracowywać i testować
Oddzielne obawy
Cons:
Wdrożenie będzie trudne. Trzeba będzie głównym API i n microservices rozpoczęciem własnego procesu i słuchać do portu.
Wygląda na to, że musiałbym utworzyć nowy interfejs API bramy dla każdego klienta, jeśli chcę mieć możliwość dostosowania. Zamiast rozszerzać aplikację, musiałbym za każdym razem tworzyć niestandardowy interfejs API do zbierania danych. To nie rozwiązałoby problemu.
Aby chronić interfejsy API rozszerzeń (uwierzytelnianie jest obsługiwane przez główny interfejs API), serwer proxy musi udostępnić klucz tajny tym interfejsom API. Zatem interfejs API rozszerzenia będzie przekazywał przychodzące żądania tylko wtedy, gdy ten pasujący klucz tajny zostanie dostarczony z serwera proxy.