react router and express GET conflict - javascript

I'm not able to figure out how react router and express route working together.
I have this
app.get('*', function(req, res) {
res.sendFile(path.resolve(__dirname) + '/server/static/index.html');
});
// routes
const apiRoutes = require('./server/routes/api');
app.use('/api', apiRoutes);
The problem is my api can't use GET because it will redirect to index.html. If I remove the wildcard route, then react-router would not be able to work properly.

Your app.get('*') statement will match any request coming in. You can fix your problem by changing the order of the statements:
// routes
const apiRoutes = require('./server/routes/api');
app.use('/api', apiRoutes);
app.get('*', function(req, res) {
res.sendFile(path.resolve(__dirname) + '/server/static/index.html');
});
This way, any requests whose path's start with /api will be handled by your apiRoutes router, all the others are handled by the asterisk.

Related

Specifying a specific route in an Express Router used with an array of routes

The Express docs are clear about the fact that you can supply app.use with an array of routes for a particular piece of middleware.
They also describe how to split routers into separate files here.
But I can't see how to combine these two approaches.
index.js
const authRoutes = require('./routes/auth');
app.use(['/api/register', '/api/login'], authRoutes);
./routes/auth
router.route('/')
.all((req, res) => res.send('responds to both routes'); // <- this works
router.route('/register') // <- But how can I specify a specific route?
.all((req, res) => {
res.send('The register route');
});
It seems like you are trying to do something like this
const authRoutes = require('./routes/auth');
app.use('/api', authRoutes);
router.route(['/register', '/login']) . // respond to both
.all((req, res) => res.send('responds to both routes');
router.route('/register') // this is /api/register
.all((req, res) => {
res.send('The register route');
});
router.route('/login') // this is /api/login
.all((req, res) => {
res.send('The login route');
});
However there is something wrong with this logic , because your single routes /register and /login in auth file will never be called when you pass /api/login or /api/register they will go through the first array route. If you put the first route to the bottom then the array route respond to both route will be never called since it either goes to first /register route or 2nd /login route.

Including seperate route files in node.js

I am developing an application and I have defined my custom routes in a different way. I am using Web Storm IDE to develop and it has a specific folder of routes where all the routes are kept individually. I have the following code in my directory /routes/about.js file:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('about', { title: 'About Us' });
});
module.exports = router;
Now in the app.js I have written the following code to include these route and use it:
var index = require('./routes/index');
var users = require('./routes/users');
var about = require('./routes/about');
app.use('/', index);
app.use('/users', users);
app.use('/about', about);
But when I click on about link, it does not open the page. Though, if I write the route in the app.js file directly as:
app.get('/about', function (req, res) {
res.render('about');
});
then it renders the page. Also, if I do not make separate routes and use the default routes file (/routes/index.js) and include this in that file, then also the code works fine. Can anyone explain or tell is there any mapping of these route files done which is missed by me, or I am doing something syntactically wrong
You probably created a route for /about/about. To fix, change the about router from this:
router.get('/about', ...);
to this:
router.get('/', ...);
This, then goes with:
app.use('/about', router);
which already includes the /about path. Everything in that router will already have /about at the beginning of the path.
Use below code in about file
app.get('/', function (req, res) {
res.render('about');
});
You have already defined '/about' route in main file so if you want to render page on '/about' so you need to define route like this '/' in about page.
For example route '/about/us' then function will be in about page :
app.get('/us', function (req, res) {
res.render('about us');
});
The method to redirect the route is correct, but you have not pass the route to app.
so you just need to do is ,
router.use('/about', about);
app.use('/', router);
Like wise add router in app

Correct format for Node architecture (BASIC)

Introduction
I have built some back end functionality in Node (First time using Node). Problem is that the whole thing was built in one page (index.js) so now im following a few basic tutorials and setting out express router middleware and now trying to follow a modular MVC approach,
This code is simple but brakes when I separate into two pages Server.js and config.js. I know its a simple problem but i cant spot it. can someone help spot the problem and maybe improve the structure ?
Problem
I go to http://localhost:8080/about or a different route and I get
Cannot GET /about
rather than the correct print out.
back-end/server.js
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
// get an instance of router
var router = express.Router();
// START THE SERVER
// ==============================================
app.listen(port);
console.log('Server has started!! ' + port);
back-end/config.js
router.use(function(req, res, next) {
console.log(req.method, req.url);
next();
});
router.get('/', function(req, res) {
res.send('im the home page!');
});
// sample route with a route the way we're used to seeing it
router.get('/sample', function(req, res) {
res.send('this is a sample!');
});
router.get('/about', function(req, res) {
res.send('im the about page!');
});
app.route('/login')
.get(function(req, res) {
res.send('this is the login form');
})
.post(function(req, res) {
console.log('processing'); // shows on console when post is made
res.send('processing the login form!'); // output on postman
});
app.use('/', router);
As #SLaks said in his comment, you need to import (require) your backend/config.js file. But it's not as simple as that...
In node, variables are scoped to the file in which they appear, so if you simply add require('./config') to your server.js file, that's not going to work either, because the router variable in config.js is local to that file - it's not going to know about the router variable in server.js.
The solution to this is to have the config.js file export a function which the server.js file can use to configure stuff. For example
config.js
module.exports = function(router) {
// set up your router here with router.use, etc.
};
server.js
var configure = require('./config');
// after you set up your express router...
configure(router);
// now start listening

Multiple level of routing using Express.js with Node.js

I'm new to javascript. I'm trying to make a RESTfull API using Node.js and Express.js
My directory structure is as follows
/server.js
/api/api.js
/api/location/location.js
I want to make the API modular. I want that all the requests (get/post/delete/push) beginning with /api/* to be handled by api.js and whatever routing be required, api.js should route it to proper module.
For example, if someone requests GET /api/location/abc/xyz then api.js will transfer control to location.js which will then transfer to abc.js which will finally transfer to xyz.js stored in directory /api/location/abc/xyz/xyz.js
How can I achieve this?
Code so far:
/server.js
var express = require('express');
var app = express();
var api = require('./api/api.js');
var location = require('./api/location/location.js');
//app.use('/api/location', location); //This works, but I want api.js to handle sub-routes!
app.use('/api', api);
app.get('/', function(req, res){
res.end('successful get/');
});
app.listen(12345);
/api/api.js
module.exports = function(req, res, next) {
res.end('successful get /api');
next();
};
//Add code to handle GET /api/location
/api/location/location.js
module.exports = function(req, res, next){
res.end('from location!');
next();
}
You would use express.Router([options]).
And write it that way:
/api/api.js
var router = require('express').Router();
router.get('/location', require('./api/location') );
module.exports = router;
/api/api/location.js
module.exports = function(req, res, next){
res.end('from location!');
}
And don't call next(); if you ended the response. You only call next() in your callback if you don't handle the response.
I don't know how complex your REST api will be later. But try to to keep the routing in a small number of file. Having a callback for the routing in an own file like /api/api/location.js is most likely not the best idea.

app.get is not working for base route

I am an absolutely newby in node.js and I try to create a new project via this technology. I use express framework but on the start I have a little trouble. I have solved this trouble with workaround but I have a question for next behavior:
My app.js
var express = require('express')
, routes = require('./routes/index')
, routes = require('./routes/login');
var app = module.exports = express.createServer();
console.log(app.env);
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.use( function(req, res, next) {
if (req.url == '/') {
res.render('index', { title: 'Express!' })
} else {
next();
}
});
//app.get('/', routes.index);
app.get('/login', routes.login);
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
In a block // Routes you can see app.use and app.get. If I try to use app.get instead of app.use I get error "cannot get /". I tried to put index.html file to my public folder. But fot "/" route I everytime got this file, not render of index.js.
app.get('/login', routes.login); - is work fine, but something wrong with "/" route. I dont want to leave my code in this state, please, help me understand this behavior.
Thank in advance.
Like the user PA. mentioned, the reason your code never finds the / url, is because you are redeclaring your routes variable:
var express = require('express')
, routes = require('./routes/index') // first declaration of 'routes'
, routes = require('./routes/login'); // re-declaration of 'routes'
This makes your first routes declaration (the declaration that was pointing to /index) unreachable by your code, which is why you get the error "cannot get /", because your routes variable only points to ./routes/login.
There are a few ways you can fix this to clean up your code:
1. Assign different variables for the different routes:
var express = require('express')
, index = require('./routes/index')
, login = require('./routes/login');
- 0R -
2. Put multiple functions in the routes file:
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
// in your routes/index file
exports.index = function(req, res){
res.render('index', { title: 'Index Page' });
};
exports.login = function(req, res){
res.render('login', { title: 'Login Page' });
};
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
// in your app.js file
// import your 'routes' functions from your 'routes' file
var express = require('express')
, routes = require('./routes/')
// now use your routes functions like this:
app.get('/', routes.index);
app.get('/login', routes.login);
- OR -
In a large application, or for better code maintainability, you may want to break up your different routing functions into different files (instead of putting all your routing functions in one file, like the example above), so using the express default setup as an example, they are placing their user functions and their index functions in the routes folder this like:
routes /
user.js
index.js
Then, they setup their application like this:
var routes = require('./routes');
var user = require('./routes/user');
And call these functions like this:
app.get('/', routes.index); // calls the "index" function inside the routes/index.js
app.get('/users', user.list); // calls the "list" function inside the routes/user.js file
Hope this helps.
Quick tip: app.use() is used to create middleware, which is a function that will get called on each request in your application, giving you, the developer, access to the request object req, and the response object res, and the power to change, or enhance your application somehow. The ability to "act in the middle of a request" is a powerful feature, and the reason why it was working for you in your original example is because your app.use() middleware was getting called when the request for / was being called, even though your app couldn't find /, which was lost when you re-declared the routes variable, you were still making a request to /, which your app.use() was able to see (because middleware gets called on EVERY request, even the "bad" ones), so your middleware was still seeing the [invalid] request to / and acting like this:
// This middleware will get called on every request,
// even on the invalid request for '/'
app.use( function(req, res, next) {
// this line of code will see that the
// request is for "/" and fire
if (req.url == '/') {
// the page now appears to render, because you are forcing the
// res.render code inside of your middleware, which isn't always
// recommended, but it is working for you in this example
// because its the only place in your example that can do anything
// when the '/' request is made
res.render('index', { title: 'Express!' })
} else {
// this is common middleware design pattern, the next()
// function tells the express framework to "move on to the next function"
// in the middleware stack
next();
}
});

Categories

Resources