I need to handle some POST data in my meteor.js app, is there an easy way to do this?
Very basic, if it was a PHP app I would just want the $_POST variable.
Meteor router
https://github.com/tmeasday/meteor-router#server-side-routing
Meteor.Router.add('/items/:id', 'POST', function(id) {
// update Item Function
return [200, 'ok'];
});
If you are simply looking to intercept the GET and POST data, then send Meteor on it's merry way, you could do something like this on the server.
if (Meteor.isServer) {
var connect = Npm.require('connect');
var app = __meteor_bootstrap__.app;
var post, get;
app
// parse the POST data
.use(connect.bodyParser())
// parse the GET data
.use(connect.query())
// intercept data and send continue
.use(function(req, res, next) {
post = req.body;
get = req.query;
return next();
});
Meteor.startup(function() {
// do something with post and get variables
});
}
EDIT 11/01/13
I ended up creating a smart package for this (for myself). There is no documentation but you are welcome to use it. https://github.com/johnnyfreeman/request-data
To retrieve the foo request variable:
RequestData.get('foo') // --> 'bar'
RequestData.post('foo') // --> 'bar'
Both methods will throw a Meteor.Error if the key isn't found so make sure you use wrap with a try/catch if the variable is optional.
You can use Meteor's Iron Router, docs here, since Router (as mentioned above) is outdated and might be no longer functional.
Router.route('/items/:id', {where: 'server'})
.get(function () {
this.response.end('get request\n');
})
.post(function () {
this.response.end('post request\n');
});
I'm using this package to serialize body data: simple:json-routes. Here is the link.
And this code snippet to access it:
WebApp.connectHandlers.use('/api/request', (req, res, next) => {
console.log(req.body);
});
Related
In application which I currently develop, it's using Express. In my case I want to get response before it's been sent and modify it (for purpose of JWT). In this application, there is a dozen of endpoints and I don't want to create my own function like sendAndSign() and replace res.send() everywhere in code. I heard there is option to override/modify logic of res.send(...) method.
I found something like this example of modifying, but in my case this doesn't work. Is there any other option (maybe using some plugin) to manage this action?
You can intercept response body in Express by temporary override res.send:
function convertData(originalData) {
// ...
// return something new
}
function responseInterceptor(req, res, next) {
var originalSend = res.send;
res.send = function(){
arguments[0] = convertData(arguments[0]);
originalSend.apply(res, arguments);
};
next();
}
app.use(responseInterceptor);
I tested in Node.js v10.15.3 and it works well.
I have created an NPM package called experss-response-hooks that provides response hooks.
You can register a hook in a middleware before all your other routes, that will enable you to change the response body when send() will be called.
For example:
const responseHooks = require('express-response-hooks');
// response hooks initialization
app.use(responseHooks());
// register a middleware that modifies the response body before being sent to the client
app.use(function (req, res, next) {
// hook on "send()" function
res.hooks.on('send', (args) => {
args[0] = 'new-body'; // args[0] is the body passed to send()
});
});
I'm using a role authorisation (connect-roles), and trying to add more than one role for each route. This is using express, and monogoose. Here is the code I currently have:
router.get('/admin/:slug', function (req, res) {
if (user.can('vip')) {
adminController.showVipView // <-- this is what I need to work
} else {
// call a different view
}
});
This is how it normally works without the if statement. This seems like super basic express, but I just cannot get it to work.
router.get('/admin/:slug', user.can('vip'), adminController.showVipView);
Just pass request and response into it:
adminController.showVipView(req, res);
It might also requires the next callback, then you should pass that into it too...
By the way, your if statement wont work either as it returns a middleware. Might do this:
user.can('vip')(req, res, function(){
adminController.showVipView(req, res);
});
Let's jump to an example. I'll skip some parts like imports, exports.
I have a controller called controllers/book.js with one route:
router.get('/my-books', function(req, res) {
if(Auth.authenticated(req,res)) {
Book.getMyBooks(function(rows) {
response.operationSucceed(req, res, rows);
});
}
});
Then, in a model called models/book.js I have that function:
function getMyBooks(successCallback) {
db.query('SELECT * FROM book b WHERE b.id_user=?', [Auth.getLoggedUID()], function(rows) {
successCallback(rows);
});
}
My question is about Auth.getLoggedUID function.
Assuming that I have a JWT authentication and assuming that I have an UID in payload (is that even acceptable?), what's the best option to retrieve it? Is there any, EXCEPT passing the req every time to every function where I need auth data?
I may have a function execution inside a function, do I need to pass the req through both of them to get the user ID? Like this?:
function getBooks(req) {
getMyBooks(req);
getCriminalBooks(req);
getEvenOtherBooksByAuthor(req, authorId);
}
Honestly I wouldn't like that.
Maybe my whole concept is wrong and I should be doing things differently?
Can someone point me the right direction in scenarios like this?
You can pass UID in header and retrieve it inside your controller as:
var uid =req.header('UID');
Then pass this UID where ever you want there is no need to carryforward whole req object everywhere.
You can use a middleware function. Let's say that every request that hits your endpoints, will have a token which you should check and possibly decode it. After that, you can set the decoded content to the req object. So something like this:
app.use(function(req, res, next) {
// get the token from the request headers most likely.
// verify and decode the token
// set the decoded content to the request
var payload = ..
req.payload = payload;
});
After this you can access the payload in every single endpoint you have. So for example in some controller you can do:
app.get('/hey', function(req, res) {
var payload = req.payload;
});
I want to create dynamic stubs as webservices. My idea is to load at every request a definition file and return data for corresponding URL.
The definition file could look like this:
/api/users {users:["john", "jack", "jake"]}
/api/users/1 {user:"john"}
/api/some-data/1 {data:"some data"}
In an application I created on behalf of a tutorial I find:
router.post('/some-irl', function (req, res) {
//some code
return {some JSON}
});
But this definition looks static to me, which should be there before I start Node.js Is it possible to define /some-irl at the time then request occures?
EDIT
Actually, I was intending to do somehting like this: https://github.com/typicode/json-server but it is already there!
You can attach a use middleware, which can check the path and decide whether to handle it or pass it on:
router.use(function(req, res, next) {
// req.path
// decide what to do
// respond or next()
});
you can define variables in the routes, use : before the variable name to define it, and then you'll get the value in req.params:
route.get('/api/users/:user/', function (req, res) {
var username = req.params.user;
});
I'm trying to implement update functionality to an Express.js app, and I'd like to use a PUT request to send the new data, but I keep getting errors using PUT. From everything I've read, it's just a matter of using app.put, but that isn't working. I've got the following in my routes file:
send = function(req, res) {
req.send(res.locals.content);
};
app.put('/api/:company', function(res,req) {
res.send('this is an update');
}, send);
When I use postman to make a PUT request, I get a "cannot PUT /api/petshop" as an error. I don't understand why I can't PUT, or what's going wrong.
You may be lacking the actual update function. You have the put path returning the result back to the client but missing the part when you tell the database to update the data.
If you're using MongoDB and ExpressJS, you could write something like this :
app.put('/api/:company', function (req, res) {
var company = req.company;
company = _.extend(company, req.body);
company.save(function(err) {
if (err) {
return res.send('/company', {
errors: err.errors,
company: company
});
} else {
res.jsonp(company);
}
})
});
This mean stack project may help you as it covers this CRUD functionality which I just used here swapping their articles for your companies. same same.
Your callback function has the arguments in the wrong order.
Change the order of callback to function(req, res).
Don't use function(res, req).
Also if you want to redirect in put or delete (to get adress), you can't use normal res.redirect('/path'), you should use res.redirect(303, '/path') instead. (source)
If not, you'll get Cannot PUT error.
Have you been checking out your headers information?
Because header should be header['content-type'] = 'application/json'; then only you will get the update object in server side (node-express), otherwise if you have content type plain 'text/htm' like that you will get empty req.body in your node app.