jeudi 23 juin 2016

NodeJS - Promise callback response [SyntaxError: Unexpected end of input]

I created the following NodeJS function. The issue I'm getting is, when I'm executing this code like: someFunc(parameter) .then(function(doSomething){ //do something here, which works fine here. }) //The following function works and is very similar to the next function. .then(someFunc1) // .then(impervaCreateIP) // //The following function works and is very similar to the above function. .then(someFunc3) .catch(function(e){ //catch error here. This works too. }) and calling the function below, it's giving me an error: [SyntaxError: Unexpected end of input] This error is coming because, when the control goes to impervaCreateIP() after function (someFunc1) is successfully complete, then inside impervaCreateIP(), the following lines are getting executed (which is waiting for a REST/API call to create a new OS Connection IP in Imperva system). httpHelp(options, data) .then(function(fullResponse){ var result = JSON.parse(fullResponse[1]) As you see above, as soon as httpHelp(options,data).then(function(fullResponse){ ... } section is called, if I print (console.log("anything")) just before the following line, it's showing that message fine. BUT, nothing is printed after the following line, reason: fullResponse[1] is NOT getting populated or not getting any valid value, by the time the following line is executed async way. This is resulting the program to go directly into the .fail(...){ .. } section and then it's going to someFunc3 (where it's NOT doing anything as exception caught during impervaCreateIP and finally reaching to the .catch(...){ .. } section and doing whatever I'm doing there. var result = JSON.parse(fullResponse[1]) Therefore, the program errors out at the .parse for the . character i.e. it's not able to PARSE anything for variable result as fullResponse[1] value is still set to "" (Blank/NULL) and it's yet to be populated. HOW, can I make my program to wait i.e. until the httpHelp(..).then(function(fullResponse) {.... } is fully done working with the REST/API call and it returns a valid value inside fullResponse[1]. PS: I see fullResponse[0].statusCode == 200, so connection is fine. Code: //Imperva create IP //qData is a hash array that has valid index/value pair values. var impervaCreateIP = function(qData){ var deferred = Q.defer(); var data = '{"connection-mode":"SSH","host-name":"server123.company.com"}' var options = { hostname: 'myImpervaServerInstance.mycompanydomain.com', port: 8083, method: 'POST', path: '/SecureSphere/api/v1/conf/serverGroups/'+ qData['siteName'] + '/' + qData['serverGroupName'] + '/servers/' + qData['ip'], headers: { 'Content-Type': 'application/xml', 'X-Requested-With': 'Nodejs', 'Cookie': 'JSESSIONID='+qData['sid'] } } //svtLog() is a logger that I'm using to log messages to a file. Out of scope of this post. svtLog('info','Imperva','Inside impervaCreateIP function') svtLog('info','Imperva',qData['ip']) svtLog('info','Imperva',qData['siteName']) svtLog('info','Imperva',qData['serverGroupName']) console.log('Inside impervaCreateIP') console.log(options); httpHelp(options, data) .then(function(fullResponse){ //The following section is not executing console.log("00 ---- this will print fine") var result = JSON.parse(fullResponse[1]) //The following section is not executing. It going straight to .catch() as the above line failed at .parse(fullResponse[1]) where fullResponse[1] is coming as BLANK. console.log("11 -----") console.log(result) console.log("22 -----") deferred.resolve(qData) console.log(result) }) .fail(function(e){ svtLog('error','Imperva','Failed to add IP in Imperva') svtLog('info','Imperva',qData['ip']) svtLog('error','Imperva',e) svtLog('info','Imperva','') deferred.reject(e) }) return deferred.promise; } fullResponse (snapshot of the array value is) in case of someFunc1/3 or ImpervaCreateIP is. I'm showing only the last 5 lines. I have made sure that head -5 for both files looks same and fullResponse[0] index value is mostly similar as well: [vagrant@localhost ws]$ cat -n someFunc1.ip.fullResponse.json |tail -5; echo ----------------; cat -n create.ip.fullResponse.json |tail -5 230 parser: null, 231 res: [Circular] }, 232 read: [Function] }, 233 '{"ip":"10.20.30.40","domain":"","connection-mode":"SSH","share-name":"","folder-path":"","user-name":"enter_your_userID","host-name":"test-imperva-clientserver01.cloud.mycompany.com","OS-type":"Linux"}' ] 234 ---------------- 233 parser: null, 234 res: [Circular] }, 235 read: [Function] }, 236 '' ] 237 [vagrant@localhost ws]$ If you notice, line# 232 and 233 in someFunc1.ip.fullResponse.json file, line# 232 ends fullResponse[0] and line# 233 starts fullResponse[1] values. In my case, lets assume someFunc1 is to find an IP thus, the output above shows, REST/API returned value fullResponse[1] value for finding an IP using Imperva REST/API (where method was GET), rest code is exactly similar to impervaCreateIP(). If you notice, line# 235 and #236 for create.ip.fullResponse.json file, you'll see that line# 235 ends fullResponse[0] array index value and line# 236 starts the value for fullResponse[1] and has a '' (Blank/NULL) in it, which means, while creating an IP using impervaCreateIP, it DID NOT receive the valid response from Imperva REST/API in fullResponse[1] array index which is used by var result = JSON.parse(...); // line in my NodeJS code above. Again, the only main different between someFunc1(find an IP) or impervaCreateIP (to create an IP) is, other than that, only console.log("...") message change a bit: For impervaCreateIP it's set to: method: 'POST', For someFunc1 it's set to: method: 'GET', OK, so it seems like, the issue is with when my method is either POST/DELETE + when I'm using var result = JSON.parse(fullResponse[1]). If I don't try to check anything using var result / JSON.parse as mentioned above, my code works fine. So, I think I the root cause is: fullResponse[1] is NOT getting populated for some reason in case my REST/API HTTP method is either POST or DELETE. If I DON'T use any status checking like what happened after impervaCreateIP(a POST action) or during someFunc3(i.e. impervaDeleteSessionID where the method is DELETE), then my program is working fine and my ERROR message goes away. BUT, I do want to verify what REST responded back for ex: so that I can catch whether REST connection worked + if create IP action failed due to permission issue for that user whose credentials I used to generate my JSESSIONID. I'm getting the ERROR only when its POST/DELETE and I'm doing JSON.parse(fullResponse[1]) How can I get the response body in the above NodeJS code, when HTTP method is "POST" or "DELETE" and I want to catch a condition as I mentioned below?? Thanks. FYI: When I tried the same impervaCreateIP NodeJS logic in a BASH shell script, I wrote the following code and it WORKS!!! as CURL command is returning all the OUTPUT good or bad i.e. with valid response code if there was an error during create IP script creation due to access issue for that user's credentials. All I'm trying to do in the NodeJS code is to catch that "do not have permission" ERROR which may come if the USER doesn't have enough privileges to CREATE an IP in Imperva system : ## Create a new IP OS connection in a given site, server group. create_ip() { JSESSIONID="${1}" addThisIP="${2}" siteName="${3}" serverGroupName="${4}" echo -e "n- Trying to create a new OS connection IP now.n"; ##Make sure while initiating a REST API call, any parameter which has ' ' (space) in Imperva should be substituted with '%20'. create_new_ip_output="$(curl -ik -X POST -H "Cookie: JSESSIONID=$JSESSIONID" -H "Content-Type: application/json" -H "Accept: application/json" "https://${MX}:8083/SecureSphere/api/v1/conf/serverGroups/${siteName// /%20}/${serverGroupName// /%20}/servers/${addThisIP}" -d '{"connection-mode":"SSH","host-name":"thisLinuxServer.fdqn","OS-type":"linux","user-name":"enter_your_userID"}')"; return_code="$?"; if [[ "${return_code}" == "0" && ! `echo "${create_new_ip_output}" | grep "do not have permission"` ]]; then echo -e "nn- OS connection IP (${addThisIP}) created successfully in site: ${siteName}, servergroup: ${serverGroupName} and stdout:n${create_new_ip_output}n"; return 0; else echo -e "nn- Failed to create a new OS connection IP (${addThisIP}) in site: ${siteName} and servergroup: ${serverGroupName}n- using session ID: ${JSESSIONID}, error log:n${create_new_ip_output}n"; return 1; fi }

Aucun commentaire:

Enregistrer un commentaire