Before my file system got a bit more complicated, I used to serve static files through app.use(express.static()). Now, I'm using express.Router() and I thought I could just change app.use(express.static()) to router.use(express.static()), but it doesn't work. It throws an error: Refused to apply style from ... because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
Is there a way I can serve static files with router.use() instead of app.use()?
Filesystem:
/
..../chat
......../register
............/styles
................styles.min.css <-- This is the static file I want to serve
............index.html
............index.js
..../routes
........index.js
....index.js
/routes/index.js:
const express = require('express');
const router = express.Router();
router.use('/chat/register', require('../chat/register'));
router.get('/', (req, res) => res.redirect('/chat/register'));
module.exports = router;
/chat/register/index.js:
const express = require('express');
const router = express.Router();
router.use('/styles', express.static('styles'));
router.get('/', (req, res) => {
res.sendFile(`${__dirname}/index.html`);
});
module.exports = router;
/index.js:
const express = require('express');
const app = express();
app.use(require('./routes'));
app.listen(process.env.PORT || 80);
console.log(`App is listening on port ${process.env.PORT || 80}`);
Sorry if the question is badly-worded or something in the code looks out of line; this is my first time posting to Stack Overflow and I'm also kinda new to Node, Express, and web servers. I learn to program on my own time.
From the express docs
the path that you provide to the express.static function is relative to the directory from where you launch your node process.
So to take this into account, you should modify chat/register/index.js
const express = require('express');
const path = require('path');
const router = express.Router();
router.use('/styles', express.static(path.join(__dirname, 'styles')));
router.get('/', (req, res) => {
res.sendFile(`${__dirname}/index.html`);
});
module.exports = router;
You have to modify your path for the css, as this will be loaded by the server so that use the relative path for server as below.
In your index.js
const express = require('express');
const router = express.Router();
const path = require('path');
router.use('/styles', express.static(path.join(__dirname, 'styles')));
router.get('/', (req, res) => {
res.sendFile(`${__dirname}/index.html`);
});
module.exports = router;
Related
I have an express app like so:
// index.js
const express = require('express');
const app = express();
const userRoutes = require('./routes/userRoutes');
app.use('/user', userRoutes);
const verifyToken = (req, res, next) => {
// validate req.cookies.token
next();
}
And I'm using an express router module like this:
// routes/userRoutes.js
const express = require('express');
const router = express.Router();
router.get('/:userid/data', verifyToken, async (req, res) => {
const data = await db.query()
res.json(data)
});
Obviously this doesn't work because verifyToken is not accesible within the module. How can I use the same verifyToken middleware function throughout different express modules?
Move verifyToken to a different file and export it from there.
Then you can import it in other places.
One thing that you can do, that works well is to group all your authed routes under a common path and use router.use to make sure that you apply the verifyToken middleware on all of them.
app.js
const express = require("express");
const app = express();
app.use("/", require("./routers.js")(app));
app.listen(3000);
router.js
module.exports = function (app) {
console.log(app);
app.get("/", (req, res) => {
res.json(5);
});
};
The error given by the Console is: " TypeError: Router.use() requires a middleware function but got an undefined "
I don't understand why I can't pass the express app(app.js) through routers( in this way I don't redeclare the express and app variable in router.js ).
Don't pass app to routes better to create a new router and pass to the app.
router.js
const express = require("express");
const router = express.Router();
router.get("/", (req, res) => {
res.json(5);
});
module.exports = router;
app.js
app.use("/", require("./routers.js"));
As you mention in the comment, you don't have to add an inside app.use
module.exports = function (app) {
app.get("/", (req, res) => {
res.json(5);
});
};
// app.js
require("./routers.js")(app);
The use method of Express needs a callback of three parameters, not the app itself, so you need something like this:
In routes.js
exports.doSomeThing = function(req, res, next){
console.log("Called endpoint");
res.send("Called endpoint");
}
In your index.js
const Express = require("express");
const app = Express();
const routes = require("./routes");
app.use("/", routes.doSomeThing);
app.listen(3030, () => {
console.log("Listening on port 3030");
});
This approach doesn't need to include the express router but this may not be adecuate for big scale projects I recommend you to read express router documentation:
https://expressjs.com/es/guide/routing.html#express-router
so I'm trying to make a simple "route system", that would handle requests and send them to a certain controller.
The problem is that I can't even handle any route, because I get
Cannot GET /
error in response.
app.js
const express = require('express')
const router = require('./routes/routes')
const app = express()
const port = 3000
app.engine('.html', require('ejs').__express)
app.set('view engine', 'html')
router.load()
app.listen(port, () => {
console.log(`Waiting on :${port}`)
})
routes.js
const express = require('express')
const app = express()
// Route config
const routes = {
['/']: {
controller: 'index',
method: 'get'
},
}
// Load routes
const load = () => {
for (const route in routes) {
app[routes[route].method](route, (req, res) => {
// Do something
})
}
}
exports.load = load
You don't use your router file in app.js, try that:
app.js
const express = require('express')
const router = require('./routes/routes')
const app = express()
const port = 3000
app.engine('.html', require('ejs').__express)
app.set('view engine', 'html')
app.use('/', router);
router.load()
app.listen(port, () => {
console.log(`Waiting on :${port}`)
})
routes.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) { res.send({ success: true }); });
module.exports = router;
It's useless and unreadeable create an array whit your all your routes.
My suggestion is to try use command by terminal express my_app for generate the base structure and try to use it or at least read for see how it's work.
You seem to be lacking the context for how the routing system works within Express.
As a starting point, please create a project with the below structure, and try creating your own route to ensure you have a grasp on how to utilize them properly.
Create a new project folder
cd into the project folder from within your terminal
run npm init -y
Run npm i express dotenv
Create a file named app.js in the root of your project folder and place the below code inside of it:
require('dotenv').config();
const express = require('express');
const app = express();
app.use(express.json({limit: '30mb', extended: true}));
app.use(express.urlencoded({ extended: true }));
app.listen(process.env.PORT || 3000, () => {console.log('Server successfully started')});
app.get('/', (req, res) => {
return res.send('Hello, World!');
});
Create a new folder named routes
Create a new file named test.js and place it inside of the routes folder
Place the below code in the test.js file.
const router = require('express').Router();
router.get('/', (req, res) => {
return res.send('Hello from your custom route!');
});
module.exports = router;
Go back into your app.js file and add the below lines of code to the bottom of the file
const testRoute = require('./routes/test');
app.use('/test', testRoute);
In your terminal, run node app.js
Make a GET request to http://localhost:3000/test by navigating to it with your browser, or by using a REST client, such as Postman.
Once you have completed these steps, you should understand the basic concept of Express routing.
You can use the router combined with Express Middleware to re-route your user to the proper controller based on the endpoint they are trying to access / the data they are trying to send.
Please test with this code
const express = require('express')
const app = express();
app.get('/', (req, res) => {
res.json({"message": "Welcome! it's working"});
});
The complete code is here on Github
In my router code, I have something like below. In my main page, I have a button to jump to login page, that is work with out nodejs, but after I connect the node.js code, only show me the main page, if I click the login button, the page will show be that Cannot GET /LoginPage.html. How to fix that?
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.render('HomePage.html', {
title: 'Hello World'
})
})
router.get('/login', (req, res) => {
res.render('LoginPage.html', {
title: 'Hello World'
})
})
In the app.js code:
const passport = require('passport')
const flash = require('express-flash')
const session = require('express-session')
const multer = require('multer');
const GridFsStorage = require("multer-gridfs-storage");
const path = require('path')
const cors = require('cors')
const crypto = require("crypto");
const favicon = require('serve-favicon')
const app = express();
const User = require('./models/user')
const router = require('./router')
app.engine('html', require( 'express-art-template'))
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(__dirname + '/public'))
app.use('/node_modules/', express.static(__dirname + '/node_modules'))
app.use(cors());
app.use(router)
app.listen(4001, (req, res) => {
console.log('port xxxx')
})
In the HTML code, just click the button, and jump to Loginpage.html
Login
A couple of things,
you have 2 same endpoints router.get('/',
So change the second route to something like router.get('/login',
you should access your login page now on /login
You are getting Cannot GET /LoginPage.html because there is no route LoginPage.html in your backend
First thing is the way you defined the routes is wrong as you have 2 same end points.Try to change the login endpoint as /login in your .js file.
You need to change the html file also as you are trying to call directly the html file not the api end point /login.You need to call to the node backend endpoint which renders the desired html file.
not the direct reference to html file.
Edit 1:
Please do the following:
Change your app.js file like below:
const express = require('express');
const app = express();
const router = require('./router');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
app.engine('html', require('express-art-template'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('', express.static(path.join(__dirname, 'public')));
app.use(cors());
app.use(router);
app.listen(4001, (req, res) => {
console.log('port 4001');
});
And the router.js to like this
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.render('index.html', {
title: 'Hello World',
});
});
router.get('/login', (req, res) => {
res.render('login.html', {
title: 'Hello World',
});
});
module.exports = router;
And create a public folder and create 2 html files index.html and login.html. Your app structure should be like below:
--public
-------+ index.html
-------+ login.html
-- app.js
--router.js
--package.json
I tried this it worked for me. Change the variables and other file names as per your need. I guess your folder structure and the way you are rendering is wrong.Hopefully it should work.
I've created a node application with express. I try to separate the following layers which will give me the ability to test the application with unit testing...
The problem is that I don't know how to call to the router.js file which will stops in the post/get/delete application.
The server.js file looks as follows
http = require('http'),
app = require('./app')(),
http.createServer(app).listen(app.get('port'), function (err) {
console.log('Express server listening on port ' + app.get('port'));
});
This is the app.js file
var express = require('express'),
logger = require('morgan'),
bodyParser = require('body-parser'),
routesApp = require('./ro/route');
module.exports = function () {
var app = express();
app.set('port', process.env.PORT || 3005);
app.use(logger('dev'));
app.use(function (req, res, next) {
res.set('APP', 'User app');
next();
});
app.use(bodyParser.json());
app.use(routesApp);
return app;
};
This is the router.js, which will route the call to other module according to the http type like post/delete/get etc...
var handleGet = require('../controller/handleGet');
var handlePost = require('../controller/handlePost');
var express = require('express');
module.exports = function (app) {
var appRoute = express.Router();
app.use(appRoute);
appRoute.route('*')
.post(function (req, res) {
handlePost(req, res);
})
.get(function (req, res) {
handleGet(req, res)
})
Currently I've two questions:
How to make it work since when in debug It dump in
app.use(appRoute); on the router.js file?
The error is TypeError: undefined is not a function
Is it good way to structure the node app like in my post? I want to seperate all this layers like SOC, I'm fairly new to node and express and I try to build it to be modular and testable...
How to make it work since when in debug It dump in app.use(appRoute); on the router.js file? The error is TypeError: undefined is not a function
This fails because you don't pass app into the module when you require it in app.js, you would need to do something like
app.use(routesApp(app)); // <- this hurts my eyes :(
Is it good way to structure the node app like in my post?I want to sperate all this leyrs like SOC,I fairly new to node and express and I try to build it to be modular and testable...
Your definitely on the right track, keeping things separated is generally always a good idea. Testing is definitely one of the big pluses but it also helps with other things like maintainability & debugging.
Personally, I would make use of the bin directory for any start up script configuration
bin/www
var app = require('./app');
app.set('port', process.env.PORT || 3005);
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
This will help decouple your express app from all the environment setup. This should keep your app.js clean and only contain app-related config
app.js
var express = require('express')
, app = express()
, logger = require('morgan')
, bodyParser = require('body-parser')
, routes = require('./routes.js');
app.use(logger('dev'));
app.use(function (req, res, next) {
res.set('APP', 'User app');
next();
});
app.use(bodyParser.json());
app.use('/', routes);
...
module.exports = app;
Then finally, your routes.js should do nothing but handle your URLs
routes.js
var express = require('express')
, router = express.Router()
, handleGet = require('../controller/handleGet')
, handlePost = require('../controller/handlePost');
router.get('/', handleGet);
router.post('/', handlePost);
...
module.exports = router;