From f3648ac479225a2f2c291c5af734091d80e99bcb Mon Sep 17 00:00:00 2001 From: Jussi Saarivirta Date: Sun, 22 Apr 2018 12:40:52 +0300 Subject: [PATCH] Fix to routes that broke after, enabling POST and other methods for all routes. Removed support for other than GET or POST and fixed routing --- readme.md | 2 +- src/api/generated/routes/routes.ts | 271 +++++++++++++++++++++++++++-- src/api/tsoa/route-template.tpl | 26 ++- 3 files changed, 284 insertions(+), 15 deletions(-) diff --git a/readme.md b/readme.md index e501eaa..6707533 100644 --- a/readme.md +++ b/readme.md @@ -8,7 +8,7 @@ To make life a lot easier for Windows users, an installation wizard now exists t [Skip straight to installation instructions.](#installation) -A test API is set up at http://astro-api.b5p.org if you wish to give it a spin ([swagger UI available](http://astro-api.b5p.org/swagger), note that from the swagger UI you can only use url upload, regular upload lacks UI). Don't use it for "production" purposes, the computing resources aren't very high and no service is guaranteed. It also may not be running the most recent version all the time. +A test API is set up at http://astro-api.b5p.org (dashboard: [http://astro-api.b5p.org/dashboard](http://astro-api.b5p.org/dashboard)) if you wish to give it a spin ([swagger UI available](http://astro-api.b5p.org/swagger), note that from the swagger UI you can only use url upload, regular upload lacks UI). Don't use it for "production" purposes, the computing resources are very low and no service is guaranteed. It's merely a demo. It also may not be running the most recent version all the time. ## Why? diff --git a/src/api/generated/routes/routes.ts b/src/api/generated/routes/routes.ts index a5d8f4b..46c1a54 100644 --- a/src/api/generated/routes/routes.ts +++ b/src/api/generated/routes/routes.ts @@ -205,7 +205,26 @@ const models: TsoaRoute.Models = { export function RegisterRoutes(app: any) { // app.post('/api/login', - app.use('/api/login', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/login', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + req: { "in": "body", "name": "req", "required": true, "ref": "LoginRequestWrapper" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new LoginController(); + const promise = controller.postLogin.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/login', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { req: { "in": "body", "name": "req", "required": true, "ref": "LoginRequestWrapper" }, @@ -224,7 +243,27 @@ export function RegisterRoutes(app: any) { }) ); // app.post('/api/upload', - app.use('/api/upload', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/upload', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + model: { "in": "body", "name": "model", "required": true, "ref": "UploadRequestWrapper" }, + req: { "in": "request", "name": "req", "required": true, "dataType": "object" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new UploadController(); + const promise = controller.postUpload.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/upload', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { model: { "in": "body", "name": "model", "required": true, "ref": "UploadRequestWrapper" }, @@ -244,7 +283,26 @@ export function RegisterRoutes(app: any) { }) ); // app.post('/api/url_upload', - app.use('/api/url_upload', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/url_upload', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + model: { "in": "body", "name": "model", "required": true, "ref": "UrlUploadRequestWrapper" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new UrlUploadController(); + const promise = controller.postUploadUrl.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/url_upload', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { model: { "in": "body", "name": "model", "required": true, "ref": "UrlUploadRequestWrapper" }, @@ -263,7 +321,26 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/submissions/:id', - app.use('/api/submissions/:id', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/submissions/:id', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + id: { "in": "path", "name": "id", "required": true, "dataType": "integer", "validators": { "isInt": { "errorMsg": "id" } } }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new SubmissionsController(); + const promise = controller.get.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/submissions/:id', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { id: { "in": "path", "name": "id", "required": true, "dataType": "integer", "validators": { "isInt": { "errorMsg": "id" } } }, @@ -282,7 +359,26 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/jobs/:id', - app.use('/api/jobs/:id', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/jobs/:id', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + id: { "in": "path", "name": "id", "required": true, "dataType": "integer", "validators": { "isInt": { "errorMsg": "id" } } }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new JobsController(); + const promise = controller.getJob.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/jobs/:id', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { id: { "in": "path", "name": "id", "required": true, "dataType": "integer", "validators": { "isInt": { "errorMsg": "id" } } }, @@ -301,7 +397,26 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/jobs/:id/calibration', - app.use('/api/jobs/:id/calibration', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/jobs/:id/calibration', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new JobsController(); + const promise = controller.getCalibration.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/jobs/:id/calibration', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, @@ -320,7 +435,26 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/jobs/:id/info', - app.use('/api/jobs/:id/info', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/jobs/:id/info', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new JobsController(); + const promise = controller.getInfo.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/jobs/:id/info', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, @@ -339,7 +473,25 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/stats/supports', - app.use('/api/stats/supports', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/stats/supports', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new StatsController(); + const promise = controller.getSupportData.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/stats/supports', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { }; @@ -357,7 +509,25 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/stats/latest', - app.use('/api/stats/latest', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/stats/latest', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new StatsController(); + const promise = controller.getLatestJobs.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/stats/latest', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { }; @@ -375,7 +545,25 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/stats/workers', - app.use('/api/stats/workers', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/stats/workers', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new StatsController(); + const promise = controller.getWorkerStates.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/stats/workers', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { }; @@ -393,7 +581,26 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/result-images/annotation/:id', - app.use('/api/result-images/annotation/:id', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/result-images/annotation/:id', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new ResultImageController(); + const promise = controller.getAnnotationImage.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/result-images/annotation/:id', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, @@ -412,7 +619,26 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/result-images/objects/:id', - app.use('/api/result-images/objects/:id', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/result-images/objects/:id', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new ResultImageController(); + const promise = controller.getObjectImage.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/result-images/objects/:id', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { id: { "in": "path", "name": "id", "required": true, "dataType": "double" }, @@ -431,7 +657,26 @@ export function RegisterRoutes(app: any) { }) ); // app.get('/api/job-control/cancel/:id', - app.use('/api/job-control/cancel/:id', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('/api/job-control/cancel/:id', + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + id: { "in": "path", "name": "id", "required": true, "dataType": "integer", "validators": { "isInt": { "errorMsg": "id" } } }, + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new JobControlController(); + const promise = controller.killJob.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('/api/job-control/cancel/:id', asyncErrorHandler(async (request: any, response: any, next: any) => { const args = { id: { "in": "path", "name": "id", "required": true, "dataType": "integer", "validators": { "isInt": { "errorMsg": "id" } } }, diff --git a/src/api/tsoa/route-template.tpl b/src/api/tsoa/route-template.tpl index a04616f..eefc18d 100644 --- a/src/api/tsoa/route-template.tpl +++ b/src/api/tsoa/route-template.tpl @@ -36,7 +36,31 @@ export function RegisterRoutes(app: any) { {{#each controllers}} {{#each actions}} // app.{{method}}('{{fullPath}}', - app.use('{{fullPath}}', + // Not ideal, but to comply with Nova's responses to both GET and POST for all methods, we register both routes by default. + app.get('{{fullPath}}', + {{#if security.length}} + authenticateMiddleware({{json security}}), + {{/if}} + asyncErrorHandler(async (request: any, response: any, next: any) => { + const args = { + {{#each parameters}} + {{@key}}: {{{json this}}}, + {{/each}} + }; + + let validatedArgs: any[] = []; + try { + validatedArgs = getValidatedArgs(args, request); + } catch (err) { + return next(err); + } + + const controller = new {{../name}}(); + const promise = controller.{{name}}.apply(controller, validatedArgs); + promiseHandler(controller, promise, response, next); + }) + ); + app.post('{{fullPath}}', {{#if security.length}} authenticateMiddleware({{json security}}), {{/if}}