I have written a chunk of Node that is acting as a web hook for a GitHub repository I have. Basically when a commit is made to that repo, a request gets made to my function which then looks for potentially sensitive data that has been checked in. I'm making multiple calls to the GitHub API to pull down data. I tried to handle all of these calls by using the async package's waterfall
and each
functions.
There are two sections to the waterfall call: getting the commit data and then getting the file data. Within the "file data" section I have the async each
that is getting the actual file contents for each file.
I'm wondering if anyone can see any obvious best practices that I am not following for JavaScript programming. Am I handling the asynchronous calls the correct way? I created two helper functions to try and keep things clean/readable - should I break any other pieces out into their own functions?
var https = require('https')
var async = require('async')
module.exports = function (ctx,cb) {
console.log("**********************************************")
var danger = ['password','pass','pw','pwd','passwd','key','user','username','secret']
var re = new RegExp(danger.join('|'))
async.waterfall([
function(callback){
var options = {
host: 'api.github.com',
path: getApiPath(ctx.data.head_commit.url),
headers: {
'User-Agent': 'Broham'
}
}
getData(options, function(commitData){
// console.log("commit data", commitData)
callback(null,commitData.files)
})
},
//for each file, get the file content and look for potentially sensitive information that has been commited
function(files, callback){
// console.log("files", files)
var review = []
async.each(files, function(file, fileCallback){
var fileOptions = {
host: 'api.github.com',
path: file.contents_url.replace('https://api.github.com', ''),
headers: {
'User-Agent': 'Broham'
}
}
// get the JSON that will have the URL for the raw file content
getData(fileOptions, function(fileData){
// get the raw file content
https.get(fileData.download_url, function(contentData){
contentData.setEncoding('utf-8')
var contents = ''
contentData.on('data', function (data) {
contents += data
})
contentData.on('end', function(){
console.log('contents', contents)
// check to see if there are any matches for the terms we want to review.
matches = contents.match(re)
if(matches.length > 0){
// console.log("matches", matches)
review = review.concat(contents.match(re))
}
fileCallback()
})
})
})
}, function(err){
callback(null, review)
})
}
], function(err, results){
if(results.length > 0){
console.log("For review:", results)
}
cb(null, 'GitEye complete!')
console.log("**********************************************")
})
}
function getData(options, callback){
https.get(options, function(res){
res.setEncoding('utf-8')
var body = ''
res.on('data', function (data) {
body += data
})
res.on('end', function(){
// console.log('body', body)
var data = JSON.parse(body);
callback(data)
})
})
}
function getApiPath(url){
var pieces = url.split('/')
var user = pieces[3]
var repo = pieces[4]
var commit = pieces[6]
// return "https://api.github.com/repos/" + user + "/" + repo + "/commits/" + commit
return "/repos/" + user + "/" + repo + "/commits/" + commit
}