Skip to content

Commit 30698e1

Browse files
committed
supported reference files in global API
1 parent 87f0b58 commit 30698e1

1 file changed

Lines changed: 90 additions & 9 deletions

File tree

‎src/routes/references/index.js‎

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
const rootRouter = require('express').Router();
1+
// Set the router for further endpoints under references
2+
// Endpoints here may be attended by either the the global or any local API
3+
const referencesRouter = require('express').Router();
4+
// Set the local references router, for endpoints which are to be responded only by local APIs
5+
const referencesLocalRouter = require('express').Router();
26
// API generic handler
37
const handler = require('../../utils/generic-handler');
48
// Get the database handler
59
const getDatabase = require('../../database');
610
// Get auxiliar functions
7-
const { parseJSON, isObjectId } = require('../../utils/auxiliar-functions');
11+
const { parseJSON, isObjectId, getConfig } = require('../../utils/auxiliar-functions');
812
// Import references configuration
913
const { REFERENCES } = require('mddb-database/utils/constants');
1014
const AVAILABLE_REFERENCES = Object.keys(REFERENCES).join(', ');
@@ -226,16 +230,93 @@ const specificReferenceSpecificFileResponse = handler({
226230
},
227231
});
228232

229-
230233
// Set the routing
231-
rootRouter.route('/').get((_, response) => {
234+
referencesRouter.route('/').get((_, response) => {
232235
// Return a message with all possible routes
233236
// This is just a map so the API user know which options are available
234237
response.json(`Available reference endpoints: ${AVAILABLE_REFERENCES}`);
235238
});
236-
rootRouter.route('/:reference').get(wholeReferenceResponse);
237-
rootRouter.route('/:reference/:id').get(specificReferenceResponse);
238-
rootRouter.route('/:reference/:id/files').get(specificReferenceFilesResponse);
239-
rootRouter.route('/:reference/:id/files/:filename').get(specificReferenceSpecificFileResponse);
239+
referencesRouter.route('/:reference').get(wholeReferenceResponse);
240+
referencesRouter.route('/:reference/:id').get(specificReferenceResponse);
241+
referencesRouter.route('/:reference/:id/files').get(specificReferenceFilesResponse);
242+
// Note that this endpoint is to be attended by the local rounter only
243+
// This is handled belowe
244+
referencesLocalRouter.route('/:reference/:id/files/:filename').get(specificReferenceSpecificFileResponse);
245+
246+
// If we are using the global API then any further query is mapped to the corresponding database
247+
// Set a handler to be used for both GET and POST methods
248+
const redirectHandler = handler({
249+
async retriever(request) {
250+
// Stablish database connection and retrieve our custom handler
251+
const database = await getDatabase(request);
252+
// Get the requested reference configuration
253+
const referenceName = request.params.reference;
254+
// Get the requested id
255+
const referenceId = request.params.id;
256+
// Get the reference data
257+
const referenceData = await database.getReferenceData(referenceName, referenceId);
258+
if (referenceData.error) return referenceData;
259+
// Get the reference configuration
260+
const referenceConfig = database.REFERENCES[referenceName];
261+
// Find one database where this reference should be present
262+
// Note that a reference may be duplicated in different nodes
263+
// However all of them should do the job, although they may be not identical
264+
// We must attempt to ask a node which will have the most updated version
265+
// To do so, find the most recently updated project including this reference
266+
// Then redirect to its node
267+
const projectsCursor = await database.projects
268+
.find({ [referenceConfig.projectIdsField]: referenceId })
269+
.sort({ updateDate: -1 })
270+
.project({ node: true });
271+
// Get the first result
272+
const newestProject = await projectsCursor.next();
273+
const nodeAlias = newestProject.node;
274+
if (!nodeAlias) return {
275+
headerError: INTERNAL_SERVER_ERROR,
276+
error: `The "${referenceName}" reference "${referenceId}" is missing the node field.`
277+
};
278+
// Get the corresponding node
279+
const node = await database.nodes.findOne({ alias: nodeAlias });
280+
if (!node) return {
281+
headerError: INTERNAL_SERVER_ERROR,
282+
error: `Node "${nodeAlias}" not found`
283+
};
284+
// Get url path removing the first slash
285+
const urlPath = request.originalUrl.substring(1);
286+
// Build the new forwarded URL using the corresponding node API url
287+
const forwardedRef = node.api_url + urlPath;
288+
// The response code must change depending on the request method
289+
let code;
290+
if (request.method === 'GET') code = 302;
291+
else if (request.method === 'POST') code = 307;
292+
else throw new Error(`Unsupported method ${request.method}`);
293+
return { code, url: forwardedRef };
294+
},
295+
// Handle the response body
296+
body(response, retrieved) {
297+
// If nothing is retrieved then end the response
298+
// Note that the header should end the response already, but just in case
299+
if (!retrieved) return response.end();
300+
// If there is any error in the body then just send the error
301+
if (retrieved.error) return response.json(retrieved.error);
302+
// Send the response
303+
response.redirect(retrieved.code, retrieved.url);
304+
},
305+
});
306+
307+
// Now depending on the request host:
308+
// Redirect to children routes if this is a local request
309+
// Redirect to other APIs if this is a global request
310+
const hostRedirection = (request, response, next) => {
311+
// Find out if the request host is configured as global
312+
const config = getConfig(request);
313+
const isGlobal = config && config.global;
314+
// Redirect accordingly
315+
if (isGlobal) return redirectHandler(request, response, next);
316+
return referencesLocalRouter(request, response, next)
317+
};
318+
319+
referencesRouter.route('/:reference/:id/files/:filename').get(hostRedirection);
320+
321+
module.exports = referencesRouter;
240322

241-
module.exports = rootRouter;

0 commit comments

Comments
 (0)