I followed a tutorial for a RESTful web app with express:
http://cwbuecheler.com/web/tutorials/2014/restful-web-app-node-express-mongodb/
It showed me how to issue get requests like this:
router.get('/userlist', function(req, res) {
var db = req.db;
db.collection('userlist').find().toArray(function (err, items) {
res.json(items);
});
});
And that makes sense to me. It renders in the jade template, too which is fantastic. Now I'm writing my own app, and it's restful as well. I've come up with the following for my get request
/budget
router.get('/', stormpath.loginRequired, function(req, res, next) {
var db = req.db;
var user_id = req.user.customData["mongo_id"];
var collection = db.get('usercollection');
collection.find({'_id' : user_id}, function (err, user_data) {
res.render('budget', user_data);
});
});
And this renders the template, but I don't think that this will allow me to retrieve JSON from this path later. Is this correct? I have tried putting res.json(user_data); inside the collection.find callback, but it literally only renders json on the page, and I cannot figure out why.
I need the JSON data to be 'GETable' because my other REST methods will be asynchronous, and I will need to use $.getJSON( '/budget', function( data )
Related
How does the framework know which api is been called?
app.get('/user/:userId/name/export', function (req, res) {
var userId = req.params.userId;
}
app.get('/user/:userId/name/:name', function (req, res) {
var userId = req.params.userId;
var name = req.params.name
}
I'm working on an api gateway, need some customization of access control. It need to block the api call and check the roles of user through the params in path, like userId and name in db. If matched the config in file, will pass the acl and call the api, otherwise, will return 401. So if the url pattern is similar, I found it's hard to distinguish two api which is exactly been call. Any suggestions? Really appreciate for you help!
Express router calls each callback, which match the URL path.
Route /user/123/name/admin matches only the second path, but route /user/123/name/export matches both of them.
If you end the request on the first callback, then the second will never be called:
app.get('/user/:userId/name/export', function (req, res) {
var userId = req.params.userId;
res.end();
}
app.get('/user/:userId/name/:name', function (req, res) {
var userId = req.params.userId;
var name = req.params.name
}
Callbacks will be called according to adding sequence. So the global paths, like app.get('*', ...) must be added at the very end.
I want to get data out of a router.get() function to another function located in the same JS file.
I have a data sent to a get method:
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
Now I want to use title variable in another method:
router.post('/', function(req, res) {
// I want to use the title variable in here
});
Any help would be appreciated.
You just need to change the scope of the variable. Be careful though when expanding the scope of variables. I.e., you would set the title outside of your router callbacks, and then reference it inside. Also, as your web app grows, it's possible you'll have many different pages, each with their own page titles.
The easy way to make this work is to initialize the title outside the route handler:
// Here, I'm using Object.freeze, assuming you want the map to be
// immutable (i.e., not accidentally changed by other parts of the code)
// (const titles = { ... } won't achieve it)
let titles = Object.freeze({ /* Formatted as a "route" --> "title" map */
index: 'Express'
});
router.get('/', function(req, res, next) {
const routeName = 'index'
res.render(routeName, { title: titles[routeName] });
});
router.post('/', function(req, res) {
const routeName = 'index'
// Access your title here:
console.log(titles[routeName]);
});
As an alternative, expressJS allows us to use app.get() and app.set() methods. Usually most expressJS apps start out like this:
let app = express();
You can stash variables associated with the app like this:
app.set('indexTitle', 'Express');
So that way in your route handler, you can access like this:
router.get('/', function(req, res, next) {
res.render(routeName, { title: app.get('indexTitle') });
});
router.post('/', function(req, res) {
// Access your title here:
console.log(app.get('indexTitle'));
});
Yet, an even easier approach may be to let the front-end keep track of all the page titles, and, if the title is absolutely something the back-end needs, the front-end can simply post that in the req.body. Yes, might be overkill, but it would eliminate the need for the server to keep track of it:
router.post('/', function(req, res) {
// Access your title here:
console.log(req.body.pageTitle);
});
so i have a chat app that i am working on here and i am trying to make it to where a user can type in like https://niknet.ddns.net/room/randomroomUID and it will join them to that room if they are logged in (i use password for handling login and signup) my code looks like this on my routes.js (in case you dont know it's the js that handles all my express stuff)
i tried this
app.get('/room/:roomUid', isLoggedIn, function(req, res) {
console.log(req.params.roomUid)
console.log(req.user)
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
var username = req.user.displayName;
app.post( 'apolloMainchat',{ roomUid:req.params.roomUid , username});
});
but im not sure how to pass the information across to the express code that handles when users /apolloMainchat
typically a user can get to /apolloMainchat like this
app.get('/apolloMainchat', isLoggedIn, function(req, res) {
console.log(req.user)
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
var username = req.user.displayName;
res.render('apolloMainchat.ejs', username);
console.log(req.user.displayName)
});
any one know how to help me?
You will want to pass this by redirecting the client to a new endpoint and then reading those parameters from the query as Renato Gama said in the comments.
Your code will then become something like this.
app.get('/room/:roomUid', isLoggedIn, function(req, res) {
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
app.redirect('apolloMainchat?roomUid=' + req.params.roomUid);
});
app.get('/apolloMainchat', function(req, res, next) {
console.log(req.params.roomUid);
});
You're just using a HTTP redirect to pass them to the new endpoint and attaching the data as a query parameter as you would if they requested it directly. It's not quite clear what you're trying to achieve, but this should do what you've described.
Hello I am trying to mock the API using swagger and express, in which I require data stored from the in memory database.
Following is my code, by which I am not able to get the data and it gives me syntax error.
I am using petstore application for mock.
Following is the script I modified as per my need.
What is wrong with the script.?
app.get('/pets', function(req, res, next) {
var myDB = new MemoryDataStore();
myDB.get('/pets',function(err, res){
});
});
I am really confused on how to build a typical REST type web app with Node.js (even though I am using Sockets).
In a typical WAMP stack you have a public javascript file and server-side PHP files. The user might be able to execute a JS function like
function updateDetails(){
$.post('details.php', formData, function(data){
console.log(data);
},'json');
}
And the server-side PHP file is something like
var stmt = "UPDATE table SET user = :user";
var params = (':user', $user);
stmt->execute();
Now I do know about node-mysql, but I don't see how it is implemented in the same way. How can I maintain a list of statements on the server side and allow the user to simply execute these statements on the client side.
I have node_modules/mysql installed.
In my server (app.js)
var mysql = require('mysql');
But unless I add all my statements there, I don't seem to be able to access them from a public JS file.
There are libraries out there that wrap database tables as resources and expose them as REST services (GET, POST, PUT, DELETE).
For example, sails.js uses Waterline for this purpose. You should look into other similar frameworks if you do not want to write the routes from scratch.
If you're just using express (4.x), then you can declare routes like the following:
// In users.js
var express = require('express');
var users = new express.Router();
users.get('/', function (req, res, next) {
// access mysql, grab all users, then...
res.json(results);
})
users.get('/:id', function (req, res, next) {
var userid = req.params.id;
// access mysql, grab user by id, then...
res.json(result);
})
users.put('/', function (req, res, next) {
var newUser = req.body;
// you can also use POST instead of PUT, and alter where the information for the new user should come from.
// insert a new row with the data found in newUser then...
res.json(createdUser);
});
users.delete('/:id', function (req, res, next) {
var userid = req.params.id;
// delete the user by id then...
res.json(deletedUser);
});
If you're really adventurous, or is a stickler for having http methods do exactly what they're supposed to, you can include a PATCH route for updating a user.
You have the option of either including mysql directly in the route, or declaring another module, then referencing that in the route. I'll finish one of the methods completely.
// more complete version of /users/:id
var mysql = require('mysql');
var connectionString = 'fill me in';
var pool = mysql.createPool(connectionString);
users.get('/:id', function (req, res, next) {
var userid = req.params.id;
var statement = "SELECT * FROM 'users' WHERE id = ?";
pool.query(statement, [userid], function (err, rows) {
if (err) { res.status(500).json(err); } // if you want to expose why you can't get the user by id.
else if (rows.length == 0) { res.status(404); } // could not find user with the given id.
else { res.json(rows[0]); } // return the found user.
});
})