-
Notifications
You must be signed in to change notification settings - Fork 117
/
fetchHookSourceCode.js
165 lines (147 loc) · 5.39 KB
/
fetchHookSourceCode.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
var request = require('hyperquest');
var config = require('../../../config');
var path = require('path');
module['exports'] = function fetchHookSourceCode (opts, callback) {
var req = opts.req,
res = opts.res,
hook = opts.req.hook;
var cache = false;
var source = "gist";
var username, script, userHome, userFile;
if (hook.mode === "Production") {
cache = true;
}
// console.log('what is hook', hook)
// the user's temporary home directory
// will contain cached versions of Hook and Hook related assets
userHome = path.resolve(process.cwd() + '/' + config.tempDirectory + hook.owner + "/" + hook.name + "/");
userName = hook.owner;
/*
if (typeof req.hook.source !== "undefined" && req.hook.source.length > 5) {
source = "hook";
script = "index";
//return res.end('custom source' + req.hook.source);
}
*/
userFile = userHome + "/" + script + '.js';
opts.script = script;
function readSource (cb) {
// As per https://github.com/bigcompany/hook.io/issues/136, as FS access is removed from worker
// Instead of loading the code from an additional async source, we now assume that the
// source has already been loaded on the couchdb document
if (typeof hook.source === "undefined" || hook.source.length === 0) {
return fetchAndSaveSource(cb);
} else {
// console.log('using cached source', hook.source);
hook.originalSource = hook.source;
return callback(null, hook.source);
}
};
function saveSourceToDisk (code, cb) {
// TODO: save to couchdb now?
// req.saveHook = true;
hook.source = code;
hook.originalSource = code;
return cb(null, code);
}
function fetchRemoteGistSource (cb) {
var gist = opts.gist; // || "https://gist.github.com/Marak/357645b8a17daeb17458";
var userScript = gist.replace('https://gist.github.com/', '');
userScript = userScript.replace('/', ' ');
var parts = userScript.split(" ");
var username = parts[0],
script = parts[1];
var gistAPI = "https://api.github.com/gists/" + script;
// Indicate that a change has happened to the hook and it should be saved
// req.saveHook = true;
/*
fetches the latest version of source code from remote Github Gist Source
requires a valid and correctly formatted link to a github gist URL
*/
var options = {
headers: {
"User-Agent": "hook.io source code agent"
}
};
// must validate request. github API limits requests per hour. non-authorizated HTTP requests cap out quickly.
// warning: in the future, we might have to ask github to increase our API limit / create several access tokens
if (config.github.accessName && config.github.accessName.length && config.github.accessToken && config.github.accessToken.length) {
options.headers['Authorization'] = "Basic " + new Buffer(config.github.accessName + ":" + config.github.accessToken, "utf8").toString("base64")
}
// console.log('getting gistAPI', gistAPI)
request.get(gistAPI, options, function (err, apiRes) {
if (err) {
return res.end(err.message);
}
var apiReply = '';
apiRes.on('data', function (c) {
apiReply += c.toString();
});
apiRes.on('error', function(err){
return callback(err);
});
apiRes.on('end', function(){
var gistJSON = {}, files, keys;
try {
gistJSON = JSON.parse(apiReply.toString());
files = gistJSON.files;
keys = Object.keys(files);
} catch (err) {
return callback(new Error('Not valid JSON: ' + apiReply));
}
// assume first file is the source code
requestSource(gistJSON.files[keys[0]].raw_url);
});
function requestSource (source) {
// console.log('getting new hook source', source)
request.get(source, function (err, res) {
if (err) {
return opts.res.end(err.message);
}
var body = '';
res.on('data', function(c){
body += c.toString();
});
res.on('end', function(){
var code = body.toString();
req.hook.source = code;
// console.log('fetchHookSourceCode setting hook.source', code);
cb(null, code);
});
});
}
});
}
function fetchSource (cb) {
if (typeof hook.sourceType === "undefined") {
hook.sourceType = "code";
if (typeof hook.source === "undefined" || hook.source.length === 0) {
if (typeof hook.gist !== "undefined" && hook.gist.length > 0) {
hook.sourceType = "gist";
}
}
}
if (hook.sourceType === "gist") {
fetchRemoteGistSource(cb);
} else {
cb(null, hook.source);
}
};
function fetchAndSaveSource (cb) {
fetchSource(function (err, code) {
if (typeof code === "undefined") {
// TODO: better error / fetch for github source when doing /source
return res.end('no source code was found for this service yet.');
// return res.end('fetchandsave Unable to fetch hook source. We made a mistake. Please contact support');
}
saveSourceToDisk(code, cb);
});
}
if (cache) {
// if cache is enabled for Hook, attempt to read the temporary source file
readSource(callback);
} else {
// if no cache is enabled, fetch the source code and save it as a local temporary file
fetchAndSaveSource(callback);
}
};