I'm trying the basic examples using the Javascript Splunk SDK using Node 0.8.0.
Trying to login to Splunk through the API gives me a 404 error.
My Javascript code -
username = "admin";
password = "changeme";
scheme = "https";
host = "localhost";
port = "8089";
version = "5.0";
Async = splunkjs.Async;
utils = splunkjs.Utils;
var tag = null;
done = callback = function() {
$(tag).remove();
};
var http = new splunkjs.ProxyHttp("/proxy");
var service = new splunkjs.Service(http, {
username: username,
password: password,
scheme: scheme,
host: host,
port: port,
version: version
});
Async.chain([
// First, we log in
function(done) {
service.login(done);
},
// Retrieve the apps
function(success, done) {
if (!success) {
done("Error logging in");
}
service.apps().fetch(done);
},
// Print them out
function(apps, done) {
var appsList = apps.list();
console.log("Applications:");
for(var i = 0; i < appsList.length; i++) {
var app = appsList[i];
console.log(" App " + i + ": " + app.name);
}
done();
}
],
function(err) {
callback(err);
}
);
This is in my own code. The same script works when run from the SDK examples. What am I doing wrong?
EDIT - My backend is running in Node.JS so I'm confused as to whether I have to change some config files or not.
If I understand your question correctly, it is because you need to add a /proxy
endpoint on your Express server. Let me try and explain first what we do in the
SDK examples, and then this should make a bit more sense.
In the SDK, when you run sdkdo examples
or sdkdo runserver
, it will start
up a small webserver. You can see the code for this server here:
https://github.com/splunk/splunk-sdk-javascript/blob/master/bin/cli.js#L137
As you can see, this server is super simple. It has two rules:
If the URI starts with "/proxy", we will do some special handling, which
you can see here:
https://github.com/splunk/splunk-sdk-javascript/blob/master/bin/cli.js#L80
If it is anything else, we assume we need to serve a static file from the
filesystem.
The interesting case is (1), which you can see from the code. All it does is
look at the request that came in, and then "re-make" that request to the Splunk
server. This is because of the Single Origin Policy, since we can't talk
cross-domain.
For Express, you can do something very similar. You can use the app.all
function,
something like this:
app.all('/proxy/*', function(req, res) {
var error = {d: { __messages: [{ type: "ERROR", text: "Proxy Error", code: "PROXY"}] }};
var writeError = function() {
res.writeHead(500, {});
res.write(JSON.stringify(error));
res.end();
};
try {
var body = "";
req.on('data', function(data) {
body += data.toString("utf-8");
});
req.on('end', function() {
var destination = req.headers["X-ProxyDestination".toLowerCase()];
var options = {
url: destination,
method: req.method,
headers: {
"Content-Length": req.headers["content-length"],
"Content-Type": req.headers["content-type"],
"Authorization": req.headers["authorization"]
},
followAllRedirects: true,
body: body,
jar: false
};
try {
request(options, function(err, response, data) {
try {
var statusCode = (response ? response.statusCode : 500) || 500;
var headers = (response ? response.headers : {}) || {};
res.writeHead(statusCode, headers);
res.write(data || JSON.stringify(err));
res.end();
}
catch (ex) {
writeError();
}
});
}
catch (ex) {
writeError();
}
});
}
catch (ex) {
writeError();
}
});
I basically just copied the code from the example server. It probably needs a bit
of tweaking to confirm to the Express API, but should be pretty straightforward.
Hopefully this makes sense - let me know if I should clarify anything!
If this code is running from server-side, the HttpProxy is not required. you can use a pure splunkjs.Http object as the first parameter to Service creation.
This is absolutely correct, I did not consider that they may want to just do a server-side connection 🙂
Also, if you just want a default server-side connection, you don't need to pass anything to Service, it will do the correct thing by default.
If I understand your question correctly, it is because you need to add a /proxy
endpoint on your Express server. Let me try and explain first what we do in the
SDK examples, and then this should make a bit more sense.
In the SDK, when you run sdkdo examples
or sdkdo runserver
, it will start
up a small webserver. You can see the code for this server here:
https://github.com/splunk/splunk-sdk-javascript/blob/master/bin/cli.js#L137
As you can see, this server is super simple. It has two rules:
If the URI starts with "/proxy", we will do some special handling, which
you can see here:
https://github.com/splunk/splunk-sdk-javascript/blob/master/bin/cli.js#L80
If it is anything else, we assume we need to serve a static file from the
filesystem.
The interesting case is (1), which you can see from the code. All it does is
look at the request that came in, and then "re-make" that request to the Splunk
server. This is because of the Single Origin Policy, since we can't talk
cross-domain.
For Express, you can do something very similar. You can use the app.all
function,
something like this:
app.all('/proxy/*', function(req, res) {
var error = {d: { __messages: [{ type: "ERROR", text: "Proxy Error", code: "PROXY"}] }};
var writeError = function() {
res.writeHead(500, {});
res.write(JSON.stringify(error));
res.end();
};
try {
var body = "";
req.on('data', function(data) {
body += data.toString("utf-8");
});
req.on('end', function() {
var destination = req.headers["X-ProxyDestination".toLowerCase()];
var options = {
url: destination,
method: req.method,
headers: {
"Content-Length": req.headers["content-length"],
"Content-Type": req.headers["content-type"],
"Authorization": req.headers["authorization"]
},
followAllRedirects: true,
body: body,
jar: false
};
try {
request(options, function(err, response, data) {
try {
var statusCode = (response ? response.statusCode : 500) || 500;
var headers = (response ? response.headers : {}) || {};
res.writeHead(statusCode, headers);
res.write(data || JSON.stringify(err));
res.end();
}
catch (ex) {
writeError();
}
});
}
catch (ex) {
writeError();
}
});
}
catch (ex) {
writeError();
}
});
I basically just copied the code from the example server. It probably needs a bit
of tweaking to confirm to the Express API, but should be pretty straightforward.
Hopefully this makes sense - let me know if I should clarify anything!
There doesn't seem to be anything wrong with the code. I tried it (on apache) and it worked just fine.
Due to Same Origin Policy issues, you do need to set up a proxy for node to handle the requests to Splunk's REST APIs, i.e. on port 8089. For example, on apache, I have modified its httpd.conf file as follows:
SSLProxyEngine On
ProxyPass /proxy/ https://localhost:8089/
This works in the SDK examples for you because the examples are shipped with special handling for the "/proxy" requests.
I'm not using Apache though, I'm using Node.JS (along with Express) for my backend. (I just checked on my dev machine and I don't have Apache installed). Is there something I can do in Node/Express to do the same?