From 872a29d1312c5240d6856a4bddd9d1491f0b67df Mon Sep 17 00:00:00 2001 From: codesketch Date: Wed, 12 Sep 2018 21:44:24 +0100 Subject: [PATCH 1/2] Fix issue --- .../node/infrastructure/service/instance.js | 7 ++- .../node/infrastructure/service/service.js | 17 +++++-- src/main/resources/routes.yml | 45 ++++++++++++++++++- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/main/node/infrastructure/service/instance.js b/src/main/node/infrastructure/service/instance.js index a55a324..04ec860 100644 --- a/src/main/node/infrastructure/service/instance.js +++ b/src/main/node/infrastructure/service/instance.js @@ -65,7 +65,12 @@ class Instance { acc[header[0]] = header[1]; } return acc; - }, {}) + }, {}), + // https://gitlab.com/codesketch/ipa/issues/5 + // as a defuault set responseType as arraybuffer so the we get the result as is, + // see https://github.com/axios/axios/blob/ccc78899bb6f595e3c44ec7ad6af610455859d78/lib/adapters/http.js#L197 + // that means the response can be trated as utf8 string only if needed meaning that the response is json, xml, etc. + responseType: 'arraybuffer' }; if (['post', 'put', 'patch'].includes(req.method.toLowerCase())) { answer.data = req.body; diff --git a/src/main/node/infrastructure/service/service.js b/src/main/node/infrastructure/service/service.js index 581941d..4793fe5 100644 --- a/src/main/node/infrastructure/service/service.js +++ b/src/main/node/infrastructure/service/service.js @@ -111,9 +111,20 @@ class Service { * @private */ propagateResponse(clientResponse, serverResponse) { - clientResponse.status(serverResponse.status); - Object.entries(serverResponse.headers || {}).forEach(entry => clientResponse.set(entry[0], entry[1])); - clientResponse.send(serverResponse.data); + try { + // https://gitlab.com/codesketch/ipa/issues/5 + // identity the response type based on the response content-type and decide what to do with the response. + let responseData = serverResponse.data; + if (!['image'].some(ct => serverResponse.headers['content-type'].includes(ct))) { + responseData = responseData.toString('utf8'); + } + clientResponse.status(serverResponse.status); + Object.entries(serverResponse.headers || {}).forEach(entry => clientResponse.set(entry[0], entry[1])); + clientResponse.send(responseData); + } catch (e) { + logger.error('unable to handle response', e); + clientResponse.status(500).json({ message: 'Internal Server Error' }); + } } } diff --git a/src/main/resources/routes.yml b/src/main/resources/routes.yml index d4a62ca..7948d22 100644 --- a/src/main/resources/routes.yml +++ b/src/main/resources/routes.yml @@ -9,6 +9,42 @@ info: servers: - url: http://localhost:3030 paths: + /images/places/{placeId}: + get: + summary: Retrieve the image for a place + operationId: getPlaceImage + backend: + $ref: "#/backends/images" + authentication: + $ref: "#/authentications/api-key" + policies: + - $ref: "#/policies/spike-arrest" + - $ref: "#/policies/quota" + tags: + - images + security: + - ApiKeyAuth: [] + parameters: + - name: placeId + in: path + required: true + description: The identifier for the place to retrieve + schema: + type: string + responses: + '200': + description: Place image + content: + image/png: + schema: + $ref: "#/components/schemas/Image" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /uuid: get: summary: Get a UUID from httpbin @@ -51,7 +87,7 @@ paths: cache: - $ref: "#/cache" tags: - - pets + - anything security: - ApiKeyAuth: [] parameters: @@ -88,6 +124,10 @@ components: name: Authorization schemas: + Image: + type: string + format: binary + UUID: required: - uuid @@ -116,6 +156,9 @@ backends: protocol: http service: places port: 3030 + images: + type: webDiscoveryService + target: https://api.prod.daphne-trails.com/api/ authentications: api-key: -- GitLab From 3e4ed5d6c27fe8dc9a5046675e49652eb5ff9951 Mon Sep 17 00:00:00 2001 From: codesketch Date: Wed, 12 Sep 2018 22:29:39 +0100 Subject: [PATCH 2/2] guess responsetype from accept and content-type headers --- src/main/node/infrastructure/service/instance.js | 14 +++++++++++++- src/main/node/infrastructure/service/service.js | 16 ++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/node/infrastructure/service/instance.js b/src/main/node/infrastructure/service/instance.js index 04ec860..57df8ce 100644 --- a/src/main/node/infrastructure/service/instance.js +++ b/src/main/node/infrastructure/service/instance.js @@ -56,6 +56,7 @@ class Instance { buildRequestOptions(req) { let pathname = `${this.basePath}${req.path}`.replace('//', '/'); + let responseType = this.determineResponseType(req); let answer = { url: url.format({ protocol: this.protocol, hostname: this.host, port: this.port, pathname: pathname, query: req.query }), method: req.method.toLowerCase(), @@ -70,7 +71,7 @@ class Instance { // as a defuault set responseType as arraybuffer so the we get the result as is, // see https://github.com/axios/axios/blob/ccc78899bb6f595e3c44ec7ad6af610455859d78/lib/adapters/http.js#L197 // that means the response can be trated as utf8 string only if needed meaning that the response is json, xml, etc. - responseType: 'arraybuffer' + responseType: responseType }; if (['post', 'put', 'patch'].includes(req.method.toLowerCase())) { answer.data = req.body; @@ -78,6 +79,17 @@ class Instance { logger.debug('request options', JSON.stringify(answer)); return answer; } + + determineResponseType(req) { + let answer = 'arraybuffer'; + if (req.headers.accept) { + const match = /.+\/(.+)/gi.exec(req.headers.accept); + if (['javascript', 'json', 'plain', 'csv', 'xml', 'css', 'html',].some(st => match[1] == st)) { + answer = match[1]; + } + } + return answer; + } } /** diff --git a/src/main/node/infrastructure/service/service.js b/src/main/node/infrastructure/service/service.js index 4793fe5..d198871 100644 --- a/src/main/node/infrastructure/service/service.js +++ b/src/main/node/infrastructure/service/service.js @@ -114,10 +114,7 @@ class Service { try { // https://gitlab.com/codesketch/ipa/issues/5 // identity the response type based on the response content-type and decide what to do with the response. - let responseData = serverResponse.data; - if (!['image'].some(ct => serverResponse.headers['content-type'].includes(ct))) { - responseData = responseData.toString('utf8'); - } + let responseData = this.extractResponseData(serverResponse); clientResponse.status(serverResponse.status); Object.entries(serverResponse.headers || {}).forEach(entry => clientResponse.set(entry[0], entry[1])); clientResponse.send(responseData); @@ -126,6 +123,17 @@ class Service { clientResponse.status(500).json({ message: 'Internal Server Error' }); } } + + extractResponseData(res) { + let answer = res.data; + if (res.headers['content-type']) { + const match = /.+\/(.+)/gi.exec(res.headers['content-type']); + if (['javascript', 'json', 'plain', 'csv', 'xml', 'css', 'html',].some(st => match[1] == st)) { + answer = answer.toString('utf-8'); + } + } + return answer; + } } /** -- GitLab