I'm using nodejs 0.4.7 to make the request, this is my code:
var post_data = JSON.stringify({
'compilation_level' : 'ADVANCED_OPTIMIZATIONS',
'output_format': 'json',
'warning_level' : 'QUIET',
'js_code' : code
});
var post_options = {
host: 'closure-compiler.appspot.com',
port: '80',
path: 'compile',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': post_data.length
}
};
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Response: ' + chunk);
});
});
post_req.write(post_data);
post_req.end();
And the response I get is
Response: <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
here.
</BODY></HTML>
Why is this happening ? What am I doing wrong ? In the tutorial it says I'm suposed to make the POST request to http://closure-compiler.appspot.com/compile...
You're trying to send json data:
var post_data = JSON.stringify({
'compilation_level' : 'ADVANCED_OPTIMIZATIONS',
'output_format': 'json',
'warning_level' : 'QUIET',
'js_code' : code
});
Google Closure Compiler API wants standard form data, so you want to use querystring instead. Also you need to indicate the output format you want (compiled code I assume), as specified by their documentation:
var post_data = querystring.stringify({
'compilation_level' : 'ADVANCED_OPTIMIZATIONS',
'output_format': 'json',
'output_info': 'compiled_code',
'warning_level' : 'QUIET',
'js_code' : code
});
Path is better declared like so:
path: '/compile',
Here is the full proof of concept code:
var http = require('http');
var querystring = require('querystring');
var code ="// ADD YOUR CODE HERE\n" +
"function hello(name) {\n" +
" alert('Hello, ' + name);\n" +
"}\n" +
"hello('New user');\n";
var post_data = querystring.stringify({
'compilation_level' : 'ADVANCED_OPTIMIZATIONS',
'output_format': 'json',
'output_info': 'compiled_code',
'warning_level' : 'QUIET',
'js_code' : code
});
var post_options = {
host: 'closure-compiler.appspot.com',
port: '80',
path: '/compile',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': post_data.length
}
};
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Response: ' + chunk);
});
});
post_req.write(post_data);
post_req.end();
Running it with node.js produces the following:
$ node test.js
Response: {"compiledCode":"alert(\"Hello, New user\");"}
Related
I'm trying to connect user accounts on my website to patreon. I keep getting an access_denied error message in response to step 3. I'm following this documentation.
My node server code looks like this:
socket.on("patreon_register",function(code,user){
var reqString = "api.patreon.com/oauth2/token?code="
+code
+"&grant_type=authorization_code&client_id="
+settings.patreon.Client_ID
+"&client_secret="
+settings.patreon.Client_Secret
+"&redirect_uri="
+"http%3A%2F%2Fwww.levisinger.com%2F%3Fpage%3Dpatreon_success",
req = querystring.stringify({
"code": code,
"grant_type": "authorization_code",
"client_id": settings.patreon.Client_ID,
"client_secret": settings.patreon.Client_Secret,
"redirect_uri": "http%3A%2F%2Fwww.levisinger.com%2F%3Fpage%3Dpatreon_success"
}),
post_options = {
host: 'api.patreon.com',
port: '80',
path: '/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(req)
}
};
// Set up the request
console.log(req);
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log(chunk);
if(
chunk.access_token &&
chunk.refresh_token &&
chunk.expires_in &&
chunk.scope &&
chunk.token_type
){
Auth.linkPatreon(user,chunk,function(err,res){
if(err){ socket.emit('patreon_register',false,res); }
else { socket.emit('patreon_register',true,res); }
});
}
});
});
// post the data
post_req.write(req);
post_req.end();
});
The req variable that's actually sent to the server looks like this (changed my codes to generic values of course)
code=MY_RESPONSE_CODE&grant_type=authorization_code&client_id=MY_CLIENT_ID&client_secret=MY_CLIENT_SECRET&redirect_uri=MY_RESPONSE_URI
Any ideas?
In the end, my server looks like this and is working:
socket.on("patreon_register",function(code,user){
var req = querystring.stringify({
code: code,
grant_type: "authorization_code",
client_id: settings.patreon.Client_ID,
client_secret: settings.patreon.Client_Secret,
redirect_uri: settings.patreon.redirect_uri
}),
post_options = {
host: 'api.patreon.com',
port: '80',
path: '/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(req)
}
};
// Set up the request
console.log(req);
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
chunk = JSON.parse(chunk);
console.log(chunk);
if(!chunk["error"]){
console.log("Linking!");
Auth.linkPatreon(user,chunk,function(err,res){
if(err){ socket.emit('patreon_register',false,res); }
else { socket.emit('patreon_register',true,res); }
console.log("Linked!");
});
}
});
});
I am trying to make remote request call inside Node.js. But when I did, it gives me error below in Terminal.
BODY: <html>
<head><title>504 Gateway Time-out</title></head>
<body bgcolor="white">
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx</center>
</body>
</html>
This is the code.
var jsonObject = JSON.stringify(jsonData);
// HTTP Call - POST
var options = {
host: 'subdomain.example.com',
port: 80,
path: '/api/logs',
method: 'POST',
headers: {
'Content-Type' : 'application/json',
'api_key' : config.systemApikey,
'secret_key' : config.systemSecretkey
}
};
// do the POST call
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log('BODY: ' + data);
});
});
req.on('error', function(e) {
console.error(e);
});
req.write(jsonObject);
req.end();
If I try the host with local network like 192.168.0.2 with port 5000 (which I assign to use for that another application), it is working. I am new to Node.js, and please help me with what I did wrong here. Thanks.
host should be a string
var options = {
host: 'subdomain.example.com',
port: 80,
path: '/api/logs',
method: 'POST',
headers: {
'Content-Type' : 'application/json',
'api_key' : config.systemApikey,
'secret_key' : config.systemSecretkey
}
};
I've been digging deep into stack overflow but haven't been able to solve my problem. I'm trying to access an API that uses digest but have had no success, and my co-workers haven't been able to pin down the problem either. I've hit a wall and have come to Stack Overflow to ask my question.
Here is my authentication code:
var https = require("https"),
crypto = require('crypto'),
_ = require('underscore');
var options = {
host: 'api.example.com',
port: 80,
path: '/path/to/uri/',
method: 'GET',
accept: 'application/json',
acceptEncoding: 'gzip, deflate',
connection: 'keep-alive',
rejectUnauthorized: false,
requestCert: true,
agent: false
};
var username = 'username',
password = 'httppassword';
var req = https.get(options, function(res) {
res.setEncoding('utf-8');
console.log(res.url);
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
var data = "";
res.on('data', function (chunk) {
data = data + chunk;
});
res.on('end', function(){
console.log(data);
var challengeParams = parseDigest(res.headers['www-authenticate']);
console.log(challengeParams);
var ha1 = crypto.createHash('md5').update(username + ':' + challengeParams.realm + ':' + password).digest('hex');
var ha2 = crypto.createHash('md5').update('GET:' + options.path).digest('hex');
var response = crypto.createHash('md5').update(ha1 + ':' + challengeParams.nonce + ':1::auth:' + ha2).digest('hex');
var authRequestParams = {
username : username,
realm : challengeParams.realm,
nonce : challengeParams.nonce,
uri : options.path,
qop : challengeParams.qop,
response : response,
nc : 1,
cnonce : ''
};
options.headers = { 'Authorization' : renderDigest(authRequestParams) };
console.log(options);
https.get(options, function(res) {
console.log("STATUS: " + res.statusCode);
console.log("HEADERS: " + JSON.stringify(res.headers));
res.setEncoding('utf-8');
var content = '';
res.on('data', function(chunk) {
content += chunk;
}).on('end', function() {
console.log(content);
});
})
});
});
req.on('error' ,function(err){
console.log("request");
console.log(err);
});
req.write('data\n');
req.write('data\n');
req.end();
And here is the challenge header sent back by the API
{ realm: 'API realm',
domain: 'https:/api.example.com/',
qop: 'auth',
nonce: 'UZ43b0FWC9591pMjy1i6H2okVwgMbDVO6fcgcQ' }
EDIT:
I thought it would be helpful for those looking to answer this question for me to provide what I'm actually sending back to the API, so here it is.
{ host: 'api.example.com',
port: 80,
path: '/path/to/uri/',
method: 'GET',
accept: 'application/json',
acceptEncoding: 'gzip, deflate',
connection: 'keep-alive',
rejectUnauthorized: false,
requestCert: true,
agent: false,
headers: { Authorization: 'Digest username="uname", realm="API realm", nonce="UZ43b0FWC9591pMjy1i6H2okVwgMbDVO6fcgcQ", uri="/path/to/uri", qop="auth", response="09c536e22bca031cdbcb289e4065064a", nc="1", cnonce=""' } }
You can use http-auth module that supports digest authentication
// HTTP module
var http = require('http');
// Authentication module.
var auth = require('http-auth');
var digest = auth.digest({
realm: "Simon Area.",
file: __dirname + "/../data/users.htdigest" // vivi:anna, sona:testpass
});
// Creating new HTTP server.
http.createServer(digest, function(req, res) {
res.end("Welcome to private area - " + req.user + "!");
}).listen(1337);
I'm using node.js to post a http request. the code works with if i define my post data ahead of the 'options' field, but if I initially set my post_data string to empty and update it later it doesn't pick up the new length. How would I get it to do that ? I'm looking to send multiple posts of varying lengths to the same place in a loop so need to be able to do this.
var post_data=''; //if i set my string content here rather than later on it works
var options = {
host: '127.0.0.1',
port: 8529,
path: '/_api/cursor',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
post_data = 'a variable length string goes here';//the change in length to post_data is not //recognised
req.write(post_data);
req.end();
'Content-Length': post_data.length
You ran this before setting post_data.
If you want to set post_data after creating the object, you'll need to set it manually later:
options.headers['Content-Length'] = post_data.length;
Note that you must set that before calling http.request().
Posting data is a matter of sending a query string (just like the way you would send it with an URL after the ?) as the request body.
This also requires to declare Content-Type and Content-Length values so the server knows how to interpret the data.
var querystring = require('querystring');
var data = querystring.stringify({
username: yourUsernameValue,
password: yourPasswordValue
});
var options = {
host: 'my.url',
port: 80,
path: '/login',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
});
});
req.write(data);
req.end();
You need to replace:
'Content-Length': post_data.length
for:
'Content-Length': Buffer.byteLength(post_data, 'utf-8')
See https://github.com/strongloop/express/issues/1870
var locationJSON, locationRequest;
locationJSON = {
latitude: 'mylat',
longitude: 'mylng'
};
locationRequest = {
host: 'localhost',
port: 1234,
path: '/',
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded',
'content-length': locationJSON.length
}
};
var req;
req = http.request(options, function(res) {
var body;
body = '';
res.on('data', function(chunk) {
body += chunk;
});
return res.on('end', function() {
console.log(body);
callback(null, body);
});
});
req.on('error', function(err) {
callback(err);
});
req.write(data);
req.end();
On the other end, I have a node.js server listening to port 1234 and it never gets the request. Any ideas?
You are doing req.write(data) but as far as I can see 'data' is not defined anywhere. You are also setting the 'content-length' header to locationJSON.length, which is undefined because locationJSON only has 'latitude' and 'longitude' properties.
Properly define 'data', and change the 'content-type' and 'content-length' to use that instead.
var locationJSON, locationRequest;
locationJSON = {
latitude: 'mylat',
longitude: 'mylng'
};
// convert the arguments to a string
var data = JSON.stringify(locationJSON);
locationRequest = {
host: 'localhost',
port: 1234,
path: '/',
method: 'POST',
header: {
'content-type': 'application/json', // Set the content-type to JSON
'content-length': data.length // Use proper string as length
}
};
/*
....
*/
req.write(data, 'utf8'); // Specify proper encoding for string
req.end();
Let me know if this still doesn't work.