Chociaż nie ma pojęcia "podprogramu" (o którym wiem) w samym hapi, podstawy są łatwe do wdrożenia.
Po pierwsze, hapi oferuje wildcard zmienne w ścieżkach, przy użyciu tych w zasadzie utworzyć ścieżkę catch-all dla danej ścieżki. Na przykład:
server.route({
method: 'GET',
path: '/projects/{project*}',
handler: (request, reply) => {
reply('in /projects, re-dispatch ' + request.params.project);
}
});
Istnieje kilka zasad do tych wieloznacznych ścieżkami, najważniejsze z nich to może być dopiero w ostatnim segmencie, który ma sens, jeśli myślisz o nim jako „catch-all”.
W powyższym przykładzie parametr {project*}
będzie dostępny pod numerem request.params.project
i będzie zawierał pozostałą część wywoływanej ścieżki, np.GET /projects/some/awesome/thing
ustawi request.params.project
na some/awesome/project
.
Następnym krokiem jest obsłużenie tej "ścieżki podrzędnej" (twoje aktualne pytanie), która jest głównie kwestią gustu i tego, jak chciałbyś pracować. Twoje pytanie sugeruje, że nie chcesz tworzyć nieskończonej, powtarzającej się listy podobnych rzeczy, ale jednocześnie możesz mieć bardzo konkretne trasy projektu.
Jednym ze sposobów jest podzielenie parametru request.params.project
na porcje i poszukiwanie folderów z pasującymi nazwami, które mogą zawierać logikę, aby dalej obsłużyć żądanie.
Przeanalizujmy tę koncepcję, przyjmując strukturę folderów (względem pliku zawierającego trasę, np. index.js
), która może być z łatwością wykorzystana do włączenia procedur obsługi określonych tras.
const fs = require('fs'); // require the built-in fs (filesystem) module
server.route({
method: 'GET',
path: '/projects/{project*}',
handler: (request, reply) => {
const segment = 'project' in request.params ? request.params.project.split('/') : [];
const name = segment.length ? segment.shift() : null;
if (!name) {
// given the samples in the question, this should provide a list of all projects,
// which would be easily be done with fs.readdir or glob.
return reply('getAllProjects');
}
let projectHandler = [__dirname, 'projects', name, 'index.js'].join('/');
fs.stat(projectHandler, (error, stat) => {
if (error) {
return reply('Not found').code(404);
}
if (!stat.isFile()) {
return reply(projectHandler + ' is not a file..').code(500);
}
const module = require(projectHandler);
module(segment, request, reply);
});
}
});
Mechanizm taki pozwoliłby masz każdy projekt jako moduł węzła w aplikacji i mieć swój kod wymyślić odpowiedniego modułu używać do obsługi ścieżkę przy starcie.
Nie musisz nawet określać tego dla każdej metody żądania, ponieważ możesz po prostu mieć trasy obsługujące wiele metod za pomocą method: ['GET', 'POST', 'PUT', 'DELETE']
zamiast method: 'GET'
.
Nie zajmuje się jednak w pełni powtarzającą się deklaracją obsługi tras, ponieważ do każdego projektu będzie potrzebna dość podobna konfiguracja modułu.
W sposób powyższy przykład zawiera i wywołuje „sub-route-ładowarki”, implementacja próbka będzie:
// <app>/projects/<projectname>/index.js
module.exports = (segments, request, reply) => {
// segments contains the remainder of the called project path
// e.g. /projects/some/awesome/project
// would become ['some', 'awesome', 'project'] inside the hapi route itself
// which in turn removes the first part (the project: 'some'), which is were we are now
// <app>/projects/some/index.js
// leaving the remainder to be ['awesome', 'project']
// request and reply are the very same ones the hapi route has received
const action = segments.length ? segments.shift() : null;
const item = segments.length ? segments.shift() : null;
// if an action was specified, handle it.
if (action) {
// if an item was specified, handle it.
if (item) {
return reply('getOneItemForProject:' + item);
}
// if action is 'items', the reply will become: getAllItemsForProject
// given the example, the reply becomes: getAllAwesomeForProject
return reply('getAll' + action[0].toUpperCase() + action.substring(1) + 'ForProject');
}
// no specific action, so reply with the entire project
reply('getOneProject');
};
Myślę, że to pokazuje, jak poszczególne projekty mogą być obsługiwane w tobie aplikacji w czasie wykonywania, choć budzi kilka obaw będziesz mieć do czynienia z przy tworzeniu architektury aplikacji:
- jeśli moduł obsługa projekt naprawdę są bardzo podobne, należy utworzyć bibliotekę którego używasz, aby zapobiec kopiowaniu samo moduł w kółko, ponieważ to ułatwia konserwację (która, I recon, była ostatecznym celem posiadania pod-routingu)
- jeśli możesz dowiedzieć się, które moduły użyć w czasie wykonywania, powinieneś także również być w stanie aby to zrozumieć, gdy rozpocznie się proces serwera.
Tworzenie biblioteki zapobiegającej powtarzaniu kodu jest czymś, co powinieneś zrobić (nauczyć się robić) na wczesnym etapie, ponieważ ułatwia to konserwację, a twoja przyszłość będzie wdzięczna.
Ustalenie, które moduły będą dostępne do obsługi różnych projektów, które masz na początku aplikacji, będzie zapisywać każde żądanie od konieczności stosowania tej samej logiki w kółko. Hapi może być w stanie buforować to dla ciebie, w takim przypadku tak naprawdę nie ma to znaczenia, ale jeśli buforowanie nie jest opcją, możesz być lepiej używając mniej dynamicznych ścieżek (co - jak sądzę - jest głównym powodem, dla którego nie jest to oferowane domyślnie przez hapi).
można przemierzać projekty folderze szuka wszystkich <project>/index.js
na początku stosowania i zarejestrować bardziej konkretną trasę korzystając glob
takiego:
const glob = require('glob');
glob('projects/*', (error, projects) => {
projects.forEach((project) => {
const name = project.replace('projects/', '');
const module = require(project);
server.route({
method: 'GET',
path: '/projects/' + name + '/{remainder*}',
handler: (request, reply) => {
const segment = 'remainder' in request.params ? request.params.remainder.split('/') : [];
module(segment, request, reply);
}
});
});
});
ten skutecznie zastępuje powyższą logikę patrząc moduł na każdy Żądajcie i przełączcie się na (nieco) bardziej efektywną trasę, ponieważ jesteście hapi dokładnie tym, które projekty będziecie serwować, pozostawiając rzeczywistą obsługę każdemu dostarczonemu modułowi projektu. (Nie zapomnij zaimplementować trasy /projects
, ponieważ teraz trzeba to zrobić wyraźnie)
Nie bardzo rozumiem, jakie jest twoje pytanie. Twoje poszukiwane trasy zagnieżdżone, a powyższy kod został już dostarczony. Więc gdzie utknąłeś? –
Zastanawiam się, czy istnieje jakikolwiek inny, wygodniejszy sposób, ponieważ w tym podejściu routing na trzeci poziom stanie się ogromnym bałaganem. 'server.route ({ sposób: 'GET', ścieżkę: '/ projekty/{PROJECT_ID}/szt/{item_id}/Wyniki/{result_id}', obsługi: getAllItemsForProject })' Więc im poszukuje rozwiązania podobnego do tego: [link] (http://stackoverflow.com/questions/25260818/rest-with-express-js-nested-router) – PoMaHTuK
Myślę, że problem z zagnieżdżaniem jest taki, że Hapi nie naprawdę ma sposób posiadania wielu programów obsługi na definicję trasy. Nadal musisz jawnie zadeklarować każdą trasę i od tej pory Hapi tak naprawdę nie ma sposobu deklarowania tras podrzędnych. – Osukaa