I have a Nodejs server with router files that take absolute routes for the HTTP methods, for example /api/users/all.
// /routes/user.routes.js
module.exports = (app) => {
app.use((req, res, next) => {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
app.get(
"/api/users/all",
controller.allAccess
);
}
Which I require() in my server.js file like this.
// server.js
require("./routes/user.routes")(app);
Now, instead of using the absolute routes, I would like to implement express.Router().
I made the following changes in my user.routes.js file.
// /routes/user.routes.js
const express = require("express");
const router = express.Router();
module.exports = (app) => {
app.use((req, res, next) => {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
router.get(
"/all",
controller.allAccess
);
}
I created an index.js file in my routes folder that uses the routes and exports the router.
// /routes/index.js
const express = require("express");
const userRoutes = require("./user.routes");
const router = express.Router();
router.use("/users", userRoutes);
module.exports = router;
And made the following changes in my server.js file.
// server.js
const routes = require("./routes");
app.use("/api/v1", routes);
But I am getting error messages when hitting the route.
TypeError: app.use is not a function at module.exports
What should I do to implement express.Router() correctly?
The problem is inside your /routes/user.routes.js because app variable is undefined in there. To fix the issue you need to replace app with router variable like below:
const express = require("express");
const router = express.Router();
router.use((req, res, next) => {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
router.get("/all", controller.allAccess);
module.exports = router;
Did you just forget to pass the app into your router.use("/users", userRoutes); call?
At the moment user.routes doesn't know what app is because you haven't implemented something like const app = express();and need to pass it in instead.
Related
This Route below Does not work in my node.js server app API deployed in server for fetching image
app.use("/uploads/images", express.static(path.join("uploads", "images")));
On the other hand, the path below just working fine
app.use("/uploads", express.static('uploads'));
I don't know what I am doing wrong in I want the first one to categorize my images better.
In Case You want to take a look into my
App.js
const fs = require("fs"); //Node Built in file Sytem module
const path = require("path"); //Path Module built in
const mongoose = require("mongoose");
const express = require("express");
const placesRoutes = require("./routes/places-routes");
const usersRoutes = require("./routes/users-routes");
const bodyParse = require("body-parser");
const HttpError = require("./Models/http-error");
const { application } = require("express");
// All the Imports Above
const app = express();
// Using Middleware
app.use(bodyParse.json());
app.use("/uploads", express.static('uploads'));
app.use("/uploads/images", express.static(path.join("uploads", "images")));
//Middleware for Handling CORS Error in Frontend
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Orgin, X-Requested-With, Content-Type, Accept, Authorization"
);
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE");
next();
});
// Using Route attaching Middleware
app.use("/api/places", placesRoutes);
app.use("/api/users", usersRoutes);
app.use((req, res, next) => {
const err = new HttpError("This Route does not exist ", 404);
throw err;
});
app.use((error, req, res, next) => {
if (req.file) {
fs.unlink(req.file.path, (err) => {
console.log(err);
});
}
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500);
res.json({ message: error.message || "An unknown error occupied !" });
});
mongoose
.connect(
`${process.env.DB_URL}`
)
.then(() => {
console.log("Database Connected");
app.listen();
})
.catch((error) => {
console.log(error);
});
You need to use __dirname prefix. Instead of this:
app.use("/uploads/images", express.static(path.join("uploads", "images")));
Try this:
app.use(
"/uploads/images",
express.static(path.join(__dirname, "uploads", "images"))
);
See my cat example image:
https://codesandbox.io/p/sandbox/node-js-express-static-path-fn8l16
*EDIT 1
Express documentation mentions this:
However, the path that you provide to the express.static function is relative to the directory from where you launch your node process. If you run the express app from another directory, it’s safer to use the absolute path of the directory that you want to serve:
const path = require('path')
app.use('/static', express.static(path.join(__dirname, 'public')))
here is my main.js file
import express from 'express';
// route file are import here
import router from "./user-route/admin-route.js";
// **************** global variable are define here
const app = express();
const port = 5000;
app.use(express.json());
app.use(("./user-route/admin-route.js"));
/// ***************** routing are created are here
app.get("/", (req, res) => {
res.send("Hello from the server");
});
// ****************** server is created here
app.listen(port, () => {
console.log("Server is Ready and Running on Port 5000");
});
and here is my external routing file
import express from 'express';
const router = express.Router();
const admin = (req, res, next) => {
res.send("Hlo from the dashboard");
}
/// admin routers are defined here
router.route("/admin").get(admin);
export default router;
how I can connect the external routing with main.js file. here I am using the module method.
if i try with require method than it's work properly. i am not sure but i think problem is here
app.use(("./user-route/admin-route.js"));
Yes, this is the issue:
app.use(("./user-route/admin-route.js"));
You can't pass a filename to app.use() and expect it to work (in fact, it throws an error).
But you were close:
app.use(router);
I think what your looking for is something similar to this? What you're missing really is the app.use routing part, there are two parameters for that.
app.use('/admin', AdminRouter);
Main.js file
import express from 'express';
// route file are import here
const AdminRouter = require('./user-route/admin-route.js')
// **************** global variable are define here
const app = express();
const port = 5000;
app.use(express.json());
/// ***************** routing are created are here
app.get("/", (req, res) => {
res.send("Hello from the server");
});
app.use('/admin', AdminRouter);
// ****************** server is created here
app.listen(port, () => {
console.log("Server is Ready and Running on Port 5000");
});
external routing file
const express = require('express');
const router = express.Router();
/// admin routers are defined here
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
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
I currently have an API setup like so...
index.js
require('dotenv').config();
const index = require('./server');
const port = process.env.PORT || 5000;
index.listen(port, () => console.log(`Server is live at localhost:${port}`));
module.exports = index;
server/index.js
const express = require('express');
const routes = require('../routes');
const bodyParser = require('body-parser');
const helmet = require('helmet');
const morgan = require('morgan');
const path = require('path');
const server = express();
server.use(express.json());
// enhance your server security with Helmet
server.use(helmet());
// use bodyParser to parse server application/json content-type
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({ extended: true }));
// log HTTP requests
server.use(morgan('combined'));
server.use(express.static(path.normalize(__dirname+'/public')));
server.use('/api', routes);
// Handle 404
server.use(function(req, res) {
res.send('404: Page not Found', 404);
});
// Handle 500
server.use(function(error, req, res, next) {
res.send('500: Internal Server Error', 500);
});
module.exports = server;
routes/index.js
const router = Router();
// enable all CORS requests
router.use(cors());
router.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
router.get('/', (req, res) => res.send('Welcome to Timelapse Videos API'));
....
For some reason my public directory always returns 404 and i don't know why. If i add this to the routes/index.js :
router.get('/public', function(req, res) {
res.sendFile(path.join(path.normalize(__dirname+'/../public'), 'index.html'));
});
It will return the static file but the issue is, there could be number of customer directories that have multiple images i want to return.
There is clearly an issue with my setup but i can for the life of me see whats going on. If i have an API all in an index.js and not split the router it seems to work.
Any help would fantastic and if you need more information please ask.
Try change this line:
server.use(express.static(path.normalize(__dirname+'/public')));
For:
server.use(express.static(__dirname + '/public'));
or
server.use(express.static('public'));
From your code, it appears the 'public' folder is at the root.
Just change
server.use(express.static(path.normalize(__dirname+'/public')));
to
server.use(express.static(path.normalize(__dirname+'./../public')));
OK, i'm not sure if i found the issue but i found a work around.
On the file server/index.js:
server/index.js
server.use(express.static(path.normalize(__dirname+'/public')));
server.use('/api', routes);
If changed the top line to:
server.use('/api', express.static(path.normalize(__dirname+'/public')));
server.use('/api', routes);
The below line is overriding the top line (I think, it wasn't working so thats my thought process).
Now if change it to this:
server.use('/api/media', express.static(path.normalize(__dirname+'/public')));
server.use('/api', routes);
Works perfectly.
Hope this helps someone else as i spent a whole day on this lol.
I'm having some trouble accessing request parameters in express router.
My server.js file has this:
app.use('/user/:id/profile', require('./routes/profile');
And this is in my ./routes/profile.js file:
router.get('/', (req, res) => {
console.log(req.params.id);
}
But the console log prints undefined.
I'm new to express and feel like I'm missing something basic about how routing works.
Can someone please help me out?
Here is my full server.js:
const express = require('express');
const app = express();
app.use(express.json());
app.use('/user/:id/profile', require('./routes/profile'));
app.listen(5000, () => console.log('Listening'));
Here is my full profile.js:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
console.log(req.params.id);
res.status(200).send('In profile route');
});
module.exports = router;
URL parameters are not exposed to routers. You have a couple of options here:
Parse req.originalUrl to get the user id (not recommended). req.originalUrl isn't affected by the router's mount point and will remain as /user/112/profile or whatever url you visited.
Add some middleware to expose the id (recommended). Your new route statement will end up looking like this:
(Now you can use req.userId in your profile.js)
app.use('/user/:id/profile', function(req, res, next) {
req.userId = req.params.id;
next();
}, require('./routes/profile'));
Change the mount point from /user/:id/profile to /user, then edit your router to listen on /:id/profile (not recommended).