For some strange reason, some changes on my route settings (MEAN environment, Node v0.12.2 and express 4) don't show effect any more!? Particularly instructions where I respond to client requests using ".sendfile()".
app.get('/', function(req, res){
res.sendfile("/public/index.html"); // <-- trying to exclude or change this
console.log("debug message"); //added later, never shown!!
});
Excluding or altering the sendfile instruction in the example above doesn't change anything - index.html is alyways being delivered upon request. Not even simple debug messages like console.log are shown any more?! Here's what I checked:
restarted Node.js server and computer several times
checked for duplicates of routes.js file
checked for duplicates of home route ("/")
cleaned browser cache
even deleted the ENTIRE route, site still delivered upon request!?!?
Maybe there is some kind of server-side cache that needs to be wiped?! I got no idea any more of what's wrong. Suggestions anyone?
There are changes in express 4 with respect to express 3. In express 4 we have got a new method app.route() to create chainable route handlers for a route path and a new class express.Router to create modular mountable route handlers. For more details ref: Moving to Express 4 What you can do is try using code in following order:
app.route('/')
.get(function(req, res) {
res.render('index');
});
And its also good serve static files by adding:
app.use(express.static(path.join(__dirname, '../public')));
Good luck...:)
Related
I just startet developing with server side JavaScript and this is my first project with it.
It is a command and control server for my owncloud server running with angular, Expressjs and bootstrap. At the moment I got trouble adding the functionality for the stop server button.
It should some code to log into the the server via ssh and do all the necessary stuff to shut it down gracefully.
The problem is, that I really can't (and also don't want to) add this via a browser script since I want to use an ssh library. Running a server side script by pressing a button doesn't seem to be possible at all (please tell me how if it is anyway, that would be the solution to all of my problems :)).
So I thought I could redirect the user to the /on page as he clicks the button and perform the actions in the app.get callback function. And here is the problem: In my server.js (the main node server) I have "two" endpoints defined at the moment
app.get("*", (req, res) =>{
res.sendFile(path.join(__dirname, "src/index.html"));
});
and
app.get("/on", (req, res) =>{
console.log("redirecting...");
//DO SOMETHING
res.redirect("/");
});
In the second one I would like to perform the ssh actions.
But as I change the first code block to (notice the / instead of the *)
app.get("/", (req, res) =>{
res.sendFile(path.join(__dirname, "src/index.html"));
});
The whole app doesn't seem to have angular any more. All angular components do show up but they are just empty and not filled with the content I defined in the app.component.html. Why is this occurring and how can I fix this? Thank you for any help ;)
PS: you can find all the code at: GitHub
There are multiple things you would preferably do, but to keep the answer short, you need few changes so you can have this up and running, first, app.get("*", ...) redirects every get to that code block, so you need to do this:
//Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//Angular DIST output folder
app.use(express.static(path.join(__dirname, "dist")));
app.get("/", (req, res) =>{
res.sendFile(path.join(__dirname, "dist/index.html"));
});
app.get("/on", (req, res) =>{
console.log("redirecting...");
//DO SOMETHING
res.redirect("/");
});
Notice one change, you don't want to call the src/index, you want to build the angular to dist folder and use that index.html, second, the route "/" will redirect to home page, the "/on" will now enter the the desired endpoint. If this is pretty much everything you want to do with the endpoints, i guess this is fine, but if you want to build something more complex, i would abstract things out. hope this helps, cheers.
I am pretty new to the node.js and express.js landscape. However I have been trying to wrap my head around the code behind creating a site (20+ pages for example) in express.js without the code getting pretty large.
A route, when using a view engine, points the incoming request to index or whatever page they requested. After running the default express-generator with the view engine set to HBS you get something like
app.use('/', index);
This points to the index.js file under the routes folder that contains something like
router.get('/', function(req, res, next){
res.render('index', {title: 'Express'});
});
And that then renders the index.hbs file to show what I want on the page.
My problem is this. Would you have to have a route for each page you wanted like a profile page, login page, about page, etc? If so wouldn't this create a lot of lines of code in routes if you had 20+ routes? Example would be in the app.js
app.use('a', a);
app.use('b', b);
...
app.use('z', z);
then each would require a corresponding route js file.
I assume there is a cleaner way of doing routing or perhaps I am over thinking this?
Any light on this concern/question of mine would be amazing.
In my express servers I break routes into different sections called "components" Each components can correspond to a give page if you're doing server-side rendering or it can correspond to a set of API routes.
Each component can have controllers to handle each route, and each controller can borrow from a handful of reusable actions.
Here's an example of an express server component I made(this example is for a set of API routes but the same architecture can be used for sets of hbs server-side rendering routes):
https://github.com/AkyunaAkish/react-redux-node-express-todo-list-boilerplate/tree/master/server/components/todos
It depends on how similar your routes are:
If they basically all have the same functionality, I'd put them in the same file.
If there are slight variations, I'd create a separate class containing the core functions, and then call to what ever is needed separately.
If they are completley different, put them all in separate files
This will give you a solid outline of how to do each:
How to include route handlers in multiple files in Express?
Node.js: Configuration and routes in a different file
How to include route handlers in multiple files in Express?
Generally, you make route files around areas of concern, though a given router can define whatever endpoints make sense. So for example, let's say your site has several pages that are fairly static (e.g. your "about" and "index" examples, and then several that are all based on blog entries (creating, listing, viewing, etc) and then several around users (user profiles and so on). You would probably create one router for each set of things, e.g.:
// ./routes/index.js
router.get('/', (req, res) => { res.render('index', {title: 'Express'}); });
router.get('/about', (req, res) => {res.render('about', {title: 'Express'});});
// etc
conceptually, you could use that more simply to pull the "index" or "about" values from the URI, but I'm assuming you'll do other things like assigning variables and such.
Then in another file
// ./routes/blog.js
router.get('/blog', (req, res) => {
// do whatever to fetch info fromt eh DB and render it...
});
And so on.
My application currently serves fine making calls with Express, but I have a page now rendered by:
app.get('/user/:username', function(req, res){
serve html page (no problems)
}
and from that page, I'm making a request for
return $http.get('/api/user/:s').success(function (resp) {
stuff...
}
which is returning a 404 not found.
The call is in my Express app.js as
app.get('/api/user/:username', routes.api.getDBUser);
and I've been stumped on this problem for ages now. I feel like the issue is from something related to the URL.
EDIT:
app.use("/user", express.static(path.join(__dirname, 'static'))); //serving statics for localhost/user paths
app.get('/api/user', authentication.isAuthenticated, routes.api.getUser);
app.get('/api/users/:username', routes.api.getDBUser);
app.get('/api/user/friends', authentication.isAuthenticated, routes.api.getUserFriends);
app.get('/api/user/history', authentication.isAuthenticated, routes.api.getUserGameHistory);
is all the routes related to the user here. I'm not sure if this has something to do with it, but accessing a routing call when the url is something like localhost(port)/something, it's okay. The URL at this particular page I'm trying to make the call from is localhost(port)/user/something
I am developing a web application with the mean.js boilerplate code. Recently I added a view to my application (the 'analysis' page) by creating an analysis module and added some route logic with the following code.
//Setting up route
angular.module('analysis').config(['$stateProvider',
function($stateProvider) {
// Projects state routing
$stateProvider.
state('imageAnalysis', {
url: '/image_analysis',
templateUrl: 'modules/analysis/views/tools.client.view.html'
});
}
]);
This works just dandy, I can go to homepage.com/image_analysis and see my tools.client.view.html page. My goal now is to have this page only visible to user who are logged in. My first approach to this was to check if the user was logged in the angular routes logic, this has proven to be difficult for me. I also read that check authentication in the front end is very unsafe. So I've decided to check if the user is logged in with Express routing.
Here is an example of what Express routing looks like for one of my other AngularJS modules
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
var projects = require('../../app/controllers/projects.server.controller');
// Projects Routes
app.route('/projects')
.get(users.requiresLogin, projects.list)
.post(users.requiresLogin, projects.create);
app.route('/projects/:projectId')
.get(users.requiresLogin, projects.read)
.put(users.requiresLogin, projects.hasAuthorization, projects.update)
.delete(users.requiresLogin, projects.hasAuthorization, projects.delete);
// Finish by binding the Project middleware
app.param('projectId', projects.projectByID);
};
Notice the users.requiresLogin function which check if a user is logged in and redirects the user to the signin page if they are not. I want to take advantage of this function. Some things I dont quite understand in the boilerplate code are what is the purpose of app.route()? I think this might be a middleware but I am not sure what it does.
Here are some attempts I've take taken at messing around with express routing. These attempts are in my analysis.server.routes.js file that I created.
Attempt 1
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
// analysis routes
app.get('/image_analysis', function(req, res) {
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
console.log('helloworld');
});
};
I thought this would log 'helloworld' when I access the image_analysis page, but it didnt appear to do anything.
Attempt 2
module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
// analysis routes
app.route('/image_analysis')
.get(users.requiresLogin);
};
Based on the other code, I thought this might work to require login for the analysis page. But it did nothing.
Any help would be much appreciated! Thanks everyone, I am struggling to grasp express routing at the moment and stackoverflow has been a tremendous help.
I don't have a solution, or not at least at this moment that I could think of.
However I can explain to you how things work and why a solution might not be trivial.
what is the purpose of app.route()
This defines your routes.
app.route('/projects/:projectId')
.get(users.requiresLogin, projects.read)
.put(users.requiresLogin, projects.hasAuthorization, projects.update)
.delete(users.requiresLogin, projects.hasAuthorization, projects.delete);
What that code does is when a client requests a URL like one of the following
GET /projects/5562ff08de4f70180bba3083
PUT /projects/5562ff08de4f70180bba3083
DELETE /projects/5562ff08de4f70180bba3083
it first executes that middleware function users.requiresLogin,
which is defined to be common in all methods (.get .put .delete)
and then their respective middlewares in that order
projects.read | projects.hasAuthorization ...
On how Angluar routing works in contrast to Express routing:
Angluar routing is all done client-side. It's all achieved through Javascript
changing the addressbar url and displaying the view attached to that route.
Your Angular app is served by the server through a single (Express) route - / (homepage)
So again, your entire Angular app loads thorough just 1 route on the server-side,
and then Angular takes over the routing to client-side through it's own ui-router.
Now it must be starting to seem obvious that it's not trivial to have server-side authentication check
interfere between client-side routing.
You can only have server-side authentication work with routes that server actually is in control of serving.
Those are mostly just your API routes, in your case.
Attempt 1
app.get('/image_analysis', function(req, res) {
console.log('helloworld');
I thought this would log 'helloworld' when I access the image_analysis page, but it didnt appear to do anything.
It indeed should have! Unless.. there's a route that comes before it that already serves all requests
app.get('*', function(req, res) {
res.send(angularApp); // your angular app is served here
});
// No request would *need* to go beyond past this point
// because it already got served above
app.get('/image_analysis', function(req, res) {
// so this isn't reached.
console.log('helloworld');
});
So that's why it doesn't work.
I want to restrict a certain subtree only to authenticated users. The basic setup is as follows (fat removed):
app.use(express.bodyParser())
.use(express.cookieParser('MY SECRET'))
.use(express.cookieSession())
.use('/admin', isAuthenticatedHandler)
.use('/admin', adminPanelHandler);
Where the handler functions is:
isAuthenticatedHandler = function(req, res, next) {
if (!req.session.username) {
res.redirect('login');
} else {
next();
}
};
The problem is that even though I provide the redirect destination as a relative path 'login', it doesn't lead to <mount_point>/login i.e. /admin/login but to /login which of course throws a 404.
From the expressjs API reference:
This next redirect is relative to the mount point of the application.
For example if you have a blog application mounted at /blog, ideally
it has no knowledge of where it was mounted, so where a redirect of
/admin/post/new would simply give you `http://example.com/admin/post/new`,
the following mount-relative redirect would give you
`http://example.com/blog/admin/post/new`:
res.redirect('admin/post/new');
Am I misreading this?
The issue here is that while you are using your middleware off of /admin, your app itself is not mounted at /admin. Your app is still off of the root, and your configuration simply says to only use your isAuthenticatedHandler middleware if the request comes in off the /admin path.
I whipped together this gist. Notice how it uses 2 Express applications, one mounted inside the other (line 23 pulls this off). That is an example of mounting the application at a different point rather than just putting a given middleware at a given point. As presently written, that example will give you an endless redirect, since the isAuthenticatedHandler fires for everything off of / in the child application, which equates to /admin overall. Using 2 separate applications might introduce other issues you're not looking to deal with, and I only include the example to show what Express means when it talks about mounting entire applications.
For your present question, you'll either need to follow what Yashua is saying and redirect to /admin/login or mount your admin interface as a separate Express application.
What are you trying to achieve? Why not just redirect to '/admin/login' ? And the mount point they are talking about is the place where your Express app is located, not necessarily the current URL. So /blog might be setup on your server to be the root of your app while / might be a totally different app. At least that's the way I read this.