makeRequest.js
2.56 KB
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
/**
* Node.js native modules
*/
var qs = require('qs');
var crypto = require('crypto');
function _buildUrl(config, args, path) {
var qsConfig = { indices: false, arrayFormat: 'repeat' };
if (config.google_client_id && config.google_private_key) {
args.client = config.google_client_id;
// TODO
// is this the best way to clean the query string?
// why does request break the signature with ' character if the signature is generated before request?
// signature = signature.replace(/\+/g,'-').replace(/\//g,'_');
var query = qs.stringify(args, qsConfig).split('');
for (var i = 0; i < query.length; ++i) {
// request will escape these which breaks the signature
if (query[i] === "'") query[i] = escape(query[i]);
}
query = query.join('');
path = path + "?" + query;
if (config.google_channel) {
path += "&channel=" + config.google_channel;
}
// Create signer object passing in the key, telling it the key is in base64 format
var signer = crypto.createHmac('sha1', config.google_private_key);
// Get the signature, telling it to return the signature in base64 format
var signature = signer.update(path).digest('base64');
signature = signature.replace(/\+/g,'-').replace(/\//g,'_');
path += "&signature=" + signature;
return path;
} else {
return path + "?" + qs.stringify(args, qsConfig);
}
}
/**
* Makes the request to Google Maps API.
*/
module.exports = function(request, config, path, args, callback, requestMaxLength, encoding) {
requestMaxLength = requestMaxLength || -1;
var secure = config.secure;
if (config.key != null) {
// google requires https when including an apiKey
secure = true;
args.key = config.key;
}
path = _buildUrl(config, args, path);
if (requestMaxLength != -1 && path.length > requestMaxLength) {
error = new Error('Request too long for google to handle (' + requestMaxLength + ' characters).');
if (typeof callback === 'function') {
return callback(error);
}
throw error;
}
var options = {
uri: (secure ? 'https' : 'http') + '://maps.googleapis.com' + path
};
if (encoding) options.encoding = encoding;
if (config.proxy) options.proxy = config.proxy;
if (typeof callback !== 'function') {
return options.uri;
}
request(options, function (error, res, data) {
if (error) {
return callback(error);
}
if (res.statusCode === 200) {
return callback(null, data);
}
error = new Error(data);
error.code = res.statusCode;
return callback(error, data);
});
};