From 4e180086ff83e546263ed5928a150781a924b437 Mon Sep 17 00:00:00 2001 From: jmkerloch Date: Wed, 5 Apr 2023 09:18:28 +0200 Subject: [PATCH 1/5] feat(projection): add route to get projection from service --- .../apis/administration/1.0.0/api.yaml | 58 ++++++++++++- src/js/administrator/administrator.js | 18 ++++ .../apis/admin/1.0.0/controller/controller.js | 64 ++++++++++++++ src/js/apis/admin/1.0.0/index.js | 44 ++++++++++ src/js/requests/projectionRequest.js | 83 +++++++++++++++++++ src/js/responses/projectionResponse.js | 56 +++++++++++++ src/js/service/service.js | 33 ++++++++ src/js/service/serviceManager.js | 2 +- .../cucumber/configurations/local-admin.json | 3 +- .../cucumber/features/req-admin-1.0.0.feature | 30 +++++++ .../requests/integrationProjectionRequest.js | 41 +++++++++ .../integrationProjectionResponse.js | 31 +++++++ 12 files changed, 460 insertions(+), 3 deletions(-) create mode 100644 src/js/requests/projectionRequest.js create mode 100644 src/js/responses/projectionResponse.js create mode 100644 test/integration/mocha/requests/integrationProjectionRequest.js create mode 100644 test/integration/mocha/responses/integrationProjectionResponse.js diff --git a/documentation/apis/administration/1.0.0/api.yaml b/documentation/apis/administration/1.0.0/api.yaml index 2e582a2..66df8c6 100644 --- a/documentation/apis/administration/1.0.0/api.yaml +++ b/documentation/apis/administration/1.0.0/api.yaml @@ -390,7 +390,55 @@ paths: application/json: schema: $ref: "#/components/schemas/errorResponse" - + + /services/{service}/projections/{projection}: + get: + tags: + - "Gestion des services" + - "Projection" + summary: "Récupération d'une projection supportée par un service." + description: | + Cette requête retourne une projection supportée par un service. + operationId: "get-service-projection" + parameters: + - name: "service" + description: "Id du service concerné" + in: "path" + required: true + schema: + type: "string" + - name: "projection" + description: "Id de la projection concernée" + in: "path" + required: true + schema: + type: "string" + responses: + 200: + description: "successful operation" + content: + application/json: + schema: + $ref: "#/components/schemas/projectionConfiguration" + 400: + description: "Invalid parameters" + content: + application/json: + schema: + $ref: "#/components/schemas/errorResponse" + 404: + description: "Not found" + content: + application/json: + schema: + $ref: "#/components/schemas/errorResponse" + 500: + description: "Internal server error" + content: + application/json: + schema: + $ref: "#/components/schemas/errorResponse" + /services/{service}/resources: get: tags: @@ -953,6 +1001,14 @@ components: version: type: "string" example: "1.0.0" + + projectionConfiguration: + type: "object" + properties: + id: + type: "string" + example: "EPSG:4326" + required: true resourceConfiguration: type: "object" diff --git a/src/js/administrator/administrator.js b/src/js/administrator/administrator.js index bcca61d..4d87e19 100644 --- a/src/js/administrator/administrator.js +++ b/src/js/administrator/administrator.js @@ -475,6 +475,24 @@ module.exports = class Administrator { } + /** + * + * @function + * @name computeRequest + * @description Gestion de la requête pour une route d'administration sur un serveur + * @param {string} serviceId - Id du service selon l'administrateur + * @param {object} request - Instance fille de la classe Request + * + */ + + async computeRequest(serviceId, request) { + + LOGGER.info("computeRequest..."); + LOGGER.debug("Compute request pour le service : " + serviceId); + const response = await this._serviceManager.computeRequest(serviceId, request); + return response; + } + /** * * @function diff --git a/src/js/apis/admin/1.0.0/controller/controller.js b/src/js/apis/admin/1.0.0/controller/controller.js index 99dd146..4bb76fe 100644 --- a/src/js/apis/admin/1.0.0/controller/controller.js +++ b/src/js/apis/admin/1.0.0/controller/controller.js @@ -4,6 +4,7 @@ const errorManager = require('../../../../utils/errorManager'); const log4js = require('log4js'); const HealthRequest = require('../../../../requests/healthRequest'); const ServiceRequest = require('../../../../requests/serviceRequest'); +const ProjectionRequest = require('../../../../requests/projectionRequest'); var LOGGER = log4js.getLogger("CONTROLLER"); @@ -110,6 +111,69 @@ module.exports = { return request; + }, + + + /** + * + * @function + * @name checkProjectionParameters + * @description Vérification des paramètres d'une requête sur /services/{service}/projections/{projection} + * @param {object} parameters - ensemble des paramètres de la requête ExpressJS + * @return {ProjectionRequest} request - Instance de la classe ProjectionRequest + * + */ + + checkProjectionParameters: function(parameters) { + + LOGGER.debug("checkProjectionParameters()"); + + // Service + if (!parameters.service) { + throw errorManager.createError(" Parameter 'service' is invalid: there is no value", 400); + } + + if (parameters.service === "") { + throw errorManager.createError(" Parameter 'service' is invalid: value should not be empty", 400); + } + + // Projection + if (!parameters.projection) { + throw errorManager.createError(" Parameter 'projection' is invalid: there is no value", 400); + } + + if (parameters.projection === "") { + throw errorManager.createError(" Parameter 'projection' is invalid: value should not be empty", 400); + } + + // TODO : vérifier ici que le service existe (appel à une fonction de la classe administrator) + + const request = new ProjectionRequest(parameters.service, parameters.projection); + + return request; + + }, + /** + * + * @function + * @name writeProjectionResponse + * @description Ré-écriture de la réponse pour une requête sur /services//projections/ + * @param {object} projectionResponse - Instance de la classe ProjectionResponse + * @return {object} userResponse - Réponse envoyée à l'utilisateur + * + */ + + writeProjectionResponse: function(projectionResponse) { + + let userResponse = {}; + + LOGGER.debug("writeProjectionResponse()"); + + // On doit utiliser les attributs avec _ car les méthodes ne sont pas disponible dans le cadre d'une communication IPC + userResponse.id = projectionResponse._id; + + return userResponse; + } } \ No newline at end of file diff --git a/src/js/apis/admin/1.0.0/index.js b/src/js/apis/admin/1.0.0/index.js index f82474c..376c9a6 100644 --- a/src/js/apis/admin/1.0.0/index.js +++ b/src/js/apis/admin/1.0.0/index.js @@ -197,6 +197,50 @@ router.route("/services/:service/restart") }); +// Services/{service}/projections/{projection} +// Récupérer une projection supportée par un service +router.route("/services/:service/projections/:projection") + + .get(async function(req, res, next) { + + LOGGER.debug("requete GET sur /admin/1.0.0/services/:service/projections/:projection"); + LOGGER.debug(req.originalUrl); + + // On récupère l'instance d'Administrator pour répondre aux requêtes + let administrator = req.app.get("administrator"); + + // on récupère l'ensemble des paramètres de la requête + const parameters = req.params; + LOGGER.debug(parameters); + + try { + + // Vérification des paramètres de la requête + const projectionRequest = controller.checkProjectionParameters(parameters); + LOGGER.debug(projectionRequest); + + // Envoie à l'administrateur et récupération de l'objet réponse + const projectionResponse = await administrator.computeRequest(projectionRequest.service, projectionRequest); + LOGGER.debug(projectionResponse); + + // Vérification de l'id retourné (utilisation attribut car communication IPC) + if (projectionResponse._id == "") { + next(errorManager.createError("Unknown projection", 404)); + }else{ + // Formattage de la réponse + const userResponse = controller.writeProjectionResponse(projectionResponse); + LOGGER.debug(userResponse); + + res.set('content-type', 'application/json'); + res.status(200).json(userResponse); + } + + } catch (error) { + return next(error); + } + + }); + // Gestion des erreurs // Cette partie doit être placée après la définition des routes normales // --- diff --git a/src/js/requests/projectionRequest.js b/src/js/requests/projectionRequest.js new file mode 100644 index 0000000..139f7c4 --- /dev/null +++ b/src/js/requests/projectionRequest.js @@ -0,0 +1,83 @@ +'use strict'; + +const Request = require('./request'); + +/** +* +* @class +* @name projectionRequest +* @description Classe modélisant une requête sur une projection d'un service géré par l'administrateur. +* +*/ + +module.exports = class projectionRequest extends Request { + + /** + * + * @function + * @name constructor + * @description Constructeur de la classe projectionRequest + * @param {string} serviceId - Id du service interrogé + * @param {string} projectionId - Id de la projection interrogée + * + */ + + constructor(serviceId, projectionId) { + + super("projection", "projectionRequest"); + + // Id du service d'après l'administrateur + this._service = serviceId; + + // Id de la projection + this._projection = projectionId; + + } + + /** + * + * @function + * @name get service + * @description Récupérer service de la requete + * + */ + get service() { + return this._service; + } + + /** + * + * @function + * @name set service + * @description Attribuer le service de la requete + * @param {string} id - Id du service + * + */ + set service(id) { + this._service = id; + } + + /** + * + * @function + * @name get projection + * @description Récupérer la projection demandée + * + */ + get projection() { + return this._projection; + } + + /** + * + * @function + * @name set projection + * @description Attribuer la projection de la requete + * @param {string} id - Id de la projection + * + */ + set projection(id) { + this._projection = id; + } + +} diff --git a/src/js/responses/projectionResponse.js b/src/js/responses/projectionResponse.js new file mode 100644 index 0000000..a4f369a --- /dev/null +++ b/src/js/responses/projectionResponse.js @@ -0,0 +1,56 @@ +'use strict'; + +const Response = require('./response'); + +/** +* +* @class +* @name projectionResponse +* @description Classe modélisant une réponse de description d'une projection +* +*/ + +module.exports = class projectionResponse extends Response { + + + /** + * + * @function + * @name constructor + * @description Constructeur de la classe projectionResponse + * + */ + constructor() { + + // Type de la réponse + super("projectionResponse"); + + // Identifiant + this._id = ""; + + } + + /** + * + * @function + * @name get id + * @description Récupérer l'identifiant + * + */ + get id () { + return this._id; + } + + /** + * + * @function + * @name set id + * @description Attribuer l'identifiant + * @param {string} id - identifiant + * + */ + set id (id) { + this._id = id; + } + +} diff --git a/src/js/service/service.js b/src/js/service/service.js index 79ece38..f19078d 100644 --- a/src/js/service/service.js +++ b/src/js/service/service.js @@ -16,6 +16,8 @@ const LogManager = require('../utils/logManager'); const log4js = require('log4js'); const errorManager = require('../utils/errorManager'); const HealthResponse = require('../responses/healthResponse'); +const ProjectionResponse = require('../responses/projectionResponse'); +const projectionRequest = require('../requests/projectionRequest'); // Création du LOGGER const LOGGER = log4js.getLogger("SERVICE"); @@ -1045,6 +1047,8 @@ module.exports = class Service { // Le if est un choix modifiable. Pour le moment c'est ainsi car dans le cas du serviceProcess, on ne peut pas y échapper. if (request._type === "healthRequest") { return this.computeHealthRequest(request); + }else if (request._type === "projectionRequest") { + return this.computeProjectionRequest(request); } else { throw errorManager.createError("Unknown request type"); } @@ -1109,4 +1113,33 @@ module.exports = class Service { } + /** + * + * @function + * @name computeProjectionRequest + * @description Fonction utilisée pour connaitre une projection utilisée par un service + * @param {projectionRequest} projectionRequest - Instance de la classe projectionRequest + * + */ + + computeProjectionRequest(projectionRequest) { + + LOGGER.info("computeProjectionRequest..."); + + // On doit utiliser les attributs avec _ car les méthodes ne sont pas disponible dans le cadre d'une communication IPC + let projectionResponse = new ProjectionResponse(); + if ( !this._projectionManager.isProjectionLoaded(projectionRequest._projection)){ + projectionResponse.id = ""; + // Le lancement d'exception n'est pas possible car il n'y aura dans ce cas pas de réponse IPC envoyé avec l'uuid de la requete + // On envoie donc une réponse avec un id vide pour le traiter comme 404 dans l'administrateur + //throw errorManager.createError(`Can't find projection ${projectionRequest._projection}`, 404) + } + else{ + + projectionResponse.id = projectionRequest._projection; + } + + return projectionResponse; + } + } diff --git a/src/js/service/serviceManager.js b/src/js/service/serviceManager.js index c8e150d..6affa08 100644 --- a/src/js/service/serviceManager.js +++ b/src/js/service/serviceManager.js @@ -234,7 +234,7 @@ module.exports = class serviceManager { let administeredService = this._loadedServiceAdministeredCatalog[serviceId]; if (!administeredService) { LOGGER.error("Aucun service associé à cet ID: " + serviceId); - throw errorManager.createError("Unknown service : " + serviceId); + throw errorManager.createError("Unknown service : " + serviceId, 404); } // On envoit la requête et renvoit la réponse diff --git a/test/functional/request/cucumber/configurations/local-admin.json b/test/functional/request/cucumber/configurations/local-admin.json index 1b4a3e6..8b26c8f 100644 --- a/test/functional/request/cucumber/configurations/local-admin.json +++ b/test/functional/request/cucumber/configurations/local-admin.json @@ -10,7 +10,8 @@ "configuration": "/admin/1.0.0/configuration", "services": "/admin/1.0.0/services", "services/": "/admin/1.0.0/services/", - "services//restart": "/admin/1.0.0/services//restart" + "services//restart": "/admin/1.0.0/services//restart", + "services//projections/": "/admin/1.0.0/services//projections/" } } }, diff --git a/test/functional/request/cucumber/features/req-admin-1.0.0.feature b/test/functional/request/cucumber/features/req-admin-1.0.0.feature index 092f0cf..bc69e84 100644 --- a/test/functional/request/cucumber/features/req-admin-1.0.0.feature +++ b/test/functional/request/cucumber/features/req-admin-1.0.0.feature @@ -144,3 +144,33 @@ Feature: Road2 with data When I send the request Then the server should send a response with status 404 And the response should contain "Can't find service" + + Scenario: [admin/1.0.0] Projection valide du service "main" + Given an "GET" request on operation "services//projections/" in api "admin" "1.0.0" + And with path parameters: + | key | value | + | service | main | + | projection | EPSG:4326 | + When I send the request + Then the server should send a response with status 200 + And the response should have an header "content-type" with value "application/json" + And the response should contain "id" + + Scenario: [admin/1.0.0] Projection invalide du service "main" + Given an "GET" request on operation "services//projections/" in api "admin" "1.0.0" + And with path parameters: + | key | value | + | service | main | + | projection | ftii | + When I send the request + Then the server should send a response with status 404 + + Scenario: [admin/1.0.0] Projection invalide du service "main" + Given an "GET" request on operation "services//projections/" in api "admin" "1.0.0" + And with path parameters: + | key | value | + | service | Unknown | + | projection | Unknown | + When I send the request + Then the server should send a response with status 404 + \ No newline at end of file diff --git a/test/integration/mocha/requests/integrationProjectionRequest.js b/test/integration/mocha/requests/integrationProjectionRequest.js new file mode 100644 index 0000000..3ca344e --- /dev/null +++ b/test/integration/mocha/requests/integrationProjectionRequest.js @@ -0,0 +1,41 @@ +const assert = require('assert'); +const ProjectionRequest = require('../../../../src/js/requests/projectionRequest'); +const logManager = require('../logManager'); + +describe('Test de la classe ProjectionRequest', function() { + + before(function() { + // runs before all tests in this block + logManager.manageLogs(); + }); + + let request = new ProjectionRequest("test", "EPSG:4326"); + + describe('Test du constructeur et des getters/setters', function() { + + it('Get type', function() { + assert.equal(request.type, "projectionRequest"); + }); + + it('Get service', function() { + assert.equal(request.service, "test"); + }); + + it('Set service', function() { + request.service = "main"; + assert.equal(request.service, "main"); + }); + + + it('Get projection', function() { + assert.equal(request.projection, "EPSG:4326"); + }); + + it('Set service', function() { + request.projection = "EPSG:2154"; + assert.equal(request.projection, "EPSG:2154"); + }); + + }); + +}); diff --git a/test/integration/mocha/responses/integrationProjectionResponse.js b/test/integration/mocha/responses/integrationProjectionResponse.js new file mode 100644 index 0000000..8808f84 --- /dev/null +++ b/test/integration/mocha/responses/integrationProjectionResponse.js @@ -0,0 +1,31 @@ +const assert = require('assert'); +const ProjectionResponse = require('../../../../src/js/responses/projectionResponse'); +const logManager = require('../logManager'); + +describe('Test de la classe ProjectionResponse', function() { + + before(function() { + // runs before all tests in this block + logManager.manageLogs(); + }); + + let response = new ProjectionResponse(); + + describe('Test du constructeur et des getters/setters', function() { + + it('Get type', function() { + assert.equal(response.type, "projectionResponse"); + }); + + it('Get id', function() { + assert.equal(response.id, ""); + }); + + it('Set id', function() { + response.id = "EPSG:4326"; + assert.equal(response.id, "EPSG:4326"); + }); + + }); + +}); From 0c48625ec3b57eb12b8a169ce81c2bb0217b1ef5 Mon Sep 17 00:00:00 2001 From: jmkerloch Date: Wed, 5 Apr 2023 14:57:49 +0200 Subject: [PATCH 2/5] feat(service): define _errorFlag in response to treat response as error. --- src/js/apis/admin/1.0.0/index.js | 17 ++++++----------- src/js/service/service.js | 15 +++++++++------ src/js/service/serviceProcess.js | 6 ++++++ .../cucumber/features/req-admin-1.0.0.feature | 2 +- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/js/apis/admin/1.0.0/index.js b/src/js/apis/admin/1.0.0/index.js index 376c9a6..07a5cbe 100644 --- a/src/js/apis/admin/1.0.0/index.js +++ b/src/js/apis/admin/1.0.0/index.js @@ -222,18 +222,13 @@ router.route("/services/:service/projections/:projection") // Envoie à l'administrateur et récupération de l'objet réponse const projectionResponse = await administrator.computeRequest(projectionRequest.service, projectionRequest); LOGGER.debug(projectionResponse); + + // Formattage de la réponse + const userResponse = controller.writeProjectionResponse(projectionResponse); + LOGGER.debug(userResponse); - // Vérification de l'id retourné (utilisation attribut car communication IPC) - if (projectionResponse._id == "") { - next(errorManager.createError("Unknown projection", 404)); - }else{ - // Formattage de la réponse - const userResponse = controller.writeProjectionResponse(projectionResponse); - LOGGER.debug(userResponse); - - res.set('content-type', 'application/json'); - res.status(200).json(userResponse); - } + res.set('content-type', 'application/json'); + res.status(200).json(userResponse); } catch (error) { return next(error); diff --git a/src/js/service/service.js b/src/js/service/service.js index f19078d..7eb289d 100644 --- a/src/js/service/service.js +++ b/src/js/service/service.js @@ -992,6 +992,8 @@ module.exports = class Service { response = this.computeAdminRequest(request); } catch(error) { LOGGER.error("Erreur lors de l'exécution de la requête: " + error); + error._uuid = request._uuid; + error._errorFlag = true process.send(error); return false; } @@ -1000,7 +1002,10 @@ module.exports = class Service { response._uuid = request._uuid; process.send(response); } catch(error) { - LOGGER.error("Erreur lors de l'exécution de la requête: " + error); + // TODO : gestion plus fine du renvoi d'un message, il faudrait que l'administrateur vérifie l'état du canal + LOGGER.error("Erreur lors de l'envoi de la réponse à la requête: " + error); + error._uuid = request._uuid; + error._errorFlag = true process.send(error); return false; } @@ -1119,20 +1124,18 @@ module.exports = class Service { * @name computeProjectionRequest * @description Fonction utilisée pour connaitre une projection utilisée par un service * @param {projectionRequest} projectionRequest - Instance de la classe projectionRequest + * @returns {projectionResponse} response - Instance de la classe projectionResponse * */ - computeProjectionRequest(projectionRequest) { + computeProjectionRequest(projectionRequest){ LOGGER.info("computeProjectionRequest..."); // On doit utiliser les attributs avec _ car les méthodes ne sont pas disponible dans le cadre d'une communication IPC let projectionResponse = new ProjectionResponse(); if ( !this._projectionManager.isProjectionLoaded(projectionRequest._projection)){ - projectionResponse.id = ""; - // Le lancement d'exception n'est pas possible car il n'y aura dans ce cas pas de réponse IPC envoyé avec l'uuid de la requete - // On envoie donc une réponse avec un id vide pour le traiter comme 404 dans l'administrateur - //throw errorManager.createError(`Can't find projection ${projectionRequest._projection}`, 404) + throw errorManager.createError(`Can't find projection ${projectionRequest._projection}`, 404); } else{ diff --git a/src/js/service/serviceProcess.js b/src/js/service/serviceProcess.js index 8f67b41..b0b8645 100644 --- a/src/js/service/serviceProcess.js +++ b/src/js/service/serviceProcess.js @@ -203,6 +203,12 @@ module.exports = class ServiceProcess extends ServiceAdministered { // On attend la réponse et on la renvoit let response = await this.waitResponse(request._uuid); + + // On vérifie s'il s'agit d'une erreur + if (response._errorFlag) { + // TODO : voir si on fait une fonction pour ajouter la récupération de la stack + throw errorManager.createError(response.error, response.status) + } return response; diff --git a/test/functional/request/cucumber/features/req-admin-1.0.0.feature b/test/functional/request/cucumber/features/req-admin-1.0.0.feature index bc69e84..62b0b5c 100644 --- a/test/functional/request/cucumber/features/req-admin-1.0.0.feature +++ b/test/functional/request/cucumber/features/req-admin-1.0.0.feature @@ -161,7 +161,7 @@ Feature: Road2 with data And with path parameters: | key | value | | service | main | - | projection | ftii | + | projection | unknown | When I send the request Then the server should send a response with status 404 From a6e4ed7193ecb7ed31a837fba2f8b96f65b31406 Mon Sep 17 00:00:00 2001 From: jmkerloch Date: Thu, 6 Apr 2023 09:04:15 +0200 Subject: [PATCH 3/5] feat(projection): return 400 if empty parameter --- src/js/administrator/administrator.js | 1 + .../apis/admin/1.0.0/controller/controller.js | 6 +++--- .../cucumber/features/req-admin-1.0.0.feature | 21 ++++++++++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/js/administrator/administrator.js b/src/js/administrator/administrator.js index 4d87e19..4fb10c8 100644 --- a/src/js/administrator/administrator.js +++ b/src/js/administrator/administrator.js @@ -482,6 +482,7 @@ module.exports = class Administrator { * @description Gestion de la requête pour une route d'administration sur un serveur * @param {string} serviceId - Id du service selon l'administrateur * @param {object} request - Instance fille de la classe Request + * @return {object} responses - Json contenant la réponse du service à la requête * */ diff --git a/src/js/apis/admin/1.0.0/controller/controller.js b/src/js/apis/admin/1.0.0/controller/controller.js index 4bb76fe..022a4c8 100644 --- a/src/js/apis/admin/1.0.0/controller/controller.js +++ b/src/js/apis/admin/1.0.0/controller/controller.js @@ -101,7 +101,7 @@ module.exports = { throw errorManager.createError(" Parameter 'service' is invalid: there is no value", 400); } - if (parameters.service === "") { + if (parameters.service.trim() === "") { throw errorManager.createError(" Parameter 'service' is invalid: value should not be empty", 400); } @@ -133,7 +133,7 @@ module.exports = { throw errorManager.createError(" Parameter 'service' is invalid: there is no value", 400); } - if (parameters.service === "") { + if (parameters.service.trim() === "") { throw errorManager.createError(" Parameter 'service' is invalid: value should not be empty", 400); } @@ -142,7 +142,7 @@ module.exports = { throw errorManager.createError(" Parameter 'projection' is invalid: there is no value", 400); } - if (parameters.projection === "") { + if (parameters.projection.trim() === "") { throw errorManager.createError(" Parameter 'projection' is invalid: value should not be empty", 400); } diff --git a/test/functional/request/cucumber/features/req-admin-1.0.0.feature b/test/functional/request/cucumber/features/req-admin-1.0.0.feature index 62b0b5c..efc33d6 100644 --- a/test/functional/request/cucumber/features/req-admin-1.0.0.feature +++ b/test/functional/request/cucumber/features/req-admin-1.0.0.feature @@ -172,5 +172,24 @@ Feature: Road2 with data | service | Unknown | | projection | Unknown | When I send the request - Then the server should send a response with status 404 + Then the server should send a response with status 404 + + Scenario: [admin/1.0.0] Projection sur service non défini + Given an "GET" request on operation "services//projections/" in api "admin" "1.0.0" + And with path parameters: + | key | value | + | service | %20 | + | projection | EPSG:4326 | + When I send the request + Then the server should send a response with status 400 + + + Scenario: [admin/1.0.0] Projection non définie sur service "main" + Given an "GET" request on operation "services//projections/" in api "admin" "1.0.0" + And with path parameters: + | key | value | + | service | main | + | projection | %20 | + When I send the request + Then the server should send a response with status 400 \ No newline at end of file From 66572645a9e299cf37059acc73dc3f53a8d17102 Mon Sep 17 00:00:00 2001 From: jmkerloch Date: Thu, 6 Apr 2023 09:04:30 +0200 Subject: [PATCH 4/5] feat(projection): update changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 414d2ef..935a67a 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,7 @@ ADDED: - Ajout de la route GET /admin/1.0.0/services dans l'API d'administration - Ajout de la route GET /admin/1.0.0/services/{service} dans l'API d'administration - Ajout de la route GET /admin/1.0.0/services/{service}/restart dans l'API d'administration + - Ajout de la route GET /admin/1.0.0/services/{service}/projections/{projection} dans l'API d'administration - Ajout de la route GET /admin/1.0.0/configuration dans l'API d'administration - Il est maintenant possible démarrer un administrateur sans services pré-configurés From 68df61750c06b41cd864dab47088e130593dcc5c Mon Sep 17 00:00:00 2001 From: Loic Date: Thu, 6 Apr 2023 11:57:59 +0200 Subject: [PATCH 5/5] [feat] add error message when needed --- src/js/service/service.js | 22 +++++++++++++++------- src/js/service/serviceProcess.js | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/js/service/service.js b/src/js/service/service.js index 7eb289d..f397f58 100644 --- a/src/js/service/service.js +++ b/src/js/service/service.js @@ -991,9 +991,15 @@ module.exports = class Service { try { response = this.computeAdminRequest(request); } catch(error) { - LOGGER.error("Erreur lors de l'exécution de la requête: " + error); + // C'est un cas particulier : on veut retrouver l'usage des controller d'APIs + // => comme c'est une requête, on fait du throw en cas d'erreur et c'est normal + // ce n'est pas une vraie erreur. Cependant, on veut renvoyer l'erreur au parent + // donc on copie le message + LOGGER.info("Erreur lors de l'exécution de la requête: " + error.message); error._uuid = request._uuid; - error._errorFlag = true + error._errorFlag = true; + error._message = error.message; + error._stack = error.stack; process.send(error); return false; } @@ -1005,7 +1011,9 @@ module.exports = class Service { // TODO : gestion plus fine du renvoi d'un message, il faudrait que l'administrateur vérifie l'état du canal LOGGER.error("Erreur lors de l'envoi de la réponse à la requête: " + error); error._uuid = request._uuid; - error._errorFlag = true + error._errorFlag = true; + error._message = error.message; + error._stack = error.stack; process.send(error); return false; } @@ -1134,15 +1142,15 @@ module.exports = class Service { // On doit utiliser les attributs avec _ car les méthodes ne sont pas disponible dans le cadre d'une communication IPC let projectionResponse = new ProjectionResponse(); - if ( !this._projectionManager.isProjectionLoaded(projectionRequest._projection)){ - throw errorManager.createError(`Can't find projection ${projectionRequest._projection}`, 404); - } - else{ + if (!this._projectionManager.isProjectionLoaded(projectionRequest._projection)) { + throw errorManager.createError(`Can't find projection ${projectionRequest._projection}`, 404); + } else { projectionResponse.id = projectionRequest._projection; } return projectionResponse; + } } diff --git a/src/js/service/serviceProcess.js b/src/js/service/serviceProcess.js index b0b8645..f513d0d 100644 --- a/src/js/service/serviceProcess.js +++ b/src/js/service/serviceProcess.js @@ -206,8 +206,8 @@ module.exports = class ServiceProcess extends ServiceAdministered { // On vérifie s'il s'agit d'une erreur if (response._errorFlag) { - // TODO : voir si on fait une fonction pour ajouter la récupération de la stack - throw errorManager.createError(response.error, response.status) + // TODO : voir ce qu'on fait de la stack dispo dans response._stack + throw errorManager.createError(response._message, response.status); } return response;