Simple test route is not responding to simple Postman request - express

I tried to create the simplest test route to test on my localhost as follows.
Verified localhost:3000 is up. Wrote a simple test file.
const express = require('express');
const router = express.Router();
router.route('/test').get((req, res) => {
console.log('route found');
});
module.exports = router;
My routes are split up as follows in my index routing file in the routes directory.
module.exports.api = require('./api');
module.exports.auth = require('./auth');
module.exports.root = require('./root');
module.exports.articles = require('./articles');
module.exports.test = require('./test');
I use the route as follows in my index.js for the server:
const routes = require(__dirname + '/routes');
app.use('/test', routes.test);
Tested it using Postman.
Sent request to localhost:3000/test/test.
No response. How can I troubleshoot further?

You are not getting any response because you are not sending any response from the server. You need to send some response back otherwise the client will keep waiting for the response until request times out.
router.route('/test').get((req, res) => {
res.send('route not found');
});
Edit
app.use('/test', routes.test); won't work with the way your route is defined. For it to work, request url should be /test/test. If you want request url to be just /test, change
app.use('/test', routes.test);
to
app.use(routes.test);

Here's a working version of what you want to do
const express = require('express');
const router = express.Router();
router.get('/test', (req, res) => {
res.send("hey");
console.log('route found');
});
module.exports = router;
Now in your main module, you need to check that you're listening to the right port, and that your express app is actually using the exported router!
const express = require('express');
const app = express();
const router = require('path/to/router/module');
app.use(router)
app.listen(8080, () => console.log("listening to port 8080"));
EDIT:
You mentioned that
My routes are split up as follows in my index routing file in the routes directory.
And, I can see that in the main module, you are requiring the directory itself, and not the routes module
const routes = require(__dirname + '/routes');
while what you should require is a module and not a directory!
const routes = require(__dirname + '/routes/yourRouteModuleName');
The solution I just gave assumes the following project's structure:
├── index.js
├── routes
│ ├── test.js
│ ├── routeModuleOrWhatever.js
│

Related

VueJS 3 project: "Cannot get" message with all paths but root

I have been trying for the past hour and a half to debug a project of mine.
The project works fine locally. Routes are systematically not working remotely except for one, the root of the project. I get a Cannot GET message in the browser elsewhere (all other paths).
From what I understand from my readings, this might have something to do with vue-router and might be caused by the server.js file I created in the root folder. The problem might have to do with the fact that my routes are dynamic.
const express = require('express');
const serveStatic = require("serve-static")
const path = require('path');
app = express();
app.use(serveStatic(path.join(__dirname, 'dist')));
const port = process.env.PORT || 3000;
app.listen(port);
This might also be caused by the fact I did not create the project with the history mode (although I'm pretty sure I did). I understand that I might have to go to my webpack config file to solve this, but I don't think I have one.
EDIT: By the way, my VueJS application is just a front-end to the PokéAPI back-end. I didn't build the back-end myself.
Simply creating the project with history mode is not enough. Your browser is trying sending text/html GET requests to the path you navigate to. But your app is a single page application which only has one index.html in /public, so you get 404 errors. Its in the vue-router docs:
To fix the issue, all you need to do is add a simple catch-all fallback route to your server. If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in.
For Node.js+express setup, you can use connect-history-api-fallback package.
npm install --save connect-history-api-fallback
Then change your server.js file to this:
const express = require('express');
var history = require('connect-history-api-fallback');
const serveStatic = require("serve-static")
const path = require('path');
app = express();
app.use(history());
app.use(serveStatic(path.join(__dirname, 'dist')));
const port = process.env.PORT || 3000;
app.listen(port);
In case you don't want to use third-party package you might be able to simply do this:
const express = require('express');
const serveStatic = require("serve-static")
const path = require('path');
app = express();
app.use(serveStatic(path.join(__dirname, 'dist')));
app.get(/.*/, function (req, res) {
res.sendFile(__dirname + "/dist/index.html");
});
const port = process.env.PORT || 3000;
app.listen(port);
But I'd recommend using the package as it handles some edge-cases

Express middleware, changes to request object do not persist

I am trying to implement some middleware in Express that should be called for all routes. This middleware should alter the request object.
I've tried several things already but seem to keep having the same issue. Soon as the middleware is left it looks like the request object is changed back to it's original state.
Currently my code resembles (I simplified it with a minimalistic example):
route.js:
const express = require('express');
const router = express.Router();
router.get('/getMe', (req, res) => {
// return the desired data.
// I expect req.params.myString to exist here but it does not.
});
module.exports = router;
index.js:
const express = require('express');
const router = express.Router();
router.use('/', require('./route'));
module.exports = router;
app.js:
const express = require('express');
const app = express();
const routes = require('./index');
app.use((req, res, next) => {
// Adding req.params.myString to the request object.
if (req.params.myString === undefined) req.params.myString = 'hello world';
next();
});
app.use('/api', routes);
As you can see I left out some of the code to keep it more readable. This is the code that gets the response and sets up the server.
Again, I am expecting that req.params.myString becomes available in the endpoint. Does anyone see what I am doing wrong?
In express docs ( http://expressjs.com/en/api.html#req.params ) it says:
If you need to make changes to a key in req.params, use the app.param
handler. Changes are applicable only to parameters already defined in
the route path.
So you need to check app.param handler.
http://expressjs.com/en/4x/api.html#app.param
You should app.set("myString", "hello World") inside your app.js and then you can access the field in your route.js/index.js scripts by using req.app.get("myString"). Or this should work too, set it like app.myString = "Hello world" and access it like req.app.myString.

Express: serve static files on subroute

I'm trying to get routing work using Express and create-react-app.
My goal is to address the user to the homepage of the application when the URL is / and to the login page when the URL matches /login.
In my server.js I have two routes defined:
var mainRoutes = require("./routes/mainRoutes");
var apiRoutes = require("./routes/apiRoutes");
[...]
app.use("/", mainRoutes);
app.use("/api", apiRoutes);
While apiRoutes contains all the api routing definitions, mainRoutes is responsible for the main navigation (at least this was the idea):
var express = require("express");
var path = require("path");
let router = express.Router();
router.route("/").get((req, res, next) => {
res.sendFile("index.html", { root: "./client/build/" });
});
router.route("/login").get((req, res, next) => {
res.send("This is the login page");
});
module.exports = router;
Somewhere I read about serving the static asset generated by the building process of create-react-app so I added:
// Priority serve any static files.
app.use(express.static(path.join(__dirname, "client/build")));
// All remaining requests return the React app, so it can handle routing.
app.get("*", function(req, res) {
res.sendFile(path.join(__dirname + "/client/build/index.html"));
});
Adding these lines, I successfully see my index.html but I can't visit both /login and /apisubroutes since it redirect me on the main page (index.html) each time.
It's like I need to serve the static files on my subroute mainRoutes but I don't have an idea on how to do that.
How can I make this work?
app.get('*') would match every single route that you have.
You should do something like this:
var mainRoutes = require("./routes/mainRoutes");
var apiRoutes = require("./routes/apiRoutes");
[...]
app.use(express.static(path.join(__dirname, "client/build")));
app.use("/", mainRoutes);
app.use("/api", apiRoutes);
// If the app reaches this point, it means that
// the path did not match any of the ones above
app.use(function(req, res, next){
// redirect the user to where we serve the index.html
res.redirect('/');
});
create-react-app I believe handles routing different, you cannot hook up the browser's route to the route you want to serve because you're running a single page application", unless you do universal routing with server and the js bundle

Why is router.post(..) not see and router.get(...) works fine?

I have a large express app that I have moved to node 7 and transforming the front end using Angular 2.
All seems to be working, except.... the router.post(...) calls.
All the router.get(...) routes work correctly. BUT the router.post(...) routes all respond with 404's.
A sample of the routing is as follows:
<routes.js>
'use strict';
import errors from './components/errors';
import path from 'path';
export default function(app) {
// Insert routes below
app.use('/api/logins', require('./api/login'));
app.use('/api/users', require('./api/user'));
app.use('/api/version', require('./api/version'));
...
app.use('/auth', require('./auth'));
// All undefined asset or api routes should return a 404
app.route('/:url(api|auth|components|app|bower_components|assets)/*')
.get(errors[404]);
// All other routes should redirect to the index.html
app.route('/*')
.get((req, res) => {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
}
and for example for
'use strict';
let express = require('express');
let router = express.Router();
let controller = require('./user.controller');
let auth = require('../../auth/auth.service');
router.post('/', auth.hasRole('admin'), controller.create);
router.get('/', auth.hasRole('admin'), controller.index);
router.get('/clean', auth.hasRole('admin'), controller.cleanDatabase);
router.get('/user/:sharingFromUserId', auth.isAuthenticated(), controller.getUserSharingFromUser);
....
Yet when I do post I see:
POST http://localhost:9000/users/ 404 (Not Found)
One strange hint in Intellij, suggests that the route.post() is not the correct function???? In the editor, the IDE seems to imply that this is the AuthHttp.post() function which is being used in the webpack section of the frontend. How can this be???

Rendering anchor links in Express

I have an issue with relative links in express. They appear to be working up to two levels deep and then they stop.
I'll attempt to illustrate the issue I am having.
Viewing page # http://example.com -> click anchor with href="level-1". This works as expected and links to http://example.com/level-1.
Viewing page # http://example.com/level-1 -> click anchor with href="level-2".
This works as expected and links to http://example.com/level-1/level-2.
Viewing page # http://example.com/level-1/level-2 -> click anchor with href="level-3". This does NOT work as expected and links to http://example.com/level-1/level-3.
I can access http://example.com/level-1/level-2/level-3 using href="level-2/level-3"
I thought it might be the way my routes are organised but no matter what I do to them the behaviour seems to be the same.
Currently I have something like
main.js
...
var app = express();
var routes = require('./router')(app);
router/index.js
module.exports = function(app) {
app.use('/level-1', require('./routes/level-1'));
app.use('/', require('./routes/home'));
};
router/routes/level-1.js
var express = require('express');
var router = express.Router();
router.use('/level-2', require('./level-2'));
router.get('/', function(req, res) {
res.render('level-1');
});
module.exports = router;
router/routes/level-2.js
var express = require('express');
var router = express.Router();
router.use('/level-3', require('./level-3'));
router.get('/', function(req, res) {
res.render('level-2');
});
module.exports = router;
router/routes/level-3.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('level-3');
});
module.exports = router;
Hopefully I have provided enough information.
I figured out the answer to my problem. I had to add the trailing / to anchor links leading to the problem pages.
What threw me, and the reason it was working up to one level deep, was that the first level of pages is accessible from a navigation bar and that links to them all in the style of href="/level-1/", the links from then on are generated and weren't generating with the trailing forward slash so href="level-2".