In developing my website I ran across an issue with the way that my static CSS, JS, and image files are being loaded to my site. Once I navigate past the .index file or any route tree, my static directory misloads and the route index suddenly is added to the static file directory path.
I have written a yelpcamp app that I am modeling this app off of that works fine as I have it written, but this for some reason is throwing this specific error I can not find any resources to help correct.
Main app.js file that has all declarations and static file load
// REQUIREMENTS
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
methodOverride = require("method-override"),
nodemailer = require("nodemailer"),
expressSanitizer= require("express-sanitizer"),
// MODELS
blog = require("./models/blog"),
// ROUTES LOCATIONS
indexRoutes = require("./routes/index"),
blogRoutes = require("./routes/blog"),
contactRoutes = require("./routes/contact");
// SETUP
mongoose.connect("mongodb://localhost/*ChangedForPrivacy*");
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
app.use(methodOverride("_method"));
// ROUTE INDEX
app.use("/", indexRoutes);
app.use("/contact", contactRoutes);
app.use("/blog", blogRoutes);
This is the blog.js file in my routes folder where I noticed the static files loading correctly
// REQUIREMENTS
var express = require("express"),
Posts = require("../models/blog"),
router = express.Router();
// INDEX- SHOW ALL Posts
router.get("/", function(req,res){
// find all POSTS
Posts.find({}, function(err, allPosts){
if(err){
console.log(err);
} else{
// this is index because lots of paths are derived from it (landing pages are separate entities)
res.render("blog/home",{posts: allPosts});
}
});
});
// NEW (FORM PAGE)
router.get('/new', function (req,res){
res.render("blog/newpost");
})
// CREATE (POST TO PAGE)
// EDIT (PUT TO PAGE)
// DELETE
// EXPORT TO ROUTER
module.exports = router;
the /blog/home page loads the static CSS, JS perfectly but once you get to /blog/newpost it changes the path of the static files to now include the /blog in it. I would expect if the first app.get in the route structure would work they would all follow, but I am at a loss why it keeps adding the additional route directory.
I found my mistake in my partials/header.ejs file. I left out the "/"before the root of my static CSS/JS files so the router followed its path and added the route as it correctly should have.
Related
I have site stub, where routing is set in 2 places.
First in app.js:
...
var index = require('./routes/index');
var users = require('./routes/users');
...
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
...
something is set with use. Next inside referred scripts, like index.js:
var express = require('express');
var router = express.Router();
var fs = require('fs');
var path = require('path');
var config = require('../config');
/* GET home page. */
router.get('/', function(req, res) {
var data = {};
...
Suppose I wish to use infromation from Express Routing doc. Where I should put the routing for, say, /users/:userId/books/:bookId?
In docs, get is called against app, while in my stub, get is called against router and in two-step manner.
Where to hook?
In docs get is called against app because they set their endpoints in app.js file. In your index.js you return the router from the file with module.exports = router;, which is app's router. Now in your app.js file says
app.use('/', index);
app.use('/users', users);
These are the routes. You are saying that all the endpoints which are in index file are starting with / and the endpoints which are in users file are starting with /users.
So the route /users/:userId/books/:bookId must be in users.js file like this
router.get('/:userId/books/:bookId', function(req, res, next) {
// do something
});
If you want to handler this route - /users/:userId/books/:bookId, then you need to write following handler in your routes/users.js file.
router.get('/:userId/books/:bookId', function(req, res) {
var data = {};
});//get route
Basically, in app.js you are categorising url's based on its first part e.g. users. So, all your routes that start with /users will be handled by your routes/users.js class. All other routes will be handled by routes/index.js, because that is defined to handle / (there is no /users, /admin etc. so all routes that are not handled by users.js can be handled in this.)
Also, in these route handler files, you define a router object, add all route handlers to it and export it at the bottom. So when you are in these files, you need to use router and in app.js you can directly use app.get() etc.
Say for example in my node_module folder I have an npm called project which has some set defined express routes. For example,
var express = require('express');
var router = express.Router();
router.get('/', function (req, res, next) {
res.render('indexPage', {title: 'Homepage'});
});
module.exports = router;
which is kept in a routes.js file
How would this be accessed in the main node project file index.js file?
I have attempted to use require() function, however, this doesn't work.
After you set your app as an Express app then add your routes middleware(s) like the below.
Also I've added some useful code parts (a simple Express app) for any beginner:
// defining an express app
var express = require('express')
var app = express()
var server = require('http').Server(app)
// setting the express app - in case of needed
app.set('x-powered-by', false) // hide x-powered-by header!
app.set('view engine', 'ejs'); // set EJS as view engine!
app.set('views', __dirname + '/views'); // specifying the directory that contains view files
// THIS IS YOUR ANSWER PART
app.use(require('./routes'))
...
...
// Other middlewares
app.use(require('./middlewares/someMiddleware'))
// Catching 404 errors
app.use('*', function(req,res){
res.status(404).send("URL not found.")
})
// Catching and evaluating the other errors
app.use(require("./middlewares/errorHandler"))
server.listen(3001, function() {
console.log('APP Server is listening HTTP port 3001')
})
Generally the last route is been 404 error. So, if the request has not been caught in any route before 404, that means "the page cannot found".
Also, errorHandler middleware takes 4 arguments (error, request, response and next).
So, if you encountered with an error in your routes.js, and if you send this error in routes files by using next(err) this error can be caught on errorHandler middleware.
This is basic information which everyone needs when starting to develope an Express application.
For more details:
http://expressjs.com/en/guide/using-middleware.html
Good luck...
Following a LoopBack tutorial, I want to modify it to serve a directory listing if the directory does not have an index.html or similar.
I have previously done this in Express using:
var express = require('express');
var serveIndex = require('serve-index');
var app = express.express();
app.use('/', serveIndex(__dirname + '/public', {}));
app.use('/', express.static('public'));
Can I modify middleware.json to do this? Alternatively, how could I do this in a LoopBack JS boot script?
I have tried putting the following in a file routes.js in the boot directory:
module.exports = function(app)
{
var serveIndex = require('serve-index');
app.use('/', serveIndex(__dirname + '../client', {}));
app.use('/', app.static('../client'));
};
But it's obviously not the same, since app.static() in the first example is not a method on the same object as use() - ie the second example produces the error:
TypeError: app.static is not a function
(Also the paths aren't right, but I'm dealing with one problem at a time)
It was quite straightforward. While I could not find a way to access the express module via the loopback app object, it could simply be require()d.
Create the file ./server/boot/routes.js with the following:
module.exports = function(app)
{
var express = require('express');
var serveIndex = require('serve-index');
var croot = __dirname+'/../../client';
app.use('/', express.static(croot));
app.use('/', serveIndex(croot, {'icons': true}));
}
Is there any way I can always serve the same file?
So, if they go to website.com/ajsdflkasjd it still serves the same file as website.com/asdnw
I would like to do this using express with node.
The file I have is a static html file, not a jade file.
By the way, the reason I'm wanting to do this, in case you were wondering, is I have an angularjs app that handles all the routing for me. So, all I need to do is serve that one page, and it will take care of the rest.
Thanks in advance!
new answer
const app= require('express')()
// static file serve
app.use(express.static(__dirname))
// not found in static files, so default to index.html
app.use((req, res) => res.sendFile(`${__dirname}/index.html`))
app.listen(3000)
old answer
var express = require('express');
var bodyParser = require('body-parser')
var path = require('path')
var app = express();
// url encoding
app.use(bodyParser.urlencoded({extended:false}));
// gzip
// redirect all html requests to `index.html`
app.use(function (req, res, next) {
if (path.extname(req.path).length > 0) {
// normal static file request
next();
}
else {
// should force return `index.html` for angular.js
req.url = '/index.html';
next();
}
});
// static file serve
app.use(express.static(__dirname))
app.listen(3000)
Below is what I'm using express with angularjs in my project. It will always send index.html unless the browser requests resource files (images, css, js, etc.) which contains extname.
var express = require('express');
var app = express();
app.configure(function () {
// url encoding
app.use(express.urlencoded());
// gzip
app.use(express.compress());
// redirect all html requests to `index.html`
app.use(function (req, res, next) {
if (path.extname(req.path).length > 0) {
// normal static file request
next();
}
else {
// should force return `index.html` for angular.js
req.url = '/index.html';
next();
}
});
// static file serve
app.use(express.static(__dirname));
});
Basic configuration for Express 4 is:
var express = require('express');
express()
.get(/.*/, function(req, res) {
res.sendFile('index.html', {
root: __dirname
});
})
.listen(8080);
Working example
Those snippets with GZip, BodyParser etc. are pretty cool, but I think over-complicated if you want to just test your single page app. Of course you can add all this "production stuff" when it starts to be needed.
Read more:
sending files
routing
Here a simple implementation with ExpressJs to create a virtual host and whenever return the index.html
var express = require('express');
var app = express();
var vhost = require('vhost');
// Function to create virtualhost
function createVhost(domain,rootDirectory){
var exp = express();
exp.use(express.static(rootDirectory));
exp.get(/.*/,function(req,res){
res.sendFile('index.html',{root:rootDirectory});
})
app.use(vhost(domain,exp));
}
// Virtual Host to create
createVhost('example.com','/home/[user]/[www]/[example.com]');
createVhost('othersite.com','/home/[user]/[www]/[othersite.com]');
// Start Server
app.listen(80,function(){
console.log('Node server on port 80');
});
Remember:
Add the domains in the "/etc/host" (in linux)
127.0.0.1 example.com
127.0.0.1 othersite.com
And run in the terminal the "app.js" with "sudo" for port 80
~/home/[server]$ sudo node app.js
You can do this in both angular as well as node side.
In Node side you can do something like this:
res.sendfile('<ur html file path');
In Angular if you using ui-router you can make use of
$urlRouterProvider.otherwise('/otherwise');
and this otherwise state needs to be defined as well
$stateProvider
.state("otherwise", { url : '/urPage'...})
If you using ngRoute, you can do
$routeProvider.otherwise({redirectTo: '/urPage'});
UPDATE
Since your routers are not configured to show a default urPage, in the server you can have something as:
var app = express.createServer();
app.get('/urPage',function(req,res){
res.sendfile('<ur html page>');
});
im new to node and after a few weeks practicing it, i found the express framework and i started to used it because it handle the tools i need more easy, but theres something i dont get to understand, its quite different from how do make the app without express. i dont quite get the express api well (its a bit confusing). im trying to make the request url to be found in specific url (./views). so when logi is requested, then it will do (./views/login.html)when url is(hostname/login), and so on if it contains folder. this is my code
/*
Chat application for #node.js
express version.
*/
//Load modules.
var express = require('express'),
socket = require('socket.io'),
swig = require('swig'),
fs = require('fs');
//Load config.
console.log('Loading configuration.');
var config = fs.readFileSync('config.json');
var config = JSON.parse(config);
var port = config.port;
var views = config.views;
console.log('Configuration loaded.');
//Initiate express module in app.
var app = express();
// app.get('/', function(request, response)
// {
// fs.readFile('./views/index.html', function(error, data)
// {
// if(error)
// {
// response.send('View cannot be rendered.');
// }
// response.type('html');
// response.send(data);
// });
// });
var test = "Hello";
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
swig.setDefaults(
{
cache: false
});
app.get('/', function(request, response)
{
response.render('index',
{
//Var to be named in the render : value;
'test': test,
'Title': 'Testing page',
});
});
//logger.
app.use(function(request, response, next)
{
console.log('%s %s', request.method, request.url);
next();
});
//Set directory for static files (css, js, img);
app.use(express.static(__dirname + '/public'));
//Run the app.
app.listen(port);
im using swig module for dynamic data in html, im also comenting my tests, used app.use() for static files in ./public folder (as found in the api). so what i want to achieve is, if the url file exist, then render it with its static files(css, js). if not, return a custom html file..
im using app.get() to recieve the expecific request.(which totally i dont get).
PD: PLEASE, NEED EXPRESS TUTORIALS (better than express homepage itself.), atleast for newbies.
Since views is not in the public directory, any url with views in it will not go to the app.use() function anyway (because it can't find it there). This is good. What you need to do now is create a routing function for that specific view. Something like this above your app.use():
app.get('/views/login', function(req, res){
res.render(__dirname + 'views/login');
});
usually, rendering engines will allow you to do a shortcut though, and just do res.render('login'); and it will find it in views by itself.
Also, some renderers allow you to specify a directory to look for when requests come in. I don't know if swig offers this though.