Can we override JSON.stringify to obtain XSS - security

How can we bypass this function to obtain full XSS?
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
response = JSON.parse(xmlHttp.responseText);
AnyFunction(response);
}
else if (xmlHttp.readyState == 4 && xmlHttp.status != 200) {
console.log(xmlHttp.responseText);
}
}
xmlHttp.open('POST', url, true);
xmlHttp.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xmlHttp.setRequestHeader('Accept', 'application/json');
data = {'searchTerm':item}
xmlHttp.send(JSON.stringify(data));
There is only one search bar for user input.

Related

Using request, how to download the first N bytes and return them in a function?

I am a bit stuck and require your help.
Any idea on how do I change this downloader function (yes, I need to keep this as a function returning a buffer) making sure it download and returns only the first N bytes?
...
async function getDataFromURL(url) {
const options = {
uri: url,
gzip: true,
encoding: null,
method: 'GET',
};
let response = await request(options);
if (response.statusCode == 200) {
return response.body;
} else {
throw response.statusCode + " " + response.statusMessage;
};
};
...
let downloadedData = await getDataFromURL('https://server/file');
Solution thanks to #kmoser
...
async function getDataFromURL(url) {
const options = {
uri: url,
gzip: true,
encoding: null,
method: 'GET',
headers: {
'Range': 'bytes=0-253' // Maximum number of bytes to download
}
};
let response = context.request(options);
if (response.statusCode == 206 || response.statusCode == 200) {
return response.body;
} else {
throw response.statusCode + " " + response.statusMessage;
};
};
...
let downloadedData = await getDataFromURL('https://server/file');

How to add headers in node.js

I have the following headers:
X-NewRelic-ID: VQACUF9bCBABU1JQAAQPU1I=
X-Device-Descriptor-Id: YWY1Zjk5OGI5N2U1ODg0Zg
User-Agent: Sahibinden-Android/4.5.2 (671; Android 5.1.1; Android Android SDK built for x86)
x-api-key: e91092ad5ea2e030c201ce9ac4373f6b565a7842
x-client-profile: Generic_v2.1
x-device-id: d4dc022224a74bc7964cb4d449cd32c2
x-timestamp: 1591117620862
x-api-hash: DF7AB8944EDB3140BCB2A3EA9BC95F70C3200DB7
adid: b165e39f-b0ee-4b22-aee5-df3675136c2c
Content-Type: application/json; charset=utf-8
X-J3PopQvX-e: a;grA22x5m7f3tr-0iQLVuq4BLsOW3uMVgYrreUpRM5M9sSufn0I0K5QO-LrGIm1gY8IHM_GtH_7uQ-cRTU-eV9762ivhZAOpU0I2ZC_dii-H-LDjjBUj8dI1uMmlx8sJjURVN1NWhJuf7iYYkopysE4rI5Ku0OAq-vv8po6yl7vF6KA4c1JEoyeJHX0WImy3c4SV30gzj4fLe1HfYlsA1Qa3ea7pl6kE4fXnYZ0q9DbWcxT_xUBj2Hx7GPYqqdOy8LK2eVQtj_qIyBqlUMu_B1WBteBo8JpEDsCN6hVZVVOmCvzBFVrJgh3rXd-bz3J6-TAgFOgIlbKEob6SrxPFvmrjrjFz2CESgBYUe2YBkwzOMYiNfRLfYKRF9bifV53JcX25D6ycfE5wp72kRvUDsF049QUgUyEvAOIdZcOTbETQtoAOIYtvClrsZQ8lI8VuKpHaqm3z0Cz59jNvXDYSIyVGQ43BbFHYJmvuVDK5hms8YQe1AU4z-kWFEZbR1GI2SD3e1ivl5a8YQNj3YLId6HeHy1BZZ4vrMfKhRmW6RFz3E8--TDu3r9J_RyYOh7_UhJ6-KW1FQ4mnoAD-1ObhBgw7VvefrijzY6iQKbnVhR2GVs0eAMv8RvON81vgIE7eZvqv4TFbNfpFzbNDYE4JboRsrroyElH9kbRkh6xc8Y_dlXZnZqHZH8Z55f1rBAQjeci9YzxGUJ4ssJE2vlniRkUSf1IZEwpxDdeUmKjk95EmdNIuC3NapbQbeRumyoe7XBCN3GOJ860o1wfeVE_u6aPpwtWAU7Huc2wY4-0M8V-WraljaUYt3iH2qVV9K-GryALZujOmjl6lLZTFBEFqijc8=;oh90F-L4vdHrRPBFFSIfspu1OBIaoliYHzKnk2hKNKM=
X-J3PopQvX-a: 0JMyqk3jVhB_ktkVhvJjiwUXW1jwIGUwnf4AuOufJI0WLr3Urn4m1ANxyELGawEfHAh3vvz7CcPSjuByQZVxMm-jqYz7WjSseSmlZGLnkSqTaTTYN7Rfz7aZTf2fSHc-F5zaQdRGr3t_KDw17Wu1CTjo8QGWUizaHYjkkclkI2q9R7McZmd_K2dpbBGOFwuVeuH4BoTabg7m9PxQ5PoqFykgD2dp=1a8_-iWK85xHc7N0iC7Kr0CmVECcipNabR42f=D15vshVt0cxZaZZd9hFHoY_b9RrDR5AjRvUTznXmJalncdoR0Uf9oP8DEv=uwgpWYp2O1szeXLHhrH9x9uutcDvyvbikmfl4G3qMa1b9TFvkWQCU7xEKN0qE5MTF2JOkJP0K-tRspZTm1dV7hFISNrU-nNJnDr0NI7l8-97eot5jkcTL=I=_7NDicD=8LlPbyWHeWBts3RJBQndMnW9p=J2Kth5rDIrHzfxsodpT0PsEHYY--EGX7-ijux_Xy4BTzYfYIc1g5teDskpD11nxM1Z=ioeOo0Ig-ocuf9TlHQPZcGru8koECDU8AKu_eptN_B50=Molip5MRHnD994ZKDjzv3N2I85rGzEZIjAT33_VSKNcqdsPSkDzUNwYolSc272M3=mAMtA2j3vWPoTuBdxkNZ3BIlBiE2k5sjiAG8upeDiVhAOzQB8BeO2LmP4VHH88Ng5brkoHeX3ncLD4WkIw0R-9TAou3zNmsClfJ_0dszt24ISM-H0GNDwuKKFm92JswKvWQOrrRGAYZODRJCzQAZQgjn=oxnjxiznUegsD84foGvwAxZyZZq8yMGNuEUk0pePeQjxWmZznzAAolQer1JvM0iHGjRJwwfXnzTF71H8GElk-sPFYDOzje11ozUnOwgom-o5FYemTpj8aR4uHffTrQa1KwXK_KMkeuJY0Q2mXNXJo49CSbO=lqWL1fNxi5OTZsYU7q2jXCSStaNR1DuTymMBJO3IFBeNFZDysgaSFooy_4H8Oi4G-eXNkuTE3sT-m-ZRleF8aVbTuhWo_ZgWuQDHAgELj2wCeGHnmh1_AeewO4wM55Le-YSC2hGHtg2qXoruUCvlQ9XJ=pcS7PLEMfEGbpbxvOaPnHAxiMc1Ahq54ZIzo-tuxDBlrrBO9FMq0a__z_CJxD0hSgWBaF2nnrrKS4ijOOhP8s1T7nPEdEDQcbVO9Q_wNd8CVzU5yH-28cCf-ojGBemEziprBB=5uzby0OJsmUTkwNXJkiF=LEalaVMS=XMnJpPWIAhfBT7OGGB4OUMk=onoMa2GJnL4Wv4SsshAiEamEV7QKp53TIkQEXXpRXa3wvq0sjiXEH-0CGivZDiS2KK-ZgcB0d-_GMD4jifXUkEaw9xmMyNkAQ51HxxgRaqO1Io_2xVF=cz3xUIFN5dS044xhn2V2neeqHd31QL_xBAMvQd9En5rPmyHpy4tJGgYXqzOfznN87b_4xab=My0BkP8JC-=CduTE5yTzbZXpb3uAlhiVv=UvE1tCBoFGJgcqV_AJt_b80Re-2Tw0Jc-ELyVoNvFrVm4-eRFDNGYlRo0V_IRYaY3ImGsG4lyCjYRaTEFF1pI5=8e539paXrGCSQJlZ5qxcAh_454XM-frw_D=s_TiZLRYeFLdcvy1jgEbkKGEcj7DbuFxNu9_YEuto2PhPTnttYRB0XW3u-wYIfq0sEdkLVes3aEUgLg7UhVjJxKESVXZvoW2jRXgbNM0p0QnDtvC9lBz-z1U9=7UkFPLXAqG_DabIY920oEnlHpHXgDL9ifX5anNuNSvr25-BxXYRgxRnG9hah4eXAkc2PcBbqif5HA0nNxXvAzZ5j7ib=h-jqI8I84aDjehZTNxjIH=Z5gsYkTWVYO5U=cvyJ4Qe8gCJYzfDirhfR-I2lg7A5mvGJb15_tAjXLOnwI1874pJvhOUqfuD8eJpITuynP9LsqiRpEU1nw7X1s_Ray9SHU3EcGkr935P33m5CBvrNzASXSr=N7mzu-WxVjevBK9MrUNHNRfoXJfunTwGwPCYZEluL9YpTLDSZtrd470yVyZK-PHFo_TV8y=ETtA-IDysdrWrE9R-5DEQpkKpGJKGieNDHptrNMsVODRm2y_RGEzI_j-qmC8mQir2GDqTZKRWqmUzVkgCsIGviKYK5_h9JSERGlvrzkWIESKdX_skM-s1n0Q=Vm4bCmFz1hSBy3k2Dx0f8myZdLWR2E0InNHTjw5rmWELfr_=ax4l5EYJirE7sO3Wm9-eimauhNYen5KNC0PeGhJ7BLCu0eamN_PXge=r_G_HlF3xXhPA8FfkxCjV3v4fWCbtGBVIQGES0jQR0sGPmxHuZsQQ9BZuGhh9ykSYce-OmeOCu7xojRXh7PJx1AVwmhrm1jE48CTYSUfegx7p-CyeWKRkGOZ_gafCibxwnJ9mslopc0WviVvbbwBKrNuZrZlWXQrnzi8ml=oq35l4xWs0Nb7VZOYezEiUgoayg7pFm8eLV02GiU7lrpQMqF_pl04dXo3QAEwDW_YgIrLCtBoVM92dckSfScDL12nZREI3Yd-V3dkN23vFr2cFXbBKoHK2uVDTqUyzMxDgqHkXxPu3rzp9g0FSA95TgKke0ikBsX7KrdNBc9cQNgj2AouCXwIzzAExo2pa2wqJk7zXna3ObWHbgk1dpiJ=dk_Gbr3LOJ-CeTWGANr=u1Cnyo-weSvvLGMlQTJjWOedNDCtduC193Bfeqn2brGiKSUV3rx09ywipxjJVjGW=eJ_k0Cex7bIq_RNZJHso1qzQ-R=IR59XtaSyM9BLwKNJ4tOiCpMltCJyWOd0yJnYcgZSUCiLBINMh-e7F_Si-e_1c3VH5UqyENO8YvR59-IYl4qUQs5NpIEZc5Hl0lImENjL_7WsBB7jue4Ty0JPxXrYo3ME_P0Xc0UIEJKN3CQCzKl9a5ZmmMTrHyJHNNW0FSrMsAgUXRtDH_MuExGdqcEjgr-8hhoS2kAV_JER1FupukcsGi0JLegpLEYF9GLDnUoDCDrPRP5tQb21gQUpEdvozNmXdVNRCukPDJeRSSYr4iCM5=-3UzYPSDwkb=_7Ea=WvgXvKtIeKbYcF5ZPk8OU-rq_ysU2Slfaf7fgHHR4Aif2cx_ZTekL=0W5LQL3AZv2QBh-VjjNri
X-J3PopQvX-b: -1o1lvb
X-J3PopQvX-c: AEC_kwhyAQAA125LdUCpBmDn_gaT36bu5R1v7tLmaWD2Y_AhYfLAeVsrDVYa
X-J3PopQvX-d: o_2
X-J3PopQvX-f: AyT1lAhyAQAA645HTYkhB4gLDM5zokBx1RSq1NMZ34yfPEFY650x2JWUiytPAWf_BDWcuH01wH8AAEB3AAAAAA==
X-J3PopQvX-z: p
Host: api.sahibinden.com
Connection: Keep-Alive
Accept-Encoding: gzip
With each request I want to be able to regenerate following headers:
X-J3PopQvX-a
X-J3PopQvX-b
X-J3PopQvX-c
X-J3PopQvX-d
X-J3PopQvX-f
X-J3PopQvX-z
I know of XMLHttpRequest but Im not sure how to use it in this case. I am new to node.js so a bit clueless
Edit:
I am able to send my headers using this : try {
let res = await httpClient.get(url, {
headers: headers,
params: query,
});
But I want to change j3pop headers everytime I send them. Need to change them manually. Is there any way for that?
Edit1:
This code here generates new headers:
function() {
'use strict';
console.log("inside");
var afterReadyCbCalled = false;
var originalHeaders = ["X-Origin-DC", "gytp","Cache-Control", "max-age=0","X-Forwarded-For", "103.255.4.53","X-Client-SrcPort", "45244","Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language", "en-US,en;q=0.5","X-Forwarded-Proto", "https","X-TLS-Version", "771","Upgrade-Insecure-Requests", "1","ISTL-REFERER", "https://www.sahibinden.com/",];
var originalBody = "";
function afterReadyCb() {
if (afterReadyCbCalled) return;
afterReadyCbCalled = true;
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var isValid = xhr.getResponseHeader("ISTL-INFINITE-LOOP");
if (isValid != null && isValid != '') return;
var a = xhr.getResponseHeader("ISTL-REDIRECT-TO");
if (a != null && a != '') {
location.replace(a);
} else {
if (window.history != null && typeof history.replaceState === 'function') {
var responseURL = xhr.responseURL != null ? xhr.responseURL : xhr.getResponseHeader("ISTL-RESPONSE-URL");
if (responseURL != null && responseURL != '') {
history.replaceState(null, '', responseURL);
}
}
document.open();
document.write(xhr.responseText);
document.close();
}
};
xhr.open("get", location.href, true);
for (var i = 0; i < originalHeaders.length; i += 2) {
var headerName = originalHeaders[i];
try {
xhr.setRequestHeader(headerName, originalHeaders[i + 1]);
} catch (e) {}
}
xhr.setRequestHeader("ISTL-INFINITE-LOOP", '1');
xhr.send(originalBody);
var evt = document.createEvent('Event');
evt.initEvent('QLpZFJdHv', true, true);
dispatchEvent(evt);
}
addEventListener('afterReady', afterReadyCb, false);
setTimeout(afterReadyCb, 400);
}());
Code is extracted from website by simply saving the html. Here is the link to website : https://www.sahibinden.com/
Here a sample code:
function doScrapRequest (postData, onSuccessCallback, onErrorCallback) {
var options = {
hostname: "your-host-name",
port: 443,
path: "/path-you-want-to-post-to",
method: 'POST',
headers: {
'X-J3PopQvX-a': '0JMyqk3j...',
'X-J3PopQvX-b': '-1o1lvb'
'X-J3PopQvX-c': 'AEC_kwhy...'
'X-J3PopQvX-d': 'o_2'
'X-J3PopQvX-f': 'AyT1lA...'
'X-J3PopQvX-z': 'p'
}
};
var req = https.request(options, function (res) {
res.setEncoding('utf8');
var body = '';
res.on('data', function (chunk) {
body = body + chunk;
});
res.on('end',function(){
console.log("Body :" + body);
if (res.statusCode != 200) {
onErrorCallback("Api call failed with response code " + res.statusCode);
} else {
// If you are expecting application/json you can do JSON.parse in the body variable.
onSuccessCallback(body);
}
});
});
req.on('error', function (e) {
console.log("Error : " + e.message);
onErrorCallback(e);
});
// write data to request body
req.write(postData);
req.end();
}

Nodejs: Why is my Promise not work in PUT request? Resloved

I using that API to create resumable Upload in Drive.
It worked but i can't receive response data from Promise
Here is my code:
var fs = require('fs');
var request = require('request');
var mime = require('mime');
var _ = require("underscore");
class resumableUpload {
constructor(credentials,token,options={}){
this.credentials = credentials; // object from json credentials
this.token = token; // object from token credentials
this.new_token = {};
this.expiry_token_time = 0;
this.options = Object.assign({
size:256*1024,
retry:-1
},options)
}
refresh_token(){
return new Promise((ok,faild)=>{
var now = new Date().getTime();
if(now>this.expiry_token_time){
request.post("https://www.googleapis.com/oauth2/v4/token",{
form:{
refresh_token:this.token.refresh_token,
client_id:this.credentials.client_id,
client_secret:this.credentials.client_secret,
redirect_uri:this.credentials.redirect_uris[0],
grant_type:'refresh_token'
}
},(err,httpResponse,body)=>{
if(err) faild(err);
this.new_token = JSON.parse(body);
this.expiry_token_time = now + this.new_token.expires_in*1000;
ok(this.new_token.access_token);
})
}else{
ok(this.new_token.access_token);
}
})
}
/*
Upload Resumable
file:{
name:'name of file',
path:'path/to/file'
}
*/
upload(file){
return new Promise((ok,faild)=>{
this.refresh_token().then((access_token)=>{
console.log(access_token);
this.file_len = fs.statSync(file.path).size;
var form = {};
if(!_.isEmpty(file.name)) form.name = file.name;
if(!_.isEmpty(file.parents)) form.parents = [file.parents];
request.post({
uri:'https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable',
headers:{
'Authorization':`Bearer ${access_token}`,
'Content-Type':'application/json; charset=UTF-8',
'X-Upload-Content-Type':mime.getType(file.path),
'X-Upload-Content-Length': this.file_len,
'Content-Length':new Buffer(JSON.stringify(form)).length
},
body:JSON.stringify(form)
},(err,res,body)=>{
if(err || _.isEmpty(res.headers.location)){
if ((this.retry > 0) || (this.retry <= -1)) {
this.retry--;
return this.upload(file); // retry
} else {
//console.log(body);
faild("Over retry");
}
}else{
var location = res.headers.location;
//console.log("URL UPLOAD: ",location);
this.sendUpload(location,file).then((data)=>{
console.log("UPLOAD DONE!!!");
ok(data);
}).catch((err)=>{
console.log("ERROR: ",err);
faild(err);
});
}
})
}).catch(faild)
})
}
sendUpload(api,file,start=0){
return new Promise((ok,faild)=>{
this.refresh_token().then((access_token)=>{
var end = parseInt(start+this.options.size-1);
if(start>=this.file_len) ok("DONE");
if(end>=this.file_len) end = this.file_len - 1;
var headers = {
'Authorization':`Bearer ${access_token}`,
'Content-Length': parseInt(end - start + 1),
'Content-Range':`bytes ${start}-${end}/${this.file_len}`
}
var uploadPipe = fs.createReadStream(file.path, {
start: start,
end: end
})
uploadPipe.pipe(request.put({uri:api,headers:headers}).on('response',(res)=>{
if(res.statusCode == 308){
//console.log(res.headers);
var new_start = parseInt(res.headers.range.split('-')[1]);
console.log("Percent: "+(new_start/this.file_len*100).toFixed(2)+" %");
return this.sendUpload(api,file,new_start+1);
}else if(res.statusCode == 200 || res.statusCode == 201){
console.log("percent: 100 %");
//ok({status:"OK"});
}
}).on('error',(err)=>{
if ((this.retry > 0) || (this.retry <= -1)) {
this.retry--;
console.log("Retry Again");
return this.sendUpload(api,file,start);
}else{
faild("Over retry");
}
}).on('data',(data)=>{
if(!_.isEmpty(data)){
console.log(data.toString());
ok(data.toString());
}
}))
}).catch(faild)
})
}
}
module.exports = resumableUpload;
In that code - sendUpload function, I split my file to many chunk and upload it in to drive.
when I upload the last chunk, server will response statusCode is 200 or 201.
It console.log "percent: 100 %" and received data from that response.
My data of response like it:
{
"kind": "drive#file",
"id": "xxxxxxxxxxxxxxxxxxxxxxxxx",
"name": "test-video",
"mimeType": "video/mp4"
}
But, the Resolve (ok function) not call, cause in upload function, i can't receive it in then function. it mean i can't see "UPLOAD DONE!!!" in screen.
Resloved: Thanks for Roamer-1888
In Pipe, return a promise not work. I change return this.sendUpload(...) to this.sendUpload(...).then(ok,faild) and it worked.

Node.js allow only supported methods

The following is the start of an API. I'm trying to write as part of my lessons, the course is strictly node.js without any frameworks.
My attempt is to reject request with 400 if the request method is not allowed.
(if method in methoArr then allow else reject)
var http = require('http');
var fs = require('fs');
const url = require('url');
var os = require('os');
var helpers = require('./helperFunctions');
var cl = console.log.bind(console);
//init server and listen
http.createServer(function(req, res) {
//define req.url as array
let qs = url.parse(req.url).pathname;
//deal with favico request
if (req.url === '/favicon.ico') {
res.writeHead(200, {
'Content-Type': 'image/x-icon'
});
res.end();
return;
}
//return if method not allowed
const methodArr = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'];
var allowedMethod = true;
cl(typeof req.method, typeof methodArr[0]);
if (
req.url != methodArr[0] &&
req.url != methodArr[1] &&
req.url != methodArr[2] &&
req.url != methodArr[3] &&
req.url != methodArr[4] &&
req.url != methodArr[5]
) {
allowedMethod = false;
}
if (allowedMethod) {
// cl('req.url: ', qs, 'helpers: ', helpers, 'req method: ', req.method);
res.writeHead(200);
res.write('end url: ' + qs + ' method: ' + req.method);
} else {
res.writeHead(400);
res.write(req.method + ' method not allowed\n' + 'methodArr#: ' + methodArr[0]);
}
res.end();
}).listen(3000, 'localhost');
The if logic seems ok but obviously not...tried a switch but same issue.
I would appreciate if you can explain the error in my logic.
Use:
req.method
instead of
req.url
in condition.
if (
req.method != methodArr[0] &&
req.method != methodArr[1] &&
req.method != methodArr[2] &&
req.method != methodArr[3] &&
req.method != methodArr[4] &&
req.method != methodArr[5]
){
allowedMethod = false;
}
Or you can use this code :
if(methodArr.indexOf(req.method) < 0){
allowedMethod = false;
}

Why does my server never receive any requests made inside of a loop in Node.js?

My code works fine outside of a loop:
var localFolder = '/home/transcripts',
apiHost = 'https://someserver'
apiCall = '/path',
sharedSecret = 'secret';
/* includes */
var sys = require('sys'),
fs = require('fs'),
exec = require('child_process').exec,
querystring = require('querystring'),
crypto = require('crypto')
request = require('request');
var file = "index_07_03_2013_1209576.csv";
console.log('Pushing CSV to API: ' + file);
var r = request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
file = "index_07_02_2013_1548773.csv";
console.log('Pushing CSV to API: ' + file);
var r = request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
file = "index_07_02_2013_1548773.csv";
console.log('Pushing CSV to API: ' + file);
var r = request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
However, when I try to move it into a forEach loop, no request is ever received by the server. I do see output indicating that the CSV file is being pushed to the API, but the request never seems to hit the server. Here's the code for that:
#!/usr/local/bin/node
/* environment vars */
var localFolder = '/home/transcripts',
apiHost = 'https://someserver'
apiCall = '/path',
sharedSecret = 'secret';
/* includes */
var sys = require('sys'),
fs = require('fs'),
exec = require('child_process').exec,
querystring = require('querystring'),
crypto = require('crypto')
request = require('request');
var counter = 0;
fs.readdir(localFolder, function(err, files) {
files.forEach(function(file) {
if (file.substr(-3, 3) == 'csv') {
console.log('Pushing CSV to API: ' + file);
request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
console.log(request);
}
counter++;
});
if (counter >= files.length) {
process.exit(0);
}
});
Anyone have any ideas what the problem might be?
I guess the looping version breaks because you run process.exit(0) as soon as counter >= files.length evaluates to true.
The reason it actually breaks the intended functionality is probably because you spin off the request calls (which are asynchronous) very fast, and once you've done that, you exit the program. My guess is that since you don't actually wait for the requests to finish (i.e. when the callbacks are done), you exit the program prematurely.
What you need is basically a wait group, and that you make sure not to exit your program before all the callbacks are done.
Try something like this:
// imports, etc
// ...
var counter = 0;
function done() {
counter--;
if(counter === 0) {
process.exit(0);
}
}
var callback = function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
done();
}
fs.readdir(localFolder, function(err, files) {
counter = files.length;
files.forEach(function(file) {
if (file.substr(-3, 3) == 'csv') {
console.log('Pushing CSV to API: ' + file);
var data = {
form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
}
request.post(apiHost + '/' + apiCall, , data, callback);
}
}
);

Resources