I'm having a hard time to organize my code, so i decide implement the bluebird in the initialization process, but the only purpuse is organization, so i don't know exactly how to call resolve in one of my process.
I have:
Configuration(app).then(Apps).then(Routes)
Configuration -> Turn my configuration object global.
Apps -> configure the uses, sets and uses of express
Routes -> create the routes
The problem is. How to apply the logic of a new promises in this file:
var Apps;
Apps = function(app) {
app.engine('.html', ejs.renderFile);
app.set('views', path.join(__dirname, '../../client/views'));
app.set('view engine', 'ejs');
app.use(body.json());
app.use(body.urlencoded({
extended: false
}));
app.use(cookie());
app.use(express["static"](path.join(__dirname, '../../client/public')));
app.use(express["static"](path.join(__dirname, '../../client/app')));
app.use(function(request, response, next) {
response.header('Access-Control-Allow-Origin', GLOBAL.config.cors.origin);
response.header('Access-Control-Allow-Methods', GLOBAL.config.cors.methods);
response.header('Access-Control-Allow-Headers', GLOBAL.config.cors.headers);
next();
});
app.use(session({
secret: '04Eq27Sgg0BDlgfRmarMar1234689007-James-Bond'
}));
};
I don't have any logic like: Do this, if ok call resolve, if not, call reject. So, is stupid to do this:
var Apps;
Apps = function(app) {
return new Promise(resolve, reject) {
app.engine('.html', ejs.renderFile);
app.set('views', path.join(__dirname, '../../client/views'));
app.set('view engine', 'ejs');
app.use(body.json());
app.use(body.urlencoded({
extended: false
}));
app.use(cookie());
app.use(express["static"](path.join(__dirname, '../../client/public')));
app.use(express["static"](path.join(__dirname, '../../client/app')));
app.use(function(request, response, next) {
response.header('Access-Control-Allow-Origin', GLOBAL.config.cors.origin);
response.header('Access-Control-Allow-Methods', GLOBAL.config.cors.methods);
response.header('Access-Control-Allow-Headers', GLOBAL.config.cors.headers);
next();
});
app.use(session({
secret: '04Eq27Sgg0BDlgfRmarMar1234689007-James-Bond'
}));
resolve()
}
};
My question is. In this case, what can i do???
Related
Im using express-ejs-layout for my project. my project has routing. I want use different layout for different res queries. for example if query is: www.xxx.com/a, use LayoutA.ejs, if query is: www.xxx.com/b, use LayoutB.ejs. My index.js part code is:
...
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '/app_server/views'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(ejsLayout);
app.use('/public', express.static(path.join(__dirname, 'public')));
require('./app_server/routes/routeManager')(app);
...
how can I?
I've just solve problem myself. I'll write for friends who face to same problem.
app.get('/a', function(req, res) {
res.render('view', { layout: 'LayoutA' });
});
app.get('/b', function(req, res) {
res.render('view', { layout: 'LayoutB' });
});
This is what I do:
First, I set a default layout
// app.js
app.set('layout', 'layouts/front') // assuming it's inside the 'views' directory
Then, I use middlewares for separate Router instances:
// app.js
app.use('/admin', AdminRoutes);
In my AdminRoutes.js:
// AdminRoutes.js
const router = express.Router();
router.use((req, res, next) => {
// changing layout for my admin panel
req.app.set('layout', 'layouts/admin');
next();
});
router.get('/', (req, res) => {
res.render('admin/index'); // will use admin layout
});
const path = require('path')
const express = require('express');
const app = express();
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.set('layout', 'layoutsA', 'layoutsB');
const router = require("express").Router();
const expressLayouts = require("express-ejs-layouts");
// user router
router.use(expressLayouts)
router.get('/, (req, res) =>{
res.render("user", {layout: "layoutsA"})
})
const router = require("express").Router();
const expressLayouts = require("express-ejs-layouts");
// post router
router.use(expressLayouts)
router.get('/, (req, res) =>{
res.render("user", {layout: "layoutsB"})
})
My angular2 app's routes don't work when accessed via URL... Express is rendering an error page instead.
So I have one route (/docs) which serves some static content and some other static resources, however, / is routed to an index.html which is managed by angular 2. So by opening the application root and then clicking various router links I can get to a route e.g. /tutorial/chapter/1. However, as that isn't a registered route in my express app, if I refresh the page I get a 404.
I want to be able to type http://localhost:3000/tutorial/chapter/1 into my browser and get that page. How do I set express to route all undefined routes to angular, and let angular handle the 404?
Here is my app.js:
var app = express();
// html view engine setup
app.set('views', path.join(__dirname, '/ng2/views'));
app.engine('html', require('jade').renderFile);
app.set('view engine', 'html');
app.use(express.static('ng2/views'));
app.use(express.static('ng2/public'));
app.use('/node_modules', express.static(__dirname + '/node_modules'));
// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'ng2/public', 'favicon.png')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//all static assetes for hexo content
app.use('/docs', serveStatic('features/docs/public', { 'index': ['index.html', 'index.htm'] }));
app.use('/', routes);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
module.exports = app;
You can see the full repo here
Here is the routes middleware def:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
Angular 2 assumes that independent of the request URL, the frontend will be returned. This assumption is based on a feature modern browsers implement called push state. You have 3 options if you want to support anything but the bleeding edge of browsers:
Recommended: Seperate the API server from the client.
If you put your client on example.org and your express backend on api.example.org you can just do what Angular assumes to be true. You can also deploy independently and the client can live on a static host or CDN. This will require that you setup CORS though.
Catch-All Express Route
Make sure all your routes in Express differ from the ones you setup in NG2 and make a catch-all handler. Put something like this at the end of your routes/middleware but before the 404 handler!
app.use(function(req, res, next) {
res.sendFile("index.html");
})
Use legacy browser-url-styles for the router.
You can make the NG2 router use hashes for routes. Check here.
app.js
Since order is important and new code is inserted in multiple locations, the whole file is included. Look for comment started with // JS -
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var serveStatic = require('serve-static')
var file = require('./features/prepareTutorial');
var routes = require('./ng2/routes/index');
var app = express();
// html view engine setup
app.set('views', path.join(__dirname, '/ng2/views'));
app.engine('html', require('jade').renderFile);
app.set('view engine', 'html');
app.use(express.static('ng2/views'));
app.use(express.static('ng2/public'));
app.use('/node_modules', express.static(__dirname + '/node_modules'));
app.use('/persist', express.static(__dirname + '/persist'));
// JS - Add /app
app.use('/app', express.static(__dirname + '/ng2/views/app'));
// I have to comment this line because it failed
//file.processTutorial(); //generate html rendered patches for tutorial steps
//file.genGit(); //generate git SHA
file.processChapters();
// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'ng2/public', 'favicon.png')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//all static assetes for hexo content
app.use('/docs', serveStatic('features/docs/public', { 'index': ['index.html', 'index.htm'] }));
//app.use(subdomain('docs', express.static('docs/public')));
app.use('/script', serveStatic('features/docs/public/script'));
app.use('/style', serveStatic('features/docs/public/style'));
app.use('/images', serveStatic('features/docs/public/images'));
app.use('/diff', serveStatic('features/tutorial/diffs'));
app.use('/git', serveStatic('features/git'));
app.use('/chapter', serveStatic('ng2/views/app/tutorial/chapter/chapters'));
app.use('/img', serveStatic('features/docs/source/img'));
app.use('/config', serveStatic('ng2/config'));
app.use('/', routes);
// JS - /tutorial static
//app.use('/tutorial', express.static('ng2/views/app/tutorial'));
// JS - /tutorial/chapter/* send index file
app.all(/^\/tutorial$/, (req, res) => {
res.redirect('/tutorial/');
});
app.use('/tutorial/', (req, res) => {
res.sendFile(__dirname + '/ng2/views/index.html');
});
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
ng2/config/systemjs.config.js & ng2/public/config/systemjs.config.js
Use absolute path
This is the main issue. With relative path, the browser is requesting files at tutorial/chapter/2/app/*, tutorial/chapter/2/node_modules/*, etc, and the app break down completely.
// snip ...
var map = {
'app': '/app', // 'dist',
'#angular': '/node_modules/#angular',
'angular2-in-memory-web-api': '/node_modules/angular2-in-memory-web-api',
'rxjs': '/node_modules/rxjs'
};
// snip ...
ng2/views/index.html
Use absolute path
This won't stop the page from loading but a mess.
// snip ...
<link rel="stylesheet" href="/stylesheets/style.css">
// snip ...
Instead of app.use('/', routes);, register a middleware that will always serve the index.html. Be cautious though, this can cause your app to return index.html even inside the /docs route.
Just use the middleware that renders the index page:
app.use(routes);
Make sure the routes middleware itself always renders the page, not only on / path.
var express = require('express');
/* render home page. */
var router = function(req, res, next) {
res.render('index', { title: 'Express' });
};
module.exports = router;
Remove this the 404 handler (it should be automatic)
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
And change the node_modules route to the following (because SystemJS relies on 404 responses during resolution):
var modules = express.Router();
modules.use(express.static(__dirname + '/node_modules'));
modules.use(function(req, res, next) {
// Missing files inside node_modules must return 404
// for the module loader to work
res.sendStatus(404);
});
app.use('/node_modules', modules);
I just try to write a simple node.js application, but if I use the express-validator the site is just loading and do nothing :(
"waiting on localhost", after some time an "ERR_EMPTY_RESPONSE" error appears.
If i delete the app.use(expressValidator) the application works again.
var express = require('express'),
expressValidator = require("express-validator");
var app = express();
app.configure(function(){
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.use(express.bodyParser());
app.use(expressValidator);
});
app.get('/', function(req, res) {
console.log('get something get');
res.render('app.jade');
});
app.post('/', function(req, res){
console.log('get something post');
res.render('app.jade');
});
app.listen(process.env.PORT || 8080);
You need to call the expressValidator function to get it to return a middleware handler:
app.use(expressValidator());
^^ important!
I got a little bit confused about my node.js application. As far as I thought, node.js runs in a single process. However if I start my application by invoking node app.jsand monitor it with htop, I can see 4 sub-processes running, where I'd expect only one to be.
app.js
var express = require('express'),
routes = require('./routes'),
objects = require('./objects'),
http = require('http'),
path = require('path'),
pinLayout = objects.pinlayout,
// utils
util = require('util'),
wiringPi = require('wiring-pi'),
winston = require('winston'),
async = require('async');
// Logger - winston
var log = new(winston.Logger)({
transports: [
new(winston.transports.Console)({
colorize: true,
timestamp: true
}),
new(winston.transports.File)({
filename: './log/app.log'
})
]
});
// WiringPi
wiringPi.setup('gpio');
var app = express();
// all environments
app.set('port', process.env.PORT || 3001);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('less-middleware')({
src: __dirname + '/public',
force: true,
compress: true
}));
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// 404 Page
app.use(function(req, res, next) {
res.render('404.jade', {
title: "404 - Page Not Found",
showFullNav: false,
status: 404,
url: req.url
});
});
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
}
Although your code runs in a single thread, node.js uses a thread pool (mostly) for file system operations. This is needed because there are no async APIs for fs.
For example, when you call file.readFile, you will go through Read(), which will call:
ASYNC_CALL(read, cb, fd, buf, len, pos);
read is the blocking unix read(2). This will run in a thread until it completes. These are the threads you are seeing.
I had set up compiling LESS on server side in Express, and it worked right in jade without putting less in layout.
my terminal:
if(err) throw err;
^
Error: ENOENT, open '/Users/lijung/Documents/Project/clubond/public/stylesheets/left_navigator.less'
app.js:
/**
* Module dependencies.
*/
var express = require('express')
, path = require('path')
, club = require('./routes/club')
, less = require('less')
, fs = require('fs');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
var RedisStore = require('connect-redis')(express);
app.use(express.cookieParser());
app.use(express.session({ secret: "william", store: new RedisStore }));
app.use(express.logger());
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.set('view options', { layout: false });
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
//index-in-layout
app.get('/club/:id', club.chkExist, club.getDataById, site.clubPage);
//compile less
app.get("*.less", function(req, res) {
var path = __dirname + req.url;
fs.readFile(path, "utf8", function(err, data) {
if(err) throw err;
less.render(data, function(err, css) {
if (err) throw err;
res.header("Content-type", "text/css");
res.send(css);
});
});
});
app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
I put my layout in views named index_in_layout:
!!! 5
html
head
title= title
script(src='/javascripts/jquery.min.js')
link(rel="stylesheet", href="/stylesheets/index.css")
link(rel="stylesheet",type='text/css', href="/public/stylesheets/left_navigator.less")
script(src='/javascripts/index_in.js')
block script
body
index.jade:
extends ./index_in_layout
block script
script(src='/javascripts/new_club.js')
script(src='/javascripts/new_bond.js')
script(src='/javascripts/new_event.js')
script(src='/javascripts/popup.js')
script(src='/javascripts/list_clubs.js')
script(src='/javascripts/list_bonds.js')
script(src='/javascripts/list_events.js')
link(rel='stylesheet', type='text/css', href='/public/stylesheets/test.less')
block body
Terminal keeps telling me Error: ENOENT that my left_navigator.less can't open. I put test.less and navigator.less in the same directory, it makes no sense.
LESS on server side driving me crazy. Can someone help me out please. Thanks
Unless I'm missing something, you really don't need to go through these heroics to get less working :-) Generally you just need to add one line to your app.configure call like this:
app.configure(function() {
app.set('views', __dirname + '/views');
...
app.use(express.compiler({ src: __dirname + '/public', enable: ['less'] }));
app.use(connect.static(__dirname + '/public'));
app.use(app.router);
});
If you do it this way, you don't need the special route for *.less files. You just request *.css with the same name in your public folder and it's automatically generated. I use master/child layouts with jade and LESS here if an example would help:
https://github.com/JustinBeckwith/ExpressStarter
Happy Coding!