blob: 633f715f40b190759b2cdacf1ce04347c4b2ade3 [file] [log] [blame]
/*
* common.js: Common utility functions for requesting against Loggly APIs
*
* (C) 2010 Charlie Robbins
* MIT LICENSE
*
*/
var https = require('https'),
util = require('util'),
request = require('request'),
loggly = require('../loggly');
var common = exports;
//
// Failure HTTP Response codes based
// off Loggly specification.
//
var failCodes = common.failCodes = {
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
409: 'Conflict / Duplicate',
410: 'Gone',
500: 'Internal Server Error',
501: 'Not Implemented',
503: 'Throttled'
};
//
// Success HTTP Response codes based
// off Loggly specification.
//
var successCodes = common.successCodes = {
200: 'OK',
201: 'Created',
202: 'Accepted',
203: 'Non-authoritative information',
204: 'Deleted'
};
//
// Core method that actually sends requests to Loggly.
// This method is designed to be flexible w.r.t. arguments
// and continuation passing given the wide range of different
// requests required to fully implement the Loggly API.
//
// Continuations:
// 1. 'callback': The callback passed into every node-loggly method
// 2. 'success': A callback that will only be called on successful requests.
// This is used throughout node-loggly to conditionally
// do post-request processing such as JSON parsing.
//
// Possible Arguments (1 & 2 are equivalent):
// 1. common.loggly('some-fully-qualified-url', auth, callback, success)
// 2. common.loggly('GET', 'some-fully-qualified-url', auth, callback, success)
// 3. common.loggly('DELETE', 'some-fully-qualified-url', auth, callback, success)
// 4. common.loggly({ method: 'POST', uri: 'some-url', body: { some: 'body'} }, callback, success)
//
common.loggly = function () {
var args = Array.prototype.slice.call(arguments),
success = args.pop(),
callback = args.pop(),
responded,
requestBody,
headers,
method,
auth,
proxy,
uri;
//
// Now that we've popped off the two callbacks
// We can make decisions about other arguments
//
if (args.length === 1) {
if (typeof args[0] === 'string') {
//
// If we got a string assume that it's the URI
//
method = 'GET';
uri = args[0];
}
else {
method = args[0].method || 'GET';
uri = args[0].uri;
requestBody = args[0].body;
auth = args[0].auth;
headers = args[0].headers;
proxy = args[0].proxy;
}
}
else if (args.length === 2) {
method = 'GET';
uri = args[0];
auth = args[1];
}
else {
method = args[0];
uri = args[1];
auth = args[2];
}
function onError(err) {
if (!responded) {
responded = true;
if (callback) { callback(err) }
}
}
var requestOptions = {
uri: uri,
method: method,
headers: headers || {},
proxy: proxy
};
if (auth) {
requestOptions.headers.authorization = 'Basic ' + new Buffer(auth.username + ':' + auth.password).toString('base64');
}
if (requestBody) {
requestOptions.body = requestBody;
}
try {
request(requestOptions, function (err, res, body) {
if (err) {
return onError(err);
}
var statusCode = res.statusCode.toString();
if (Object.keys(failCodes).indexOf(statusCode) !== -1) {
return onError((new Error('Loggly Error (' + statusCode + '): ' + failCodes[statusCode])));
}
success(res, body);
});
}
catch (ex) {
onError(ex);
}
};
//
// ### function serialize (obj, key)
// #### @obj {Object|literal} Object to serialize
// #### @key {string} **Optional** Optional key represented by obj in a larger object
// Performs simple comma-separated, `key=value` serialization for Loggly when
// logging for non-JSON values.
//
common.serialize = function (obj, key) {
if (obj === null) {
obj = 'null';
}
else if (obj === undefined) {
obj = 'undefined';
}
else if (obj === false) {
obj = 'false';
}
if (typeof obj !== 'object') {
return key ? key + '=' + obj : obj;
}
var msg = '',
keys = Object.keys(obj),
length = keys.length;
for (var i = 0; i < length; i++) {
if (Array.isArray(obj[keys[i]])) {
msg += keys[i] + '=[';
for (var j = 0, l = obj[keys[i]].length; j < l; j++) {
msg += common.serialize(obj[keys[i]][j]);
if (j < l - 1) {
msg += ', ';
}
}
msg += ']';
}
else {
msg += common.serialize(obj[keys[i]], keys[i]);
}
if (i < length - 1) {
msg += ', ';
}
}
return msg;
};
//
// function clone (obj)
// Helper method for deep cloning pure JSON objects
// i.e. JSON objects that are either literals or objects (no Arrays, etc)
//
common.clone = function (obj) {
var clone = {};
for (var i in obj) {
clone[i] = obj[i] instanceof Object ? common.clone(obj[i]) : obj[i];
}
return clone;
};