Related
For router.use, it does not work like this anymore:
router.use("/api", apiRoutes);
Instead an error is thrown:
throw new typeerror('router.use() requires a middleware function but got a ' + gettype(fn))
How do I re-purpose that expression so that it works? I have not found any examples that were useful so far. Here is some of my sample code:
routes/index.js (this does not work)
const path = require("path");
const router = require("express").Router();
const apiRoutes = require("./api");
// API Routes
router.use("/api", apiRoutes);**// this throws an error**
router.use(function(req, res) {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
module.exports = router;
Here is an example of my attempt to re-purpose but I do not think it's correct:
var path = require("path");
var router = require("express").Router();
var apiRoutes = require("./api");
//API Routes
//authRouter.use(require('./authenticate').basic(usersdb))
//router.use("./api", apiRoutes);
console.log("Hitting API routes...")
router.use("./api", function(req, res, next) { **//re-purpsose attempt here**
res.send(apiRoutes)
console.log("API Routes:", apiRoutes)
next()
});
console.log("API Routes hit")
// //If no API routes are hit, send the React app
// router.use(function(req, res) {
// res.sendFile(path.join(__dirname, "../client/public/index.html"));
// });
module.exports = router
This is the overall error I'm getting (404 returned):
GET /api/website_1_function_call/scrape 404 4.004 ms - 173
I know that this may be due to something else indirectly but I really am not sure about the router.use part.
I know for sure that the routes are not being hit properly and would like to fix.
Any advice would be appreciated. Thank you in advance.
Here is more code:
server.js
require("dotenv").config();
var express = require("express");
var cors = require('cors');
var bodyParser = require('body-parser');
var logger = require("morgan");
//const mongoose = require("mongoose");
var db = require("./models")
var routes = require("./routes");
var app = express();
var PORT = process.env.PORT || 3001;
var path = require('path');
//Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(bodyParser.json());
//Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === 'production') {
app.use(express.static("client/build"));
}
app.use(cors());
app.use(logger("dev"));
//Add routes, both API and view
app.use(routes);
//replaced with below:
//app.use(app.router);
//routes.initialize(app);
// //Connect to the Mongo DB
// mongoose.connect(process.env.MONGODB_URI || "mongodb://localhost/kaibru");
var syncOptions = { force: false };
// If running a test, set syncOptions.force to true
// clearing the `testdb`
if (process.env.NODE_ENV === "test") {
syncOptions.force = true;
};
// Starting the server, syncing our models ------------------------------------/
db.sequelize.sync(syncOptions).then(function() {
app.listen(PORT, function() {
console.log(
"==> π Listening on port %s. Visit http://localhost:%s/ in your browser.",
PORT,
PORT
);
});
});
// //Start the API server
// app.listen(PORT, function() {
// console.log(`π ==> API Server now listening on PORT ${PORT}!`);
// });
routes/index.js
var path = require("path");
var router = require("express").Router();
var apiRoutes = require("./api");
//API Routes
//authRouter.use(require('./authenticate').basic(usersdb))
//router.use("/api", apiRoutes);
console.log("Hitting API routes...")
router.use("/api", function(req, res, next) { // this is my re-purpose
attempt
apiRoutes
console.log("API Routes:", apiRoutes)
// next()
}); // this is my r-purpose attempt
console.log("API Routes hit")
// //If no API routes are hit, send the React app
// router.use(function(req, res) {
// res.sendFile(path.join(__dirname, "../client/public/index.html"));
// });
module.exports = router
routes/api/index.js
var router = require("express").Router();
require("./website_1");
var website_1Routes = require("./website_1_function_call");
//const userRoutes = require("./user");
//Website_1 routes
//http://localhost:3000/api/website_1_function_call/scrape
//authRouter.use(require('./authenticate').basic(usersdb))
//router.use("/website_1_function_call", website_1Routes);
//experimental use
router.use("/website_1_function_call", function(req, res, next) { // this is my re-purpose attempt
website_1Routes
console.log("website_1Routes:", website_1Routes)
// next()
}); //this is my re-purpose attempt
//router.use("/user", userRoutes);
module.exports = router
routes/api/website_1_function_call.js
require("./website_1");
require("./website_1_db");
require("./website_1_router");
//Call scrape functions from website_1 file
mainscrape();
//specificScrape() //let's leave this one dormant for now
//Now for saving to database
saveToDatabase();
//Now for the routes
routing();
I think my re-purpose attempt worked ( I removed next() since there are no defined routes right after). It seems to be processing. However, now my response hangs and this happens:
GET /api/website_1_function_call/scrape - - ms - -
This prints in the browser console:
GET http://localhost:3000/api/website_1_function_call/scrape
net::ERR_EMPTY_RESPONSE
0.chunk.js:871 Uncaught (in promise) Error: Network Error
at createError (0.chunk.js:871)
at XMLHttpRequest.handleError (0.chunk.js:366)
So now I think my scraper code and my code to update the database does not work.
Scrape function code:
//var express = require("express");
var router = require("express").Router();
require("../../controllers/website_1controller");
//requiring this website's models
var Items_1 = require("../../models/website_1");
//require("./website_1_db");
//require("./website_1_router");
// Our scraping tools
// Axios is a promised-based http library, similar to jQuery's Ajax method
// It works on the client and on the server
var axios = require("axios");
var cheerio = require("cheerio");
mainscrape = function() {
//Now to configure the routes
router.get("/scrape", function(req, res) {
//instead of simple res.render, user router.get
console.log("scraping started...");
//Grab the html body with axios
axios.get("url placeholder").then(function(response) {
//Load to cheerio and save to $ selector
console.log("Scraping all greenheartshop mainpage...");
var $ = cheerio.load(response.data);
var output = [];
var promises = [];
//Now we need to grab the title reference for each article
$("article").each(function(i, element) {
//save empty result object
var result = {};
//thumbnail
result.thumbnail = $(this)
//.children("article.product-grid-item.product-block").html()
.children("figure.product-item-thumbnail")
.children("a")
.attr("href")
//console.log("result thumbnail")
//console.log(result)
console.log(result.thumbnail)
var result = {}
//details
result.detail= $(this)
//.children("product-item-mask").html()
.children("div.product-item-details")
// .children("div.product-item-brand")
// .children("h5.product-item-title")
// .children("a")
// .children("div.product-item-price")
//.children("product-price-line")
//.children("price-value")
.text()
//result.detail = result.detail.trim();
//console.log("result detail")
//console.log(result)
console.log(result.detail)
//Capture the scraped data and save to database
console.log("Capturing Scrape")
if(result.detail !== '') {
var promise = Items_1
.saveToDatabase(result, result, {upsert:true, new:true})
console.log("saveToDatabase");
promises.push(promise);
}
Promise.all(promises).then((data) => {
res.json(data);
});
//saveToDatabase();
// if (result.thumbnail !== {} && result.detail !== "") {
// var promise = Items_1
// // .items_1_create({
// // resultThumbnail: result.thumbnail,
// // resultDetails: result.detail
// // })
// promises.push(promise)
// // .then(dbModel => output.push(dbModel));
// Promise.all(promises).then((data) => {
// res.json(data)
// })
// }
});
});
//Now to CREATE the results using controller file
// console.log("creating items in the database now...")
// router.post('/scrape', website_1Controller.items_1_create);
//Now to display the results
// console.log("Items now being displayed...")
// router.get('/scrape/display', website_1Controller.items_1_list)
});
}
module.exports = router;
module.exports = mainscrape;
module.exports = specificScrape;
Code to update the database:
require("../../controllers/website_1controller");
require("./website_1");
var Items_1 = require( "../../models");
//After scraping the main page, the following function is to save to the
database
saveToDatabase = function() {
//prepare the data
var result = {}
var dataToStore = Items_1.items_1_create
console.log(dataToStore)
//console.log(items_1_create)
//insert data to the database
// dataToStore.save().// We will not sue this part for now
// then(() => {
// console.log("Data successfully saved");
// }).catch(err => {
// console.log("Error: ", err);
// });
}
module.exports = saveToDatabase;
Code for final routing (after scrape is complete)
var website_1Controller = require("../../controllers/website_1controller");
var router = require("express").Router();
routing = function() {
//Now to CREATE the results using controller file
console.log("creating items in the database now...")
//router.route("/browse")
router.post('/browse', website_1Controller.items_1_create);
router.get('/browse', website_1Controller.items_1_list);
//Now to display the results
console.log("Items now being displayed...")
//router.route("/browse:search")
router.get('/:search', website_1Controller.items_1_specific);
};
require("./website_1");
module.exports = routing;
module.exports = router;
models
'use strict';
// Dependencies
// =============================================================
// Sequelize (capital) references the standard library
//var Sequelize = require("sequelize");
// sequelize (lowercase) references our connection to the DB.
//var sequelize = require("../config/connection.js");
// Creates a "Items_1" model that matches up with DB
module.exports = function(sequelize, DataTypes) {
var Items_1 = sequelize.define("Items_1", {
// the routeName gets saved as a string
detail: DataTypes.STRING,
// the name of the character (a string)
thumbnail: DataTypes.BLOB,
// the character's role (a string)
//role: Sequelize.STRING,
// the character's age (a string)
//age: Sequelize.INTEGER,
// and the character's force points (an int)
//forcePoints: Sequelize.INTEGER
}, {
// disable the modification of tablenames; By default, sequelize will
automatically
// transform all passed model names (first parameter of define) into
plural.
// if you don't want that, set the following
freezeTableName: true
});
return Items_1;
//Syncs with DB
//Items_1.sync();
// Makes the Items_1 Model available for other files (will also create a table)
};
controller
// *********************************************************************************
// website_1controllers.js - this file offers a set of routes for displaying and saving data to the db
// *********************************************************************************
// Dependencies
// =============================================================
var db = require("../models");
//display results for mainpage scrape
exports.items_1_create = function(req, res) {
db.Items_1.findOneAndUpdate(req.body, req.body, {upsert: true, new:
true})
.then(dbModel => res.json(dbModel))
.catch(err => res.status(422).json(err))
console.log("findOneAndUpdate complete")
},
exports.items_1_list = function(req,res) {
db.Items_1.findAll({})
},
exports.items_1_specific = function(req,res) {
db.Items_1.findById(req.params.search)
},
function(err, results) {
if (err) { return next(err); } //Error in API usage.
if (results.result.thumbnail==={} && results.result.detail==="") {//No
Results.
var err = new Error('Results not found');
err.status = 404;
return next(err)
}
//Successful, so render
res.render("click_results", { title: 'Click Results', resultThumbnail:
result.thumbnail, resultDetails: result.detail });
}
So the new issue is that the response hangs. I think it's because the code to update the database does not work (using sequelize). Let me know if anything else is needed and thank you in advance.
Thanks for all of the input everyone. After reviewing I found out that the function itself does not have to be re-purposed as I initially thought... I didn't know that if, for example, you are using "router.use("/directoy", directory) and you are using it in succession to point to different directories, the final directory hit must have a defined route like router.get(). I modularized my code to the point where the final directory was just a list of functions (one of these functions had the router.get method). This did not work. When I point the file directly to the code containing the router.get method, my scraped data returns to the terminal. Just thought I'd share my findings at least because I didn't know this at all . Many thanks to #mehta-rohan and #Anand Undavia for the insights. I'm still trying to get the data to render to the page but that's a different problem altogether.
I have one app hosted at the root and I would like to host this new app in a subdirectory /rps using proxypass etc. Everything is working fine except when I try to call my api I get 404 errors in routes for example https://myapp.com/rps/api/posts/. The front end app is basically static served from the public folder of express.
Open to any ideas what I may doing wrong or alternate methods. I'd really like not to have a new server for this small application and I can't really build it into the already existing app. Of course, the routes were working locally, just not when I host in my strange scenario on the server...
See code:
(server) index.js:
const config = require('./config.js');
const app = express()
const port = process.env.PORT || 5000;
var indexRouter = express.Router();
const posts = require('./routes/api/posts')
indexRouter.use('/api/posts', posts)
app.use(express.static(__dirname+ '/public'))
indexRouter.get(/.*/, (req, res) => res.sendFile(__dirname+'/public/index.html'))
app.use(config.baseUrl, indexRouter);
(server) config.js:
module.exports = {
baseUrl: '/rps/',
}
(server) ./routes/api/posts.js:
const router = express.Router()
router.post('/', (req, res) => {
//gets my thang in action...
})
module.exports = router
(client) main.js:
axios.post('/api/posts/', { // /rps/api/posts ??
stuff: things,
})
.then(function (response) {
// do something else
})
.catch(function (error) {
console.log(error);
})
Thank you in advance!
I'm creating an app using Node and Express. However, I can see it'll soon become difficult to manage all the routes that are placed inside app.js. I have placed all my models in a subdirectory /models.
Here's my app current structure:
app.js
models
-- products
-- customers
-- ...
public
views
node_modules
In app.js:
var express = require('express'),
routes = require('./routes'),
user = require('./routes/user'),
http = require('http'),
path = require('path'),
EmployeeProvider = require('./models/employeeprovider').EmployeeProvider,
Products = require('./models/products').Products,
Orders = require('./models/orders').Orders,
Customers = require('./models/customers').Customers,
checkAuth = function(req, res, next) {
if (!req.session.user_id) {
res.send('You are not authorized to view this page');
} else {
next();
}
};
var app = express();
Then some configuration like port, views directory, rendering engine, etc.
Further down app.js I've got the routes:
app.get('/product/edit', auth, function(req, res) {
Products.findAll(function(error, prds) {
res.render('product_edit', {
title: 'New Product',
products: prds
});
});
});
At the top I'm assigning the contents of models/products.js to a variable, all works fine. However keeping all routes inside app.js is not ideal. But if I move the routes to routes/product.js and load the Products models:
var prod = require('../models/products.js');
I get an error saying that object has no method findAll.
What am I doing wrong? How can I remove the routes from app.js?
As of express 4.x Router is added to support your case.
A router object is an isolated instance of middleware and routes. You can think of it as a βmini-application,β capable only of performing middleware and routing functions. Every Express application has a built-in app router.
Example from expressjs site:
// routes/calendarRouter.js
var express = require('express');
var router = express.Router();
// invoked for any requested passed to this router
router.use(function(req, res, next) {
// .. some logic here .. like any other middleware
next();
});
// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function(req, res, next) {
// ..
});
module.exports = router;
Then in app.js:
// skipping part that sets up app
var calendarRouter = require('./routes/calendarRouter');
// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', calendarRouter);
// rest of logic
Since I don't like repetition, here's what I do:
// app.js
//...
var routes = requireDir('./routes'); // https://www.npmjs.org/package/require-dir
for (var i in routes) app.use('/', routes[i]);
//...
And each file in routes is like:
// routes/someroute.js
var express = require('express');
var router = express.Router();
router.get('/someroute', function(req, res) {
res.render('someview', {});
});
module.exports = router;
This way you can avoid long repetitive lists like this one:
app.use('/' , require('./routes/index'));
app.use('/repetition' , require('./routes/repetition'));
app.use('/is' , require('./routes/is'));
app.use('/so' , require('./routes/so'));
app.use('/damn' , require('./routes/damn'));
app.use('/boring' , require('./routes/boring'));
Edit: these long examples assume each route file contains something like the following:
var router = express.Router();
router.get('/', function(req, res, next) {
// ...
next();
});
module.exports = router;
All of them could be mounted to "root", but what for them is "root", is actually a specific path given to app.use, because you can mount routes into specific paths (this also supports things like specifying the path with a regex, Express is quite neat in regards to what you can do with routing).
I can suggest you this file structure (according to Modular web applications with Node.js and Express from tjholowaychuk):
app.js
modules
users
index.js
model.js
users-api
index.js
static-pages
index.js
user-api and static-pages export expressjs applications, you can easily mount them in app.js.
In users module you can describe some Data Access operations and all methods about manipulating with the User entity (like create, update etc.). Our API module will use all these methods.
And here is sample code of app.js file (without common express stuff, only mounting routes from different modules):
var express = require('express');
var app = express();
// mount all the applications
app.use('/api/v1', require("user-api"));
app.use(require("static-pages"));
app.listen(3000);
To use your modules this way you must start your app like this NODE_PATH=modules node app.js (i put this line to package.json file in scripts section).
Here is sample code of users module:
index.js
User = require("./model");
module.exports = {
get: function(id, callback) {
User.findOne(id, function(err, user) {
callback(err, user);
});
},
create: function(data, callback) {
// do whatever with incoming data here
data = modifyDataInSomeWay(data);
var newUser = new User(data);
newUser.save(function(err, savedUser) {
// some logic here
callback(err, savedUser);
});
}
};
model.js (with Mongoose stuff for example of course!)
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = new Schema({
firstname : {type: String, required: false},
lastname : {type: String, required: false},
email : {type: String, required: true}
});
module.exports = mongoose.model('user', User);
And example of user-api module (here is the main part of the answer about separating routes and models).
var users = require("users");
var express = require("express");
var app = module.exports = express(); // we export new express app here!
app.post('/users', function(req, res, next) {
// try to use high-level calls here
// if you want something complex just create another special module for this
users.create(req.body, function(err, user) {
if(err) return next(err); // do something on error
res.json(user); // return user json if ok
});
});
And example of static-pages. If you are not going to build a kind of REST interface you may simply create several modules that will render pages only.
var express = require("express");
var app = module.exports = express(); // we export new express app here again!
app.get('/', function(req, res, next) {
res.render('index', {user: req.user});
});
app.get('/about', function(req, res, next) {
// get data somewhere and put it in the template
res.render('about', {data: data});
});
Of course you can do whatever you want with modules. The main idea about expressjs is to use a lot of small apps instead of single one.
About nodejs modules you can read stackoverflow and docs.
Hope this helps.
I am getting my hands on node.js and I am trying to understand the whole require/exports thing. I have the following main app.js file:
/app.js
var express = require('express'),
http = require('http'),
redis = require('redis'),
routes = require('./routes'),
var app = express(),
client = redis.createClient();
// some more stuff here...
// and my routes
app.get('/', routes.index);
then, I have the routes file:
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
I can of course use the client object on my app.js file, but how can I use the same object in my routes?
Since req and res are already being passed around by Express, you can attach client to one or both in a custom middleware:
app.use(function (req, res, next) {
req.client = res.client = client;
next();
});
Note that order does matter with middleware, so this will need to be before app.use(app.router);.
But, then you can access the client within any route handlers:
exports.index = function(req, res){
req.client.get(..., function (err, ...) {
res.render('index', { title: 'Express' });
});
};
The easiest way is to export a function from your routes file that takes a client, and returns an object with your routes:
exports = module.exports = function (client) {
return {
index: function (req, res) {
// use client here, as needed
res.render('index', { title: 'Express' });
}
};
};
Then from app.js:
var client = redis.createClient(),
routes = require('./routes')(client);
This question already has answers here:
How to separate routes on Node.js and Express 4?
(9 answers)
Closed 1 year ago.
In my NodeJS express application I have app.js that has a few common routes. Then in a wf.js file I would like to define a few more routes.
How can I get app.js to recognize other route handlers defined in wf.js file?
A simple require does not seem to work.
If you want to put the routes in a separate file, for example routes.js, you can create the routes.js file in this way:
module.exports = function(app){
app.get('/login', function(req, res){
res.render('login', {
title: 'Express Login'
});
});
//other routes..
}
And then you can require it from app.js passing the app object in this way:
require('./routes')(app);
Have a look at these examples: https://github.com/visionmedia/express/tree/master/examples/route-separation
In Express 4.x you can get an instance of the router object and import another file that contains more routes. You can even do this recursively so your routes import other routes allowing you to create easy-to-maintain URL paths.
For example, if I have a separate route file for my /tests endpoint already and want to add a new set of routes for /tests/automated I may want to break these /automated routes out into a another file to keep my /test file small and easy to manage. It also lets you logically group routes together by URL path which can be really convenient.
Contents of ./app.js:
var express = require('express'),
app = express();
var testRoutes = require('./routes/tests');
// Import my test routes into the path '/test'
app.use('/tests', testRoutes);
Contents of ./routes/tests.js:
var express = require('express'),
router = express.Router();
var automatedRoutes = require('./testRoutes/automated');
router
// Add a binding to handle '/tests'
.get('/', function(){
// render the /tests view
})
// Import my automated routes into the path '/tests/automated'
// This works because we're already within the '/tests' route
// so we're simply appending more routes to the '/tests' endpoint
.use('/automated', automatedRoutes);
module.exports = router;
Contents of ./routes/testRoutes/automated.js:
var express = require('express'),
router = express.Router();
router
// Add a binding for '/tests/automated/'
.get('/', function(){
// render the /tests/automated view
})
module.exports = router;
Building on #ShadowCloud 's example I was able to dynamically include all routes in a sub directory.
routes/index.js
var fs = require('fs');
module.exports = function(app){
fs.readdirSync(__dirname).forEach(function(file) {
if (file == "index.js") return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
Then placing route files in the routes directory like so:
routes/test1.js
module.exports = function(app){
app.get('/test1/', function(req, res){
//...
});
//other routes..
}
Repeating that for as many times as I needed and then finally in app.js placing
require('./routes')(app);
If you're using express-4.x with TypeScript and ES6, this would be the best template to use:
src/api/login.ts
import express, { Router, Request, Response } from "express";
const router: Router = express.Router();
// POST /user/signin
router.post('/signin', async (req: Request, res: Response) => {
try {
res.send('OK');
} catch (e) {
res.status(500).send(e.toString());
}
});
export default router;
src/app.ts
import express, { Request, Response } from "express";
import compression from "compression"; // compresses requests
import expressValidator from "express-validator";
import bodyParser from "body-parser";
import login from './api/login';
const app = express();
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.get('/public/hc', (req: Request, res: Response) => {
res.send('OK');
});
app.use('/user', login);
app.listen(8080, () => {
console.log("Press CTRL-C to stop\n");
});
Much cleaner than using var and module.exports.
Full recursive routing of all .js files inside /routes folder, put this in app.js.
// Initialize ALL routes including subfolders
var fs = require('fs');
var path = require('path');
function recursiveRoutes(folderName) {
fs.readdirSync(folderName).forEach(function(file) {
var fullName = path.join(folderName, file);
var stat = fs.lstatSync(fullName);
if (stat.isDirectory()) {
recursiveRoutes(fullName);
} else if (file.toLowerCase().indexOf('.js')) {
require('./' + fullName)(app);
console.log("require('" + fullName + "')");
}
});
}
recursiveRoutes('routes'); // Initialize it
in /routes you put whatevername.js and initialize your routes like this:
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('index', { title: 'index' });
});
app.get('/contactus', function(req, res) {
res.render('contactus', { title: 'contactus' });
});
}
And build yet more on the previous answer, this version of routes/index.js will ignore any files not ending in .js (and itself)
var fs = require('fs');
module.exports = function(app) {
fs.readdirSync(__dirname).forEach(function(file) {
if (file === "index.js" || file.substr(file.lastIndexOf('.') + 1) !== 'js')
return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
I am trying to update this answer with "express": "^4.16.3". This answer is similar to the one from ShortRound1911.
server.js:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const db = require('./src/config/db');
const routes = require('./src/routes');
const port = 3001;
const app = new express();
//...use body-parser
app.use(bodyParser.urlencoded({ extended: true }));
//...fire connection
mongoose.connect(db.url, (err, database) => {
if (err) return console.log(err);
//...fire the routes
app.use('/', routes);
app.listen(port, () => {
console.log('we are live on ' + port);
});
});
/src/routes/index.js:
const express = require('express');
const app = express();
const siswaRoute = require('./siswa_route');
app.get('/', (req, res) => {
res.json({item: 'Welcome ini separated page...'});
})
.use('/siswa', siswaRoute);
module.exports = app;
/src/routes/siswa_route.js:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({item: 'Siswa page...'});
});
module.exports = app;
If you want a separate .js file to better organize your routes, just create a variable in the app.js file pointing to its location in the filesystem:
var wf = require(./routes/wf);
then,
app.get('/wf', wf.foo );
where .foo is some function declared in your wf.js file. e.g
// wf.js file
exports.foo = function(req,res){
console.log(` request object is ${req}, response object is ${res} `);
}
One tweak to all of these answers:
var routes = fs.readdirSync('routes')
.filter(function(v){
return (/.js$/).test(v);
});
Just use a regex to filter via testing each file in the array. It is not recursive, but it will filter out folders that don't end in .js
I know this is an old question, but I was trying to figure out something like for myself and this is the place I ended up on, so I wanted to put my solution to a similar problem in case someone else has the same issues I'm having. There's a nice node module out there called consign that does a lot of the file system stuff that is seen here for you (ie - no readdirSync stuff). For example:
I have a restful API application I'm trying to build and I want to put all of the requests that go to '/api/*' to be authenticated and I want to store all of my routes that go in api into their own directory (let's just call it 'api'). In the main part of the app:
app.use('/api', [authenticationMiddlewareFunction], require('./routes/api'));
Inside of the routes directory, I have a directory called "api" and a file called api.js. In api.js, I simply have:
var express = require('express');
var router = express.Router();
var consign = require('consign');
// get all routes inside the api directory and attach them to the api router
// all of these routes should be behind authorization
consign({cwd: 'routes'})
.include('api')
.into(router);
module.exports = router;
Everything worked as expected. Hope this helps someone.
index.js
const express = require("express");
const app = express();
const http = require('http');
const server = http.createServer(app).listen(3000);
const router = (global.router = (express.Router()));
app.use('/books', require('./routes/books'))
app.use('/users', require('./routes/users'))
app.use(router);
routes/users.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'John Smith'})
}
module.exports = router
routes/books.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'Dreams from My Father by Barack Obama'})
}
module.exports = router
if you have your server running local (http://localhost:3000) then
// Users
curl --request GET 'localhost:3000/users' => {name: 'John Smith'}
// Books
curl --request GET 'localhost:3000/books' => {name: 'Dreams from My Father by Barack Obama'}
I wrote a small plugin for doing this! got sick of writing the same code over and over.
https://www.npmjs.com/package/js-file-req
Hope it helps.
you can put all route functions in other files(modules) , and link it to the main server file.
in the main express file, add a function that will link the module to the server:
function link_routes(app, route_collection){
route_collection['get'].forEach(route => app.get(route.path, route.func));
route_collection['post'].forEach(route => app.post(route.path, route.func));
route_collection['delete'].forEach(route => app.delete(route.path, route.func));
route_collection['put'].forEach(route => app.put(route.path, route.func));
}
and call that function for each route model:
link_routes(app, require('./login.js'))
in the module files(for example - login.js file), define the functions as usual:
const login_screen = (req, res) => {
res.sendFile(`${__dirname}/pages/login.html`);
};
const forgot_password = (req, res) => {
console.log('we will reset the password here')
}
and export it with the request method as a key and the value is an array of objects, each with path and function keys.
module.exports = {
get: [{path:'/',func:login_screen}, {...} ],
post: [{path:'/login:forgotPassword', func:forgot_password}]
};