Express route does not match without wildcard - node.js

I am using express 3. I have a GET route in my code which does not match if I do not place a * wildcard at the end
var express = require('express');
var app = new express();
app.get('/image/upload', function(req, res) {
console.log(req.params);
res.send("ok");
});
var port = 3002;
app.listen(port);
console.log("Image Get Server started on port " + port);
The code is as above. The URL that I am trying to hit is
http://localhost:3002/image/upload/imageId.jpg
The response that I get is Cannot GET /image/upload/imageId.jpg
However when I place a wildcard at the end of the route to match
app.get('/image/upload*', function(req, res) {
it works. I remember the routes working without such wildcards. What is it that I am missing in this?

you may try:
app.get('/image/upload/:name', function (req, res)
{
var name = req.params.name;
try{
res.send("OK");
}
catch(err){
console.log("Error on: "+name+err);
}
});
it works at my node, but not sure if it is compatible with express 3

Related

Only able to access one route from routes hierarchy

I'm attempting to access a route directly from a request, even though another subfolder works the other does not. Repeatedly throwing 404 errors. /api/getPostList works but /post/ or /post/:title doesn't work.
I've restructured the code, attempted to change it from a get request to a post request, added /post/:title to access an individual post or without a / to access the main list.
Server.js contains
app.use('/', Routes);
routes/index.js contains
const router = require('express').Router();
const posts = require('./posts');
const api = require('./api');
router.use('/post', posts);
router.use('/api', api);
module.exports = router;
routes/api/index.js contains
Api.get('/getPostList', (req, res) => {
PostModel.find(function (err, post) {
if (err) return console.log('error: ' + err);
return res.json({ postList: post});
});
console.log("Attempted to get post list on /getPost/ route: " + ++postRouteCnt);
});
Api.get('/getPost/:title', getPost);
module.exports = Api;
routes/post/index.js contains
const Posts = require('express').Router();
const post = require('./post');
const PostModel = require('../../../server/models.js');
let postRouteCnt = 0;
Posts.get('/', (req, res) => {
PostModel.find(function (err, post) {
if (err) return console.log('error: ' + err);
return res.json({ postList: post});
});
console.log("Attempted to get post list on /post/ route: " + ++postRouteCnt);
});
Posts.get('/:title', post);
module.exports = Posts;
When calling /post/ I get a 404 Cannot GET /post/ when I should receive the json response.
EDIT:
Folder structure
Server/
routes/
api/
index.js
getPost.js (for individual post)
posts/
index.js
post.js (for individual post)
server.js
Base on your structure folder, I try to write code with simple code
App.js :
const express = require('express')
const app = express()
const port = 3000
const Routes = require('./routes/posts/index.js');
app.use('/', Routes);
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
.routes/ posts/ index.js :
const express = require('express');
const router = express.Router();
const postController = require('./post');
// GET /
router.get('/posts', postController.getPosts);
module.exports = router;
.routes/ posts/ post.js :
exports.getPosts = (req,res) => {
res.send('test');
}
Try input http://localhost:3000/posts and its work
You can write any logic in .routes/ posts/ post.js :
try changing it like this
Posts.get('/', (req, res) => {
PostModel.find(function (err, post) {
if (err) throw err;
res.send({ postList: post});
});
console.log("Attempted to get post list on /post/ route: " + ++postRouteCnt);
});
now try this url
/post/

App.js to redirect to a module

I am debugging into a NODE JS application and I am very new to node js. I have a REST module file
students.js
module.exports = function (service) {
/**
* Retrives data from DB
*/
service.get('/mobile/students', function (req, res) {
res.set('Content-Type', 'application/json')
.status(200)
.json(DBHelper.getAllStudents());
});
service.post('/mobile/students', function (req, res) {
res.status(200).json(data);
});
});
To run it locally I am using the following app.js
const express = require('express');
const app = express();
var routes = require('./students');
app.get('/', function (req, res) {
res.send('Hello World!')
});
app.listen(3010, function () {
console.log('Example app listening on port 3010!')
});
When I hit
http://localhost:3010/students, I am hitting a 404.
How do I explicit route the path to the student modules?
you need to add routes(app); line after var routes = require('./students'); then Your routes will be mounted..
http://localhost:3010/students if use this it will prompt you again with 404 but if you use http://localhost:3010/mobile/students it will produce desire output..

NodeJS/Express GET exit status of external application

I am pretty new to NodeJS and this is my first time with Express 4, I'm trying to build a simple RESTful front-end around a command-line application. There will ultimately only be one GET and one POST necessary, with the POST handling about 3 or 4 different parameters. The GET should call the command-line application with all default parameters, which is basically just a status check and return the exit status upon completion. The POST will pass along POST parameters on the commandline. I know that this basically calls for an asynchronous call, like child_process.execFile(), but I can't seem to figure out how to actually return the response from within the callback function.
This is the tutorial I used as a starting point, omitting the mongoose dependency, because I have no need for MongoDB, so I basically just followed it up to the point where you start the server. At this point, I'm pretty lost. I always hate writing async code...
var express = require('express'); // call express
var app = express(); // define our app using express
var bodyParser = require('body-parser');
var child_process = require('child_process');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = process.env.PORT || 8080; // set our port
var router = express.Router(); // get an instance of the express Router
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
router.get('/myapp/status', function(req, res) {
console.log(req.user);
child_process.execFile(
'casperjs',
['myfile.js', '--cmd="Status"', '--user="myuser"', '--pass="#mypass"'],
null,
function(response) {
// ???
}, res);
});
app.use('/api', router);
app.listen(port);
console.log('Magic happens on port ' + port);
You can try the following:
router.get('/myapp/status', function(req, res) {
console.log(req.user);
child_process.execFile(
'casperjs', //command
["myfile.js --cmd=Status --user=myuser --pass=#mypass"], // args
function(err, stdout, stderr) { //callback
if (err) {
return res.status(500).send(err);
}
res.send(stdout); // to send response to client
});
});

How to configure express js 4 to serve some pages in http and others in https?

Is there any way to configure a node js application with express js 4 to serve some pages under http protocol and other, those which need more security, in https?
I describe my problem: I'm developing a shop online and I want to display certain pages, like the products list or the product detail views under http, and others which I think need more security, like login or the shopping cart views, under https protocol.
I have tried the express-force-ssl module, but it isn't working. The following code snippet is not from my app (which is too dirty) it is just an example which alos doesn't work for me:
var express = require('express');
var forceSSL = require('express-force-ssl');
var fs = require('fs');
var http = require('http');
var https = require('https');
var ssl_options = {
key: fs.readFileSync('./server-private-key.pem'),
cert: fs.readFileSync('./server-certificate.pem'),
ca: fs.readFileSync('./server-certificate-signing-request.pem')
};
var app = express();
var server = http.createServer(app);
var secureServer = https.createServer(ssl_options, app);
app.use(forceSSL);
app.get('/', function (req, res, next) {
res.send('Hello')
});
app.get('/user/:name', function (req, res, next) {
var user = req.params.name;
res.send('Hello ' + user + '')
});
app.get('/login', forceSSL, function (req, res, next) {
res.send('Hello<br/>Goodbye')
});
app.get('/logout', forceSSL, function (req, res, next) {
res.send('Hello')
});
secureServer.listen(443)
server.listen(8085)
console.log('server started');
The result is that when I launch the application, with url http://localhost:8085, the server automatically redirects it to https://localhost and serves all pages in https protocol.
What I want is to start on http://localhost:8085, navigate to http://localhost/user/userA, then from it go to https://localhost/login and, if click on "Hello" link, I would like to be redirected to http://localhost:8085.
Is there any missing code to get the behavior I want or even any other way to reach it without express-force-ssl module?
I have asked to the author of express-force-ssl module and he has told me that the redirect behavior works as expected. Here is the post.
But diving a little more in its code I've created a custom plugin to solve my problem. Here is the code:
var parseUrl = require('url').parse;
var isSecure = function (req) {
if (req.secure) {
return true;
}
else if (
req.get('X-Forwarded-Proto') &&
req.get('X-Forwarded-Proto').toLowerCase &&
req.get('X-Forwarded-Proto').toLowerCase() === 'https') {
return true;
}
return false;
};
exports = module.exports = function (req, res, next) {
if (isSecure(req)) {
if (req.method === "GET") {
var httpPort = req.app.get('httpPort') || 80;
var fullUrl = parseUrl(req.protocol + '://' + req.header('Host') + req.originalUrl);
res.redirect('http://' + fullUrl.hostname + ':' + httpPort + req.originalUrl);
}
else {
next();
}
}
else {
next();
}
};
It's very similar to force-ssl file but here we manage the opposite action, i.e., here I redirect to http when a route is forced to it. So it's needed to add the function to every route we want to see under http protocol:
var express = require('express');
var forceSSL = require('express-force-ssl');
var fs = require('fs');
var http = require('http');
var https = require('https');
var useHttp = require('./useHttp');
var ssl_options = {
key: fs.readFileSync('./server-private-key.pem'),
cert: fs.readFileSync('./server-certificate.pem')
};
var app = express();
var server = http.createServer(app);
var secureServer = https.createServer(ssl_options, app);
app.get('/', useHttp, function (req, res, next) {
res.send('Hello')
});
app.get('/user/:name', useHttp, function (req, res, next) {
var user = req.params.name;
res.send('Hello ' + user + '')
});
app.get('/login', forceSSL, function (req, res, next) {
res.send('Hello<br/>Goodbye')
});
app.get('/logout', forceSSL, function (req, res, next) {
res.send('Hello')
});
app.set('httpsPort', 9090);
app.set('httpPort', 8085);
secureServer.listen(9090)
server.listen(8085)
console.log('server started');
As you can see I need now to specify in all routes which protocol use: useHttp for http or forceSSL for https.
Although I'm not comfortable at all with this solution because I have to specify in all routes which kind of protocol I want. But at least it works. So I would be very pleased if someone finds any other solution, for isntance, adding in middleware layer a function to manage all http requests and just redirect to https when it is specified with forceSSL. By the moment, this works.

Why Express.js' app.get() can only work in the same file app.listen() is called?

When app.listen() is in the same file as app.get(), it works; and when I add app.get() calls in other files via require, they don't work:
// ~ means root folder
// This below is in ~/index.js
var routes = require('~/routes/routes.js');
var server = app.listen(3000, function () {
console.log('Listening on port %d', server.address().port);
});
app.get('/snails', function (req, res) {
res.send('ESCARGOT');
});
// This below is in ~/routes/routes.js
var app = module.exports = require('exports')();
app.get('/birds', function () {
res.send('PENGUIN');
});
// SUCCESS -> localhost:3000/snails will return "ESCARGOT"
// FAIL -> localhost:3000/birds will return "Cannot GET /birds"
Second example to prove the point; this time, app.listen() is moved to routes.js:
// ~ means root folder
// The below is in ~/index.js
var routes = require('~/routes/routes.js');
app.get('/snails', function (req, res) {
res.send('ESCARGOT');
});
// The below is in ~/routes/routes.js
var app = module.exports = require('exports')();
app.get('/birds', function () {
res.send('PENGUIN');
});
var server = app.listen(3000, function () {
console.log('Listening on port %d', server.address().port);
});
// FAIL -> localhost:3000/snails will return "Cannot GET /snails"
// SUCCESS -> localhost:3000/birds will return "PENGUIN"
Why is this so? Is it because app.listen() only targets the file that it is called in?
You need to export your app and include it in your routes file
module.exports = app;
And then in your routes file
var app = include('pathtoyourapp.js');
Then you'll have access to your app in your routes file.
You should be doing something along the lines of this in routes/routes.js
module.exports = function(app) {
app.get('/birds', function(req, res, next) {
res.send('Hello');
});
};
and in the index.js
var app = express();
app.get('/snails', function(req, res, next) {
res.send('SNAILS');
});
require('./routes/routes')(app);
app.listen(3000);
should now work.
BTW i'm not 100% sure what you are trying to do by doing require('exports')(), and it looks weird that you are actually exporting that, instead of the app (that contains the new birds route) in routes/routes.js, so that's why it probably doesn't work. Try the way I suggested.
Let me know if you need any additional things.
Use example:
var express = require('express'),
http = require('http'),
port = Number(process.env.PORT || 3000),
app = express();
app.get('/', function(req, res) {
res.end('Test message');
});
http.createServer(app).listen(port);
Most important is:
http.createServer(app).listen(port);
Send app argument for manipulation of servers behaviors.

Resources