How does one access data posted within restify 1.x.x? - rest

I'm posting data to a restify API, but cannot find any currently examples for how to access the posted data. How does this work?

I found the answer. One of the included plugins needs to be activated, restify.bodyParser. The data may then be found in either req.params (default) or req.body (mapParams: false), depending on the settings (look specifically at BodyParser section).
Example:
server.use(restify.bodyParser({ mapParams: false })); // mapped in req.body
Or:
server.use(restify.bodyParser()); // mapped in req.params

For restify 5.0.0+, use:
server.use(restify.plugins.bodyParser());
https://github.com/restify/node-restify/issues/1394#issuecomment-312728341
For older versions use:
server.use(restify.bodyParser());
After telling restify to use the bodyParser middleware the request body will be available on the request objects body property:
server.post('/article', (req, res, next) => {
console.log(req.body)
next()
})

Is very simple:
server.use(restify.bodyParser({ mapParams: false }));
You need to activate the bodyParser in restify

This code will print the request body to the console:
var restify = require('restify');
var server = restify.createServer();
// This line MUST appear before any route declaration such as the one below
server.use(restify.bodyParser());
server.post('/customer/:id', function (req, resp, next) {
console.log("The request body is " + req.body);
response.send("post received for customer " + req.params.id + ". Thanks!");
return next();
});

Related

Axios Delete Not Working In React App But Working In PostMan/Insomnia

Axios DELETE works when I send a request through postman but on my react app it doesn't. I'm passing the _id that MongoDB assigns the entry. I'm initiating ObjectId and it still doesn't work. I also double checked if I was using the correct route, which I was.
In my app I have click function that calls SaveBook. That part I feel okay about. Let me know if I need to share something else.
SaveBook in AuthActions.js on the front end
export const saveBook = ({books, user, book, _id}) => {
return function () {
console.log(`This is id ${JSON.stringify(_id)}`)
const savedIndex = books.indexOf(book);
if (savedIndex >= 0) {
console.log(savedIndex)
axios
.delete("/api/users/wishlist", {_id})
} else {
console.log(savedIndex)
// console.log(`Adding ${book.book.title} to faves...`);
axios
.post("/api/users/dashboard", {book, user})
.then(console.log("success"))
.catch (err =>
json(err)
);
}
}
};
In users.js the delete operation on the server side
router.delete('/wishlist', (req, res) => {
const db = mongoUtil.getDb();
db.db("mern-auth-2").collection("savedbooks")
.deleteOne({_id:ObjectId(req.body._id)})
.then(res.json(res.data))
});
I realized req.body wasn't the correct choice for the Delete method and used url params/ req.params to send the _id. This works well.
Fixed this line in authActions.js
axios
.delete("/api/users/wishlist/" + _id,)
Fixed these few lines in Users.js
router.delete('/wishlist/:id', (req, res) => {
const db = mongoUtil.getDb();
db.db("mern-auth-2").collection("savedbooks")
// .deleteOne({_id:ObjectId(req.body._id)})
.deleteOne({_id:ObjectId(req.params.id)})

Mistake in using DOMPurify on the backend to sanitize form data?

I was wondering if it was possible to use DOMPurify to sanitize user input on a form before it is saved to database. Here's what I've got in my routes.js folder for my form post:
.post('/questionForm', (req, res, next) =>{
console.log(req.body);
/*console.log(req.headers);*/
const questions = new QuestionForm({
_id: mongoose.Types.ObjectId(),
price: req.body.price,
seats: req.body.seats,
body_style: req.body.body_style,
personality: req.body.personality,
activity: req.body.activity,
driving: req.body.driving,
priority: req.body.priority
});
var qClean = DOMPurify.sanitize(questions);
//res.redirect(200, path)({
// res: "Message recieved. Check for a response later."
//});
qClean.save()
.then(result => {
//res.redirect(200, '/path')({
// //res: "Message recieved. Check for a response later."
//});
res.status(200).json({
docs:[questions]
});
})
.catch(err => {
console.log(err);
});
});
I also imported the package at the top of the page with
import DOMPurify from 'dompurify';
When I run the server and submit a post request, it throws a 500 error and claims that dompurify.sanitize is not a function. Am I using it in the wrong place, and/or is it even correct to use it in the back end at all?
This might be a bit late, but for others like me happening to run into this use case I found an npm package that seems well suited so far. It's called isomorphic-dompurify.
isomorphic-dompurify
DOMPurify needs a DOM to interact with; usually supplied by the browser. Isomorphic-dompurify feeds DOMPurify another package, "jsdom", as a dependency that acts like a supplementary virtual DOM so DOMPurify knows how to sanitize your input server-side.
In the packages' own words "DOMPurify needs a DOM tree to base on, which is not available in Node by default. To work on the server side, we need a fake DOM to be created and supplied to DOMPurify. It means that DOMPurify initialization logic on server is not the same as on client".
Building on #Seth Lyness's excellent answer --
If you'd rather not add another dependency, you can just use this code before you require DOMPurify. Basically what isometric-dompurify is doing is just creating a jsdom object and putting it in global.window.
const jsdom = require('jsdom');
const {JSDOM} = jsdom;
const {window} = new JSDOM('<!DOCTYPE html>');
global.window = window;

Unable to access Profile scope on Uber API with node-uber wrapper

I'm trying to build a project using the Uber API and node, and was using the node-uber wrapper here: https://github.com/shernshiou/node-uber
I've been able to access the History scope with no issue, but I'm not able to get the Profile scope. Any insight into what might be wrong? Snippets below.
Thanks!
app.get('/sign-in', function (req, res) {
var url = uber.getAuthorizeUrl(['history', 'profile']);
res.redirect(url);
console.log(url);
});
app.get('/oauth/callback', function (req, res) {
var code = req.query.code
uber.authorization({ authorization_code: code },
function (err, access_token) {
req.session.uberToken = access_token
res.redirect('/my-trips');
});
});
app.get('/api/profile', function (req, res) {
uber.user.profile({access_token: req.session.uberToken}, function (err, apiResponse) {
res.send(apiResponse);
});
});
Could you please show your error message? Based on your snippet, it's hard to understand what might go wrong without making assumptions. One thing that you might check is the authorization within the callback method. More specific, this assignment:
req.session.uberToken = access_token
You're assigning the uberToken to the request, which doesn't have any effect. Modifications to the response, however, would be useful. The request property won't exist in the method scope for the GET /api/profile. Hence, accessing the profile should return a HTTP 401 (Unauthorized).

Handling CSRF/XSRF tokens with Angular frontend and Drupal 7 backend

I'm in the process of building a new AngularJS frontend for a Drupal 7 website. This is using the Services module with session-based authentication, across two domains using CORS. I am able to authenticate with Drupal, retrieve the user object and session data, and then get the CSRF token from the services module. What I'm having trouble with is setting all this up in the header so that subsequent requests are authenticated. I understand the overall concept but am new to both AngularJS and preventing CSRF attacks.
From what I have gathered reading about this set-up with AngularJS and RubyOnRails, there can be inconsistencies between platforms concerning what the token is named and how it is processed. There also seems to be a number of suggestions on how to set this token in the header. However, I'm having trouble in finding a solid example of how to get these platforms speaking the same language.
The only thing I'm doing with my $httpProvider in app.js is:
delete $httpProvider.defaults.headers.common['X-Requested-With'];
The login controller, in controller.js:
.controller('LoginCtrl', ['$scope', '$http', '$cookies', 'SessionService', function($scope, $http, $cookies, SessionService) {
$scope.login = function(user) {
//set login url and variables
var url = 'http://mywebsite.com/service/default/user/login.json';
var postDataString = 'name=' + encodeURIComponent(user.username) + '&pass=' + encodeURIComponent(user.password);
$http({
method: 'POST',
url: url,
data : postDataString,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (data, status, headers, config) {
var sessId = data.sessid;
var sessName = data.session_name;
$cookies[sessName] = sessId;
var xsrfUrl = 'http://mywebsite.com/services/session/token';
$http({
method: 'GET',
url: xsrfUrl
}).success(function (data, status, headers, config) {
$cookies["XSRF-TOKEN"] = data;
SessionService.setUserAuthenticated(true);
}).error(function (data, status, headers, config) {
console.log('error loading xsrf/csrf');
});
}).error(function (data, status, headers, config) {
if(data) {
console.log(data);
var msgText = data.join("\n");
alert(msgText);
} else {
alert('Unable to login');
}
});
};
The solution has to do with how the cookies need to be set and then passed through subsequent requests. Attempts to set them manually did not go well but the solution was simpler than I expected. Each $http call needs to set the options:
withCredentials: true
Another change I made was to use the term CSRF instead of XSRF, to be consistent with Drupal. I didn't use any built-in AngularJS CSRF functionality.
addItem: function(data)
{
return $http.post('api/programs/'+$stateParams.id+'/workouts', {item:data},{
headers:
{
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-CSRF-Token': $('meta[name="xxtkn"]').attr('content')
}
});
}
since it has been a year of this topic! not sure still encountering the same problem but for the ones who comes to search for answers here is how i handle it!
Pay attention the headers{} part i define a new header and call it X-CSRF-Token and grab value from the DOM of (serverside) generated html or php. It is not a good practise to also request the csrf token from the server.Cuz attacker could somehow request that as well. Since you save it as a cookie. Attacker can steal the cookie! No need to save it in a cookie! send the token with header and read it in the serverside to match it!
and for multitab of a same page issue. I use the same token thruout the whole session.
Only regenerate on login, logout and change of major site or user settings.
There is a great library callse ng-drupal-7-services. If you use this in you project it solves authentication / reauthentication and file / node creation aut of the box and you can fokuse on the importent stuff in your project.
So Authentication is there solved like this:
function login(loginData) {
//UserResource ahndles all requeste of the services 3.x user resource.
return UserResource
.login(loginData)
.success(function (responseData, status, headers, config) {
setAuthenticationHeaders(responseData.token);
setLastConnectTime(Date.now());
setConnectionState((responseData.user.uid === 0)?false:true)
setCookies(responseData.sessid, responseData.session_name);
setCurrentUser(responseData.user);
AuthenticationChannel.pubLoginConfirmed(responseData);
})
.error(function (responseError, status, headers, config) {
AuthenticationChannel.pubLoginFailed(responseError);
});
};
(function() {
'use strict';
AuthenticationHttpInterceptor.$inject = [ '$injector'];
function AuthenticationHttpInterceptor($injector) {
var intercepter = {
request : doRequestCongiguration,
};
return intercepter;
function doRequestCongiguration (config) {
var tokenHeaders = null;
// Need to manually retrieve dependencies with $injector.invoke
// because Authentication depends on $http, which doesn't exist during the
// configuration phase (when we are setting up interceptors).
// Using $injector.invoke ensures that we are provided with the
// dependencies after they have been created.
$injector.invoke(['AuthenticationService', function (AuthenticationService) {
tokenHeaders = AuthenticationService.getAuthenticationHeaders();
}]);
//add headers_______________________
//add Authorisation and X-CSRF-TOKEN if given
if (tokenHeaders) {
angular.extend(config.headers, tokenHeaders);
}
//add flags_________________________________________________
//add withCredentials to every request
//needed because we send cookies in our request headers
config.withCredentials = true;
return config;
};
There is also some kind of kitchen sink for this project here: Drupal-API-Explorer
Yes, each platform has their own convention in naming their tokens.
Here is a small lib put together hoping to make it easy to use with different platforms. This will allow you to use set names and could be used across all requests. It also works for cross-domain requests.
https://github.com/pasupulaphani/angular-csrf-cross-domain

confused with facebook json object with jquery and nodejs

writing my first facebook/node/express app
With express I'm using
app.post('/friends', function(req, res) {
graph.get("/me/friends?fields=id,name", function(err, res2) {
res.send(res2);
});
});
client side I'm using
$('#getFriends').click(function() {
$.post('/friends', function(data) {
console.log(data);
console.log(data.length);
});
});
With a previous app, I called the graph from the client side with getJSON and looped through everything with a for loop to print out the id and name. With this, I'm confused. Do I need to convert it to an array or a string first? Am I using the express request properly?
It logs the data object, but even when I go to print the length it's null.