How to make a rest call to SharePoint 2013 from node.js? - node.js

In my node.js app, I want to make a rest call to sharepoint 2013. This is the node.js code
function downloadData(res, key, success, fail) {
var opts = url.parse(key);
opts.method = 'GET';
opts.headers = {"Accept":"application/json;odata=verbose","X-RequestDigest":"0x146E2BDC9A21FDA62E793A0FC9793A530A5C6688BE194FB051703C8529B01A16607931C77D26EE61FA360AD04526F476A052FAC9B3C9277A5463AC20A27C3543,07 Mar 2016 15:37:18 -0000"};
opts.headers['Content-Type'] = 'application/json;odata=nometadata';
var req = http.request(opts, function(response) {
var str = '';
//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
success(res, str, key);
});
})
//req.write(data);
req.end();
}
I got the digest value from the client side, I did an alert statement, and copied it. I tried it on a sample url, which does work if I paste on the browser. When I run this, I get 401 unauthorized.
Does anyone know what's wrong?
Thanks

First of all, X-RequestDigest Header is used to validate client requests but not for authentication purposes.
Assuming your SharePoint sites utilizes NTLM authentication (default), you could utilize httpntlm package that implements HTTP NTLM authentication flow and allows to perform HTTP requests as demonstrated below:
var credentials = {
username: 'jdoe',
password: 'password',
domain: 'contoso'
};
var webUrl = "http://contoso.intranet.com";
var fileUrl = "/Shared Documents/guide.docx";
httpntlm.get({
url: webUrl + "/_api/web/getfilebyserverrelativeurl('" + fileUrl + "')/$value",
username: credentials.username,
password: credentials.password,
domain: credentials.domain
}, function (err, res) {
if (err) console.log(err);
console.log(res.body); //print data
});

Related

TypeError: Request path contains unescaped characters, any idea

//route to search (POST http://localhost:8080/api/search)
apiRoutes.post('/search', function(req, res) {
console.log('search');
var query = req.params;
console.log(query);
options = {
protocol : "https:/",
host: "https://api.themoviedb.org",
path: "/3/search/movie?api_key=35f7a26be584f96e6b93e68dc3b2eabd&language=en-US&page=1&include_adult=false&query="+query,
};
var req = https.request(options, function(res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
});
req.write("{}");
req.end();
})
DOES ANYONE KNOW WHERE THE PROBLEM IS?
I'm trying to do a request to do a research to the api the movie db and get the result back
There are some problems with the code. I have tested it and made it to work.
let options = {
host: "api.themoviedb.org",
path: "/3/search/movie?api_key=35f7a26be584f96e6b93e68dc3b2eabd&language=en-US&page=1&include_adult=false&query="+query.data.replace(' ','%20'),
};
first of all since you are using https module you don't need to specify the protocol nor you need to put it in the url. That's how your options variable should be.
Second you are appending the entire query object to the url which is {} instead you should append a string which will be in one of the key of your query object in my case its query.data
Third if there are spaces in the string Eg: Home Alone you to maintain space and avoid the error we replace the string with %20 which is a escaping character.
Forth Try giving a unique name for https request variable and its response variable in the callback function or it will override the route's req res variables cause your code to not work. Notice how I have used route's res function to send the data back and end the response
Also I am getting the data in req.body and you are using req.params however there are no params defined in your routes. Try going through the documentation for more information
Here is the complete code
apiRoutes.post('/search',function (req, res) {
https = require('https');
var query = req.body;
console.log(query.data);
let options = {
host: "api.themoviedb.org",
path: "/3/search/movie?api_key=35f7a26be584f96e6b93e68dc3b2eabd&language=en-US&page=1&include_adult=false&query="+query.data.replace(' ','%20'),
};
var request = https.request(options, function(response) {
var chunks = [];
response.on("data", function (chunk) {
chunks.push(chunk);
});
response.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
res.send(body);
res.end()
});
});
request.end();
});
Hope it helps.

Revoke salesforce token nodejs

I am trying to revoke a salesforce token from nodejs using an https request (both GET and POST methods tried).
This is my code for GET method
var token = user.token;
var uri = token.instanceUrl+'/services/oauth2/revoke?token='+token.accessToken;
console.log("data: "+postData+", options: "+JSON.stringify(postOptions)+ ", \r\n" + uri);
https.get(uri, function(response){
var buffer = '';
console.log(response.statusCode);
response.on('data', function (chunk) {
buffer += chunk;
});
response.on('end', function(){
console.log(buffer);
});
});
But i keep on getting this
error=unsupported_token_type&error_description=this%20token%20type%20is%20not%20supported, code: 400
I have also tried the address in browser and get a 400 Bad Request status.
All required options have been set according to salesforce online documentation https://help.salesforce.com/apex/HTViewHelpDoc?id=remoteaccess_revoke_token.htm&language=en
What am I missing which makes it a bad request?
I'm showing you how to do it using the request module:
var request = require('request')
request.post('https://login.salesforce.com/services/oauth2/revoke', {
form: {
token: '[ACCESS_TOKEN]'
},
followAllRedirects: true
}, function (err, res, body) {})
No idea what URL you are trying with, but the login URLs are identical for all users, you don't have to use your instance subdomain.
Also note this from their docs:
For a sandbox, use test.salesforce.com instead of login.salesforce.com.

Node.js post video from s3 to Facebook via Graph API

I have a video file on s3 that I want to post to a user Facebook account:
https.get(signedUrlOfObjectInS3, function(httpRes){
var form = new formData(); // that's form-data module https://github.com/felixge/node-form-data
form.append('source', httpRes);
var options = {
method: 'post',
host: 'graph-video.facebook.com',
path: '/me/videos?access_token=' + user_access_token,
headers: form.getHeaders(),
}
var buffer = '';
var apiCall = https.request(options, function (res){
res.on('data',function(chunk){
buffer += chunk;
});
res.on('end',function(){
var data = JSON.parse(buffer);
console.log('data from fb is: ' + util.inspect(data));
});
});
form.pipe(apiCall);
});
The response I get from Facebook is:
(#352) Sorry, the video file you selected is in a format that we don\'t support.
The video file on s3 is a mov file with a content type of video/quicktime.
OK, so apparently Facebook ignores the content type in the headers and guesses it from the file name. Since the s3 signed url doesn't end with filename.mov for example, it doesn't get it...
All I had to do was concating a '&f=filename.mov' to the end of the signedUrl, and now Facebook get that...
The following code actually worked fine for me for me:
https.get(signedUrlOfObjectInS3, function(httpRes) {
var form = new FormData(); // that's form-data module https://github.com/felixge/node-form-data
form.append('source', httpRes);
var options = {
method: 'post',
host: 'graph-video.facebook.com',
path: '/me/videos?access_token=' + user_access_token,
headers: form.getHeaders(),
}
var apiCall = https.request(options);
form.pipe(apiCall);
apiCall.on('response', function(res) {
console.log(res.statusCode);
});
});
try making the small difference in apiCall postback ,
other explanation might be that i've used a public amazon URL...

Using Q promises in HTTP requests with NodeJs

I'm trying to make a chain of promises functions which use HTTP requests in NodeJS with Kraken framework.
My code could work in 90% of cases, but if the distant requested server takes time to respond, the code will return an error with undefined values. So I think Q is a good solution to prevent that.
Here's the situation :
We access to a URL with a "code" parameter -> the route controller takes this param to use it in a HTTP POST request -> the response (a token) is stored in a variable and used in an other HTTP GET request -> the response (multiple JSON objects) is stored in variable too -> all variables are stored in a MongoDB.
If functions are not used in this order, of course it fails.
var Q = require('q');
module.exports = function (router) {
router.get('/', function (req, res) {
var codein = req.param('code');
if(codein){
console.log('Provided code: ' + codein+'\n');
getAccessToken(codein).then(function(token){
console.log('Provided AccessToken: ' + token + '\n');
getUsername(token).then(function(userdata){
console.log('Provided Username: ' + JSON.parse(userdata).username + '\n');
storeData(userdata).then(function(msg){
console.log(msg);
res.redirect('/dashboard/' + JSON.parse(userdata).username);
});
});
});
}
else{
console.log('Access Denied, redirecting...');
res.redirect('/');
}
});
};
This method works, but actually didn't resolve the problem, because sometimes variable are undefined again. I think it's my request functions which aren't well made...
Here's an example of the first function with POST request :
var getAccessToken = function(cod){
var def = Q.defer();
var data = querystring.stringify({
client_id:"1234567890",
client_secret:"******",
grant_type:"authorization_code",
redirect_uri:"http://localhost:8000/r/callback",
code:cod
});
var options = {
host: 'domain.server.com',
port: 443,
path: '/api/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(data)
}
};
var response = "";
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
response += chunk;
});
res.on('end', function(){
var json = JSON.parse(response);
var acto = json.access_token;
def.resolve(acto);
});
});
req.write(data);
req.end();
return def.promise;
};
In this case the acto variable can be undefined... So am I using Q in a wrong way ?
EDIT
To understand my problem, let me show you what can I have in my output console (really rare but happens) :
Provided code: 12345678910
Provided Username: user543210
Instead of :
Provided code: 12345678910
Provided AccessToken: 9876543210
Provided Username: user
I think you need to account for 2 scenarios
Where the Twitch API takes time to respond.
The Twitch response cannot be parsed
The code
res.on('end', function(){
var json = JSON.parse(response);
var acto = json.access_token;
def.resolve(acto);
});
Should be modified as:
try {
var json = JSON.parse(response);
var acto = json.access_token;
//check if acto is undefined
if (acto === undefined) {
def.reject('Some error message');
} else {
def.resolve(acto);
}
} catch (error) {
//since the JSON could not be parse
def.reject(error);
}

Node.js and twilio integration

I am trying to integrate twilio with Node.js+express.
I don't have a site yet. what value should I give for HOSTNAME, along with SID and AUTH_TOKEN, these values I got from twilio site.
I have written some code, whatever suggestion given below I have placed in to views folder in twiclient.js , I have added a route in app.js to redirect the request if /twi is called , but I am not getting any result. some errors are appearing in the console, would you please help me figure out what I'm doing wrong? I have placed the correct SID, token and hostname, as specified below.
app.js has the following entry, does anything else need to be done for the twilio calling part to work?
Also, where should I define the GUI for calling a phone in the views folder?
var TwilioClient = require('twilio').Client,
      Twiml = require('twilio').Twiml,
      sys = require('sys');
var client = new TwilioClient('MY_ACCOUNT_SID', 'MY_AUTH_TOKEN', 'MY_HOSTNAME');
var phone = client.getPhoneNumber('+2323232323');
phone.setup(function() { phone.makeCall('+15555555555', null, function(call) {});
phone.setup(function() {
    phone.makeCall('+15555555555', null, function(call) {
        call.on('answered', function(callParams, response) {
            response.append(new Twiml.Say('Hey buddy. Let\'s meet for drinks later tonight.'));
            response.send();
        });
    });
});
The hostname is 'api.twilio.com'. Your SID and AUTH_TOKEN come from your twilio account. When you log in, go to the dashboard. You'll find your SID and AUTH_TOKEN listed there.
Here's the code I use to make a request to twilio to place a call. It should help you get started.
var https = require('https');
var qs = require('querystring');
var api = 'your api key';
var auth = 'your auth token';
var postdata = qs.stringify({
'From' : '+5554321212',
'To' : '+5552226262',
'Url' : 'http://yourwebsite.com/call'
});
var options = {
host: 'api.twilio.com',
path: '/2010-04-01/Accounts/<your api key>/Calls.xml',
port: 443,
method: 'POST',
headers: {
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Length' : postdata.length
},
auth: api + ':' + auth
};
var request = https.request(options, function(res){
res.setEncoding('utf8');
res.on('data', function(chunk){
console.log('Response: ' + chunk);
})
})
request.write(postdata);
request.end();

Resources