From 4a25c13b6ed1913d540612452b2d45859685bf80 Mon Sep 17 00:00:00 2001 From: Gor Martsen Date: Sat, 9 Mar 2019 00:53:56 -0500 Subject: [PATCH 1/3] Some prototyping --- router-proxy.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/router-proxy.js b/router-proxy.js index 772d55d..dfcc3fa 100644 --- a/router-proxy.js +++ b/router-proxy.js @@ -749,7 +749,8 @@ function proxyRequest(route, path, method, jsonData, requestDetails, callback) { targetRequest.endpoint = { scope: endpointTargets[0].scope, - secureKey: endpointTargets[0].secureKey + secureKey: endpointTargets[0].secureKey, + binary: endpointTargets[0].binary } hookCall(targetRequest, 'before', function(){ @@ -806,13 +807,17 @@ function proxyRequest(route, path, method, jsonData, requestDetails, callback) { return callback(new Error('Endpoint not found'), null) } let bodyJSON = false - try { - bodyJSON = JSON.parse(body); - } catch (e) { - debug.debug('JSON.parse(body) Error received: %O', e); - return callback(new Error('Service respond is not JSON.')); + if(!targetRequest.endpoint.binary) { + try { + bodyJSON = JSON.parse(body); + } catch (e) { + debug.debug('JSON.parse(body) Error received: %O', e); + return callback(new Error('Service respond is not JSON.')); + } + } - debug.debug('%s body: %O', route, bodyJSON); + debug.debug('%s body: %O', route, body); + // process after hooks // hookCall requestDetails.headers and _buffer should contain response data. From 30ce5a0c45a23c231ba0665504cf0ffa68cdafa3 Mon Sep 17 00:00:00 2001 From: Gor Martsen Date: Sun, 10 Mar 2019 22:39:42 -0400 Subject: [PATCH 2/3] # prevent condition.payload from parsing non object data --- router-proxy.js | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/router-proxy.js b/router-proxy.js index e1d9480..3c5cc81 100644 --- a/router-proxy.js +++ b/router-proxy.js @@ -193,7 +193,7 @@ function getProperty( propertyName, object ) { let parts = propertyName.split( "." ), length = parts.length, i, - property = object || this; + property = object; for ( i = 0; i < length; i++ ) { if (!property[parts[i]]) { return new Error('Property Does not exists') @@ -235,6 +235,9 @@ function checkConditions(conditions, requestDetails, jsonData) { // check payload if (conditions.payload && conditions.payload.length && jsonData) { + if(typeof jsonData != "object") { + return false + } for (let payload of conditions.payload ) { debug.debug('Checking for condition %O', payload) let receivedPayloadValue = getProperty(payload.name, jsonData) @@ -339,12 +342,9 @@ function hookCall(targetRequest, phase, callback) { let headers = {}; // TODO verify date,content-type, transfer-encoding headers let skipHeaders = [ - 'host', - 'content-type', - 'date', - 'connection', - 'content-length', - 'transfer-encoding' + 'host', // issue to properly connect + 'connection', // if it is closed, behavior is unexpected + 'content-length', //issue with recounting length of the package ] for (var i in targetRequest.requestDetails.headers) { if (skipHeaders.indexOf(i) != -1) { @@ -547,17 +547,7 @@ function hookCall(targetRequest, phase, callback) { } else { debug.log('adapter processed'); - let bodyJSON = false - try { - bodyJSON = JSON.parse(body); - } catch (e) { - debug.debug('JSON.parse(body) Error received: %O', e); - debug.log('Notify before reseived not json') - } - if (bodyJSON) { - // need to replace body data - targetRequest.requestDetails._buffer = body - } + targetRequest.requestDetails._buffer = body // need to set headers x-set-XXXXX debug.debug('Adapter Headers received: %O code: %s', response.headers, response.statusCode); for (var i in response.headers) { @@ -566,8 +556,8 @@ function hookCall(targetRequest, phase, callback) { targetRequest.requestDetails.headers[headerName] = response.headers[i]; } } + delete targetRequest.requestDetails.headers['content-length'] if (phase == 'before') { - delete targetRequest.requestDetails.headers['content-length'] // resign it if (targetRequest.requestDetails.headers.signature) { targetRequest.requestDetails.headers.signature = 'sha256=' From c5157b5d4c9920c8fa4c7164903c8e5b950d7711 Mon Sep 17 00:00:00 2001 From: Gor Martsen Date: Sun, 10 Mar 2019 23:16:03 -0400 Subject: [PATCH 3/3] Use latest claster --- package.json | 2 +- router-proxy.js | 80 ++++++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 287f270..2e04a4a 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "dependencies": { "@microservice-framework/microservice": "^1.3.5", "@microservice-framework/microservice-client": "^1.3.0", - "@microservice-framework/microservice-cluster": "^1.2.2", + "@microservice-framework/microservice-cluster": "github:microservice-framework/microservice-cluster#2.x", "@microservice-framework/microservice-router-register": "^1.3.1", "debug": "^2.2.0", "dot": "^1.1.1", diff --git a/router-proxy.js b/router-proxy.js index 3c5cc81..73582e4 100644 --- a/router-proxy.js +++ b/router-proxy.js @@ -85,7 +85,7 @@ function applyAccessToken(requestDetails) { /** * Proxy GET requests. */ -function ProxyRequestGet(jsonData, requestDetails, callback) { +function ProxyRequestGet(url, requestDetails, callback) { applyAccessToken(requestDetails); if (requestDetails.url == '') { var Explorer = new ExplorerClass(requestDetails, callback); @@ -94,7 +94,7 @@ function ProxyRequestGet(jsonData, requestDetails, callback) { let cutPosition = requestDetails.url.lastIndexOf('/'); let route = requestDetails.url.substring(0, cutPosition); let path = requestDetails.url.substring(cutPosition + 1); - proxyRequest(route, path, 'GET', jsonData, requestDetails, callback); + proxyRequest(route, path, 'GET', url, requestDetails, callback); } /** @@ -124,12 +124,12 @@ function ProxyRequestPUT(jsonData, requestDetails, callback) { /** * Proxy DELETE requests. */ -function ProxyRequestDELETE(jsonData, requestDetails, callback) { +function ProxyRequestDELETE(url, requestDetails, callback) { applyAccessToken(requestDetails); let cutPosition = requestDetails.url.lastIndexOf('/'); let route = requestDetails.url.substring(0, cutPosition); let path = requestDetails.url.substring(cutPosition + 1); - proxyRequest(route, path, 'DELETE', jsonData, requestDetails, callback); + proxyRequest(route, path, 'DELETE', url, requestDetails, callback); } @@ -235,7 +235,7 @@ function checkConditions(conditions, requestDetails, jsonData) { // check payload if (conditions.payload && conditions.payload.length && jsonData) { - if(typeof jsonData != "object") { + if (typeof jsonData != "object") { return false } for (let payload of conditions.payload ) { @@ -268,7 +268,7 @@ function checkConditions(conditions, requestDetails, jsonData) { function matchRoute(targetRequest, routeItem) { let routeItems = targetRequest.route.split('/'); - if(routeItem.type == "metric") { + if (routeItem.type == "metric") { if (routeItem.conditions) { if (!checkConditions(routeItem.conditions, targetRequest.requestDetails, targetRequest.jsonData)) { @@ -580,6 +580,25 @@ function hookCall(targetRequest, phase, callback) { } +/** + * decode buffer to specidied by content-type format. + */ +function decodeData(contentType, buffer){ + let data = false + switch (contentType) { + case undefined: // version 1.x compatibility. If no content-type provided, assume json. + case 'application/json': { + data = JSON.parse(buffer); + break; + } + // Todo support more decoders here? + default: { + data = buffer + } + } + return data +} + /** * Find all hook routes by stage. */ @@ -764,10 +783,10 @@ function _request(getRequest, callback, targetRequest, noMetric) { debug.log('Metric route %s result %O', targetRequest.route, router); let statusCode = 0 - if(error) { + if (error) { statusCode = error.code } else { - if(response.statusCode) { + if (response.statusCode) { statusCode = response.statusCode } } @@ -849,8 +868,7 @@ function proxyRequest(route, path, method, jsonData, requestDetails, callback) { targetRequest.endpoint = { scope: endpointTargets[0].scope, - secureKey: endpointTargets[0].secureKey, - binary: endpointTargets[0].binary + secureKey: endpointTargets[0].secureKey } hookCall(targetRequest, 'before', function(){ @@ -877,6 +895,7 @@ function proxyRequest(route, path, method, jsonData, requestDetails, callback) { let i; let skipHeaders = [ 'host', + 'connection', 'content-length' ] for (i in requestDetails.headers) { @@ -906,19 +925,15 @@ function proxyRequest(route, path, method, jsonData, requestDetails, callback) { // TODO call after hooks return callback(new Error('Endpoint not found'), null) } - let bodyJSON = false - if(!targetRequest.endpoint.binary) { - try { - bodyJSON = JSON.parse(body); - } catch (e) { - debug.debug('JSON.parse(body) Error received: %O', e); - return callback(new Error('Service respond is not JSON.')); - } - + let bodyJSON = "" + try { + bodyJSON = decodeData(body, response.headers['content-type']) + } catch (e) { + debug.debug('decodeData Error received: %O', e); + return callback(e); } debug.debug('%s body: %O', route, body); - // process after hooks // hookCall requestDetails.headers and _buffer should contain response data. let answerDetails = { @@ -935,20 +950,23 @@ function proxyRequest(route, path, method, jsonData, requestDetails, callback) { endpoint: targetRequest.endpoint } hookCall(targetAnswer, 'after', function(){ - let body = false + // Double check updated _buffer after proxy. + let body = false try { - body = JSON.parse(answerDetails._buffer); + body = decodeData(answerDetails._buffer, answerDetails.headers['content-type']) } catch (e) { - debug.debug('JSON.parse(body) Error received: %O', e); - return callback(new Error('Service respond is not JSON.')); + debug.debug('decodeData Error received: %O', e); + return callback(e); } - // prefix with base_URL all urls - if (method != 'OPTIONS') { - if (body.url) { - body.url = process.env.BASE_URL + body.url; - } else if (body.id) { - body.url = process.env.BASE_URL + route + '/' + body.id; + if(typeof body == "object") { + // prefix with base_URL all urls + if (method != 'OPTIONS') { + if (body.url) { + body.url = process.env.BASE_URL + body.url; + } else if (body.id) { + body.url = process.env.BASE_URL + route + '/' + body.id; + } } } if (body instanceof Array) { @@ -973,7 +991,7 @@ function proxyRequest(route, path, method, jsonData, requestDetails, callback) { responseHeaders[i] = answerDetails.headers[i]; } } - + // deprecated. websoket need to be rewriten as a hook broadcast if (response.statusCode == 200) { sendBroadcastMessage(router, method, requestDetails.url, body); }