understanding modules/routes in nodejs - node.js

I'm new in nodejs. I want to build a rest service with multiple, lets say, categories.
> app.js
var express = require('express')
, http = require('http')
, routes = require('./routes')
, path = require('path');
app = express();
app.use(app.router);
app.get('*',routes.index);
app.listen(3000);
console.log('Express app started on port 3000');
and
> routes/index.js
var sites = [
'sve',
'ice'
];
exports.index = function(req,res){
var url = req.url.split('/');
for (i in sites) {
app.get('/' + sites[i] + '/*',require('./' + sites[i]));
}
};
and
> routes/sve/index.js
module.exports = function(req, res){
console.log('sve')
res.end({category:'sve'});
};
and
> routes/sve/index.js
module.exports = function(req, res){
console.log('sve')
res.end({category:'sve'});
};
when I run "node app" I get "Express app started on port 3000" and the server is running but when I access "localhost:3000/sve/test" I have no response or "localhost:3000/ice/test" or even "localhost:3000/abc/test".
Not even in the console.
What am I doing wrong?

As mentioned in my comment, I think you are looking for a method of using sub-apps (like Rails Engines) do modularize your application. If this is the case, you should use app.use() to mount a sub-app.
There's a good video on it here.
One last thing of relevance that isn't mentioned in the video, you can mount sub-apps relative. For instance:
var subapplication = require('./lib/someapp');
app.use('/base', app.use(subapplication));
This will treat the routes in subapplication as being from the '/base' path. For instance, a route catching '/a' in subapplication, when mounted in this example, will match a request to '/base/a'.

Related

No content in <app-root> element in browser using the command "node app.js"

I created an Angular 7 application using the Angular CLI. I added my express server as one knows it. Afterwards I used the command "node server/app.js to start my app, but then in the browser in the "Elements" section there appears <app-root></app-root> without any content. As if the browser knew nothing about the actual Angular application. And when I run the ng serve command it seems to know about the actual Angular application, but there appears a 404 not found error in terms of post and get requests to the data server.
I already had a working Angular4 application with -I guess- the same setup and now same things seem to not work any longer.
I researched all day long to find the solution but for nothing.
I think it is not advantageous to post all my files in here. Comment if I was wrong and I am going to edit them.
Thanks in advance.
My app.js:
"use strict";
var bodyParser = require('body-parser');
const cors = require('cors');
// import { Observable } from 'rxjs';
var express = require("express");
var path = require("path");
var app = express();
app.use(cors());
const router = express.Router();
var nodeModulesPath = path.join(__dirname, "..", "node_modules");
app.use("/node_modules", express.static(nodeModulesPath));
var srcPath = path.join(__dirname, "..", "src");
app.use("/src", express.static(srcPath));
var serverPath = path.join(__dirname);
app.use("/server", express.static(serverPath));
// app.use(bodyParser.json());
var models = require("./models");
models.sequelize.sync({force:true}).then(function() {
console.log("TABELLE ERSTELLT");
// app.use(cors());
app.use("/", router);
app.use(bodyParser
.urlencoded({extended:true})
);
app.use(bodyParser.json());
console.log("after bodyparser");
app.get("/", function(req,res){
res.sendFile(path.join(__dirname, "views", "index.html"));
});
// app.get('/*', function(req, res) {
// res.sendFile(path.join(__dirname, "views", "index.html"));
// });
app.post("/goals/create",function (req, res){
models.Goal.create({
id: req.body.id,
name: req.body.name,
content: req.body.content,
firstGivenValue: req.body.firstGivenValue,
fittingValue: req.body.fittingValue,
someone_would_like_to_implement: req.body.someone_would_like_to_implement,
i_know_how_to_implement_it: req.body.i_know_how_to_implement_it
}).then(function(obj){
console.log(obj.id);
// res.end("erfolgreich");
res.redirect("/");
})
console.log(req.body);
});
app.get("/test",(req, res) => {
res.end("test erfolgreich");
});
app.listen(3000);
});
You mention that you think it used to work for angular 4. Currently you're serving the index.html from the src folder. That's not going to work, your app is a typescript app and will need to be compiled one way or another; not to mention the Angular compiler. In the early days (I think pre 4, but not sure) angular serve also write the served files in a folder in your project, so you could just pick those JIT compiled files up and toss them on a web server, or express server. Those days are gone (with good reason for that matter, mostly performance).
You will now have to create an explicit build (ng build) and tell your express server (app.js) to target your dist folder.
TL;DR:
Run ng build
Replace
var srcPath = path.join(__dirname, "..", "src");
app.use("/src", express.static(srcPath));
With:
var distPath = path.join(__dirname, "..", "dist");
app.use("/dist", express.static(distPath));

Express Vhost 'argument handle is required'

Firstly, found a couple of similar question on here but no duplicates, I think my situation is slightly different.
Trying to get a website and associated API working on Express using vhost for subdomians.
Here is my folder structure
/api
api.js
/server
website.js
server.js
My server.js
const vhost = require('vhost');
const express = require('express');
const app = express();
app.use(vhost('localhost', require('./server/website.js').app));
app.use(vhost('api.localhost', require('./api/api.js').app));
app.listen(1337, () => {});
My api.js
const express = require('express');
const app = express();
app.get('/', function(req, res){
res.send({ hello: 'world' });
});
module.exports = app;
Initially my path to api.js was wrong and I got a not found error so now I know my path is right but now I get the error "Typeerror: argument handle is required" whatever I do.
Any help would really be appreciated.
Your exporting the app already. So it is not necessary to add .app to the end of your require.
It should be:
app.use(vhost('localhost', require('./server/website')));
app.use(vhost('api.localhost', require('./api/api')));
Hope that helps.
here's what I did:
//used the api.localhost as the subdomain url
//it requires another express app.js to work
//the other express app must -> module.exports = app;
const vhost = require('vhost');
const app = express();
app.use(vhost('api.localhost', require('./api/app')));

After restructuring my node/express app, my static route to index.html will not work

I'm wanting to server index.html as a default, as I'm using angular to handle client side routes.
Here's the structure of my app.
Here is app/app.js
var express = require('express'),
config = require('./config/config'),
bodyParser = require('body-parser'),
app = express(),
router = express.Router();
require('./config/db')(function(db) {
require('./routes/routes')(app, router, null, db);
app.use(express.static(__dirname, '/'));
app.use(bodyParser.json());
app.use('/', router);
app.listen(config.port);
console.log('Listening on port ' + config.port);
});
The only thing in ./routes/routes.js are server side routes. I'm really not sure what I did, but index.html used to load by default and then angular took care of the rest.
I'm new to node/express.
Error I keep getting is "Cannot get/"
Any help is appreciated!
you should use
app.use(express.static(path.resolve('./public')));
on the express configuration
in your route you need to have one to serve your root path
module.exports = function(app) {
// Root routing
var core = require('/controllers/core');
app.route('/').get(core.index);
};
your server controller
exports.index = function(req, res) {
res.render('index'); //assuming that you are using some view engine.
};

Run NodeJS app on nodejitsu, all i get is "cannot get /"

as part of my learning i wanted to deploy my app to nodejitsu. Its running fine on my local server, but on nodejitsu all i get is
Cannot GET /
I thought it may have something to do with the NODE_ENV set to production on the server, but i never touched this on my local server. I changed it on nodejitsu to development but still i cant get it to work.
After commenting all the code i think the problem is in my index.js which i show below:
var express = require('express');//the framework
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//var session = require('express-session');
var methodOverride = require('method-override');
var passport = require("passport");//for authentication
var LocalStrategy = require('passport-local').Strategy;//local users for passport
var http = require('http');
var path = require('path');
var db = require('./dataBase');//to connect to the db
var userRoles = require('./routingConfig').userRoles;
var accessLevels = require('./routingConfig').accessLevels;
var debug = false;
var db = new db('inmobiliaria', 'localhost', 3306, debug);
require('./passport')(passport, db, debug)
var app = express();
app.set('port', 1337);
app.use(methodOverride());
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }))
//app.use(session({ secret: 'SECRET' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(function (req, res, next) {
var role = userRoles.public;//default role
var username = '';
if (req.user) {
role = req.user.role;
username = req.user.username;
}
res.cookie('user', JSON.stringify({
'username': username,
'role': role
}));
next();
});
app.use('/', express.static(path.join(__dirname + '/../Client/')));
app.use("/lib", express.static(path.join(__dirname + '/../Client/lib/')));
app.use("/ctr", express.static(path.join(__dirname + '/../Client/Controllers/')));
app.use("/media", express.static(path.join(__dirname + '/../Client/media/')));
app.use("/views", express.static(path.join(__dirname + '/../Client/Views/')));
app.use("/srv", express.static(path.join(__dirname + '/../Client/Services/')));
app.use("/dct", express.static(path.join(__dirname + '/../Client/Directives/')));
require('./routes')(app, passport, db);
//require('./emailConfiguration');
http.createServer(app).listen(process.env.PORT || app.get('port'), function (err) {
console.log("Express server listening on port " + app.get('port'));
if (err) {
throw err; // For completeness's sake.
}
});
I investigated about this variable, but im not sure it has something to do with it. This is the url http://horaciotest.jit.su/, in case you want to see it.
Is this configuration? Am i doing something that should not be done?
Thanks for taking your time.
EDIT:
i managed to reduce the error case to a few lines i think. As the guys at nodejitsu suggested, im now trying to use the module node-static to serve static files, but i cant get it to work along express:
this code works on nodejitsu and my local server (or at least doesnt show any errors)
var statik = require('node-static');
var http = require('http');
var path = require('path');
var file = new (statik.Server)(path.join(__dirname + '/../Client/'));//index.html here
http.createServer(function (req, res) {
console.log(path.join(__dirname + '/../Client/'));
file.serve(req, res);
}).listen(8080);
but as soon as i add express, i get the error i mentioned above:
var express = require('express');
var statik = require('node-static');
var http = require('http');
var path = require('path');
var app = express();
var file = new (statik.Server)(path.join(__dirname + '/../Client/'));//index.html here
http.createServer(app, function (req, res) {
console.log(path.join(__dirname + '/../Client/'));
file.serve(req, res);
}).listen(8080);
Can someone tell me why when i add the express app i get the error? it may be what i need to get this to work on nodejitsu, thanks!
I found out what the problem was, hope it helps someone:
My project structure had two folders: one was named Client, where all my html and .js from angular where.
The other folder was WebServer, where i had all my nodejs files.
In order to deploy to nodejitsu, you run a command which is jitsu deploy, this in turn runs another command: npm pack. This command creates a .tgz file with all the data in you nodejs directory excluding the node_modules file and any file that starts with .. Problem is, if you like me have files outside that folder, they wont be included.
The solutions is to move your client folder inside the nodejs one. Everything you need to sent to the server should be in side this folder.

How do I always serve the same file with express?

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>');
});

Resources