first parameter in Express - node.js

I'm learning Express on Node and am running a simple server script that should return your name if it is fed as a variable, but I'm not sure how to call the variable in the URL
http://localhost:3000/:$jon
http://localhost:3000/?jon
http://localhost:3000/$jon
http://localhost:3000/:$jon
http://localhost:3000/:([\$])$jon
I really thought it was just..
http://localhost:3000/jon
The only 2 files in the directory are the server.js
// Load the 'express' module
const express = require('express');
// Create a new Express application instance
const app = express();
// Create a new 'hasName' middleware function
const hasName = function(req, res, next) {
// Use the QueryString 'name' parameter to decide on a proper response
if (req.param('name')) {
// If a 'name' parameter exists it will call the next middleware
next();
} else {
// If a 'name' parameter does not exists it will return a proper response
res.send('What is you name?');
}
};
// Create a new 'sayHello' middleware function
const sayHello = function(req, res, next) {
// Use the 'response' object to send a respone with the 'name' parameter
res.send('Hello ' + req.param('name'));
};
// Mount both middleware funcitons
app.get('/', hasName, sayHello);
// Use the Express application instance to listen to the '3000' port
app.listen(3000);
// Log the server status to the console
console.log('Server running at http://localhost:3000/');
// Use the module.exports property to expose our Express application instance for external usage
module.exports = app;
and then a package.json to include express
{
"name": "MEAN",
"version": "0.0.3",
"dependencies": {
"express": "4.14.0"
}
}
I'm running nmp install to intall the express from the dependencies and then node server and then getting what I'd expect at localhost
but I also just noticed I've got a depreciation on line 10.. so am I calling it wrong or do I need to patch this file? It's from a fairly recent book.

use req.params.name instead
https://expressjs.com/en/4x/api.html#req.params
you could write your code this way:
const express = require('express');
const app = express();
app.get('/', function(req, res, next){
res.send("what's your name?");
});
app.get('/:name', function(req, res, next){
res.send('Hello ' + req.params.name);
});
app.listen(3000, function(){
console.log('Server running at http://localhost:3000/');
});

You can just use app.get('/:name', hasName, sayHello); instead of app.get('/', hasName, sayHello);.

Related

How do I get the full route path including the parameters from express or extend the request object to do so?

I have the following route in my express (version 4.17.1) API in a postTimecardCompany.js file:
const mongoose = require('mongoose');
const Timecard = require('./../models/timecard');
function postTimecardCompany(server) {
server.post('/api/v1/timecard/:userId', (req, res) => {
// Insert timecard data into the database
Timecard.create(data, (error, result) => {
// Check for errors
if (error) {
res.status(500).end();
return;
}
// Respond
res.status(200).send({timecardId: result._id});
});
});
}
module.exports = postTimecardCompany;
The route (among other routes) is loaded via the following mechanism by server.js file:
[
'postTimecardCompany',
'anotherRoute',
'someOtherRoute',
'andSoOn...'
].map((route) => {
require('./core/routes/' + route + '.js').call(null, server)
});
I have a middleware (in server.js file) where I check which route is being called.
server.use((req, res, next) => {
// If route is "/api/v1/timecard/:userId" do something
});
I have found various solutions which do nearly what I am looking for, but not exactly.
For example, if I post to the route with a data parameter userId value of "123f9b" then req.originalUrl gives an output of "/api/v1/timecard/123f9b."
What i'm looking to get is the original route path with the parameters in it so for a request of "/api/v1/timecard/123f9b" it would be: "/api/v1/timecard/:userId."
How do I get this functionality in express or extend express to get the original route path with parameters in the request object?
if you want to use from your approach, it's is impossible, after that your approach is not standard in express check the documentation, if you want get routes in a middleware you should try like this:
server.js
const express = require('express')
const server = express()
const postTimecardCompany = require('./routes/postTimecardCompany.js')// don't use map()
server.use("/",postTimecardCompany)//use the routes
server.listen(6565,()=>console.log(`Listening to PORT 6565`))
routes of postTimecardCompany.js
use Router of express and export router, and you can use middleware before each route you want, there are many ways to use middleware in routes, check the documentation
const express = require("express");
const router = express.Router();
const middleware = require('../middleware');//require middlewares
router.post("/api/v1/timecard/:userId", middleware,(req, res) => {
// Insert timecard data into the database
console.log(req.route.path);
});
module.exports = router;
middleware.js
module.exports = ((req, res, next) => {
console.log(req.route.path);
next()
});

NodeJS, Express. Cannot upload static content

I've tried to write node server which would run React app created by create-react-app. Actually, something strange happens and I don't have any clue what I'm doing wrong (run app as node server/index.js):
export default (app, dirname) => {
app.use(favicon(path.join(dirname, '..','build', 'favicon.ico')));
app.use(express.static(path.join(dirname, '..','build')));
// initialize routers
bootRotes(app);
if (process.env.NODE_ENV === AVAILABLE_ENVIROMENTS.DEVELOPMENT) {
expressBootDev(app, dirname);
} else {
app.get('/*', (req, res) => {
res.sendFile(path.join(dirname, '..', 'build', 'index.html'));
});
}
}
build folder contains build react app which created the following command npm run build
Strange things are happening when after uploading index page it tries to upload static content. For example http://localhost:5000/static/js/2.30e86b6e.chunk.js. Browser just adds / after each static content url and it turns to http://localhost:5000/static/js/2.30e86b6e.chunk.js/ and of course this url doesn't match to express.static middleware.
Moreover, I've checked via Postman, that url GET http://localhost:5000/static/js/2.30e86b6e.chunk.js withot / at the end provides content which is expected.
I work with PRODUCTION env, it means that expressBootDev doesn't have any impacts.
Has anybody has the same issue? I've spent whole day and don't know hopw to fix it.
When I'm creating a simple code in a root app folder with almost the same logic and run as node server.js and it works as expected:
//server.js
const express = require('express');
const favicon = require('express-favicon');
const path = require('path');
const port = process.env.PORT || 8080;
const app = express();
app.use(favicon(__dirname + '/build/favicon.ico'));
app.use(express.static(__dirname));
app.use(express.static(path.join(__dirname, 'build')));
app.get('/ping', function (req, res) {
return res.send('pong');
});
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(port);
And I don't see any principal difference
var fs = require('fs');
var express = require('express');
var router = express.Router();
// GET: Sent some basic info for usage
router.get('/', (req, res, next) => {
var fname = __dirname + '/../public/index.html';
var val = fs.readFile( fname, 'utf8', ( err, data) => {
//send can only be called once, write can be called many times,
// in short res.send(msg) == res.write(msg);res.end();
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(data);
res.end();
});
});
module.exports = router;
Here is the example how you can do a static file serving with node.
https://github.com/msatyan/ApiServe1/blob/master/routes/index.js
The full project is
https://github.com/msatyan/ApiServe1
FYI: Node.js with HTTP1 is not an efficient for static file serving by design, I believe HTTP2 support in node has addressed this problem. The reason for inefficiency with HTTP1 is that it has to take the file content read at native layer to JavaScript layer and then send it through HTTP server.

Serving VueJS Builds via Express.js using history mode

I want to serve vue js dist/ via express js. I am using history router in vue js app.
The following are the api calls
api/
s-file/sending/:id
terms/get/:which
As i have figured out a solution in python here. I don't know how to do it in node js with express
The code i am using right now is
app.use(function (req, res, next) {
if (/api/.test(req.url))
next();
else {
var file = "";
if (req.url.endsWith(".js")) {
file = path.resolve(path.join(distPath, req.url))
res.header("Content-Type", "application/javascript; charset=utf-8");
res.status(200);
res.send(fs.readFileSync(file).toString());
} else if (req.url.endsWith(".css")) {
file = path.resolve(path.join(distPath, req.url))
res.header("Content-Type", "text/css; charset=utf-8");
res.status(200);
res.send(fs.readFileSync(file).toString());
} else {
file = path.resolve(path.join(distPath, "index.html"))
res.header("Content-Type", "text/html; charset=utf-8");
res.status(200);
res.send(fs.readFileSync(file).toString());
}
}
})
Have a look at connect-history-api-fallback that is referenced in the vue docs.
This should solve your problems.
Example using connect-history-api-fallback
var express = require('express');
var history = require('connect-history-api-fallback');
var app = express();
// Middleware for serving '/dist' directory
const staticFileMiddleware = express.static('dist');
// 1st call for unredirected requests
app.use(staticFileMiddleware);
// Support history api
// this is the HTTP request path not the path on disk
app.use(history({
index: '/index.html'
}));
// 2nd call for redirected requests
app.use(staticFileMiddleware);
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
The very simpler one if anyone wants to use
Just add this below all the valid routes and above app.listen
app.all("*", (_req, res) => {
try {
res.sendFile('/absolute/path/to/index.html');
} catch (error) {
res.json({ success: false, message: "Something went wrong" });
}
});
Make sure you have included
app.use(express.static('/path/to/dist/directory'));

ExpressJS Router is not handling root routes

UPDATE 2: I just noticed that if on the app file I change the line:
app.use('/', home);
to:
app.use('/anything', home);
then all of the sub routes "roots" work fine.
UPDATE 3: I just realized something else. A method on the home.js file that I did not originally include below since I didn't think was relevant turns out to be the cause of the problem.
router.get('/:adventureId', (req, res) => {
var data;
//Irrelevant content that sets data as a JSON object.
res.json(data);
});
Turns out that every single sub route "root" is passing through here and since on the other routes adventureId is undefined then data is just an empty JSON object.
So the real question is: If this router bound to "/" and the other "roots" are bound to "/adventure" and "/test" why are all of them going through "/:adventrueId"?
I have a very simple ExpressJS application on which all of the "roots" in each and every single route other than home are not being handled and they always display an empty JSON object on the page.
In some posts it was mentioned that it could be a caching issue since these routes always return a 304 status, but I've tried doing an "Empty cach and hard reload" on Chrome and even with the 200 status I still get a blank page with an empty JSON object displayed on it. I tried it with MS Edge and got the exact same behavior.
Here's what I have:
On my app file
var app = express();
var home = require('./routes/home');
var adventure = require('./routes/adventure');
var test = require('./routes/test');
app.use('/', home);
app.use('/adventure', adventure);
app.use('/test', test);
On home.js file:
var express = require('express');
var router = express.Router();
router.get('/', (req, res) => {
console.log("This works fine with http://localhost:3000.");
res.render('home');
});
router.get('/:adventureId', (req, res) => {
var data;
//Irrelevant content that sets data as a JSON object.
res.json(data);
});
module.exports = router;
On the adventure.js file:
var express = require('express');
var router = express.Router();
router.use('/:id', (req, res) => {
console.log("This works fine with http://localhost:3000/adventure/5.");
next();
});
router.get('/:id', (req, res) => {
console.log("This works fine with http://localhost:3000/adventure/5.");
res.render('adventure');
});
//I've also tried putting this before the other routes and the result is the same.
router.get('/', (req, res) => {
console.log("This is never written in the console with http://localhost:3000/adventure.");
res.send("This is never rendered in the page.");
});
On the test.js file:
var express = require('express');
var router = express.Router();
router.use('/', (req, res) => {
console.log("This is never written on the console with http://localhost:3000/test.");
res.send("Hello from the test root route");
});
module.exports = router;
In the ExpressJS Router documentation and every single blog and example I've found it says that this is how it should work so I am really at a loss here.
Thank you.
If this router bound to "/" and the other "roots" are bound to "/adventure" and "/test" why are all of them going through "/:adventrueId"?
Because Express doesn't match routes based on which one matches best, it matches on which one matches first.
In your case, the route /:advertureId was declared before the routes for /adventure or /test. And /adventure and /test both match /:advertureId, so the handler for that route is called.
If you want to prevent this, declare more specific routes first:
app.use('/adventure', adventure);
app.use('/test', test);
app.use('/', home);
After much going around, several updates on the question and banging my head against the keyboard I finally understood what the problem is:
By having the routers set up like this:
app.use('/', home);
app.use('/adventure', adventure);
app.use('/game', gameService);
app.use('/test', test);
and on the "home" router having this method signature:
router.get('/:adventureId', (req, res) => {
var data;
//Irrelevant content that sets data as a JSON object.
res.json(data);
});
Every single sub route "root" was being interpreted as the parameter of the previous method so:
/adventure
/test
/anything
would be handled as:
adventrueId = adventrue
adventureId = test
adventrueId = anything
The solution was to do this:
app.use('/adventure', adventure);
app.use('/game', gameService);
app.use('/test', test);
app.use('/', home);
And now everything works.

how to create a nodeJS module with expressJS

I'm making a nodeJS module, and I want to use expressJS as a framework for it.
I'm trying to see, how I could go by, including a function inside and app.get(); and call it via another file, such as the actual app.
var express = require("express");
var app = express();
app.get("/", function (req, res) {
exports.type = function (text) {
console.log(req.ip);
console.log(text);
}
});
now when I use this, and i call it on the actual app like:
var web = require("directory_to_file");
var express = require("express");
var app = express();
var http = require("http").Server(app);
app.get("/", function (req, res) {
web.type("Hello, world");
});
http.listen(10022, function () {
console.log("server is up");
});
I get an error:
TypeError: Property 'type' of object #<Object> is not a function
anyone know a way to make it so I can call the function?
There are generally two things you want to export as a module - an API and a Middleware. The classic example of middleware is an authentication module. To do the middleware, just export the middleware. I tend to do a little more than that so I can configure the middleware later. Something along the lines of this:
module.exports = exports = function(config) {
// Do something with config here
return function(req, res, next) {
// your middleware here
};
};
You can then use your middleware in your main program like this:
var app = require('express')(),
mymodule = require('./mymodule');
var config = {}; // replace with whatever config you need
app.use(mymodule(config));
app.listen(process.env.PORT || 3000);
To implement an API, you will create a Router object, then attach your routes to the Router object. You can then "mount" your router in your main program. For example, you could have a file called 'myroutes.js' with the following contents:
var express = require('express'),
myroutes = express.Router();
myroutes.get('/foo', (req, res) => {
res.status(200).type('application/json').send({ myparam: 'foo' });
});
module.exports = exports = myroutes;
Have the following in your main program:
var app = require('express')(),
myroutes = require('./myroutes');
app.use('/api', require('./myroutes'));
app.listen(process.env.PORT || 3000);
Here, in 'myroutes.js', I'm defining a sub-route of /foo and then in the main program, I'm mounting that on /api - so I would access /api/foo to access that API.
In your directory_to_file you are only exporting on app.get('/') which will never be called.
You could add in your directory_to_file the following code
var express = require('express');
var router = express.Router();
router.get('/', function(req, server) {
console.log(req.ip);
});
module.exports = router;
And in your main file you could use app.use('/', web)
A short explanation:
You are creating a new express app / config in your directory_to_file file which won't be launched or used. So your app.get event won't be fired once.
That's why web.type is not a function. You are not exporting anything.
Use the way I provided. This is a commonly used method.
You could call the code I provided a "route". Create multiple routes / route files and include them in your main method.
Your code just looks confused. If I understand you correctly, what you are really trying to do (at least in Node/express terminology) is write your own middleware.
Express is designed with this in mind and it's pretty straightforward e.g.
ipLogger.js
module.exports = function(req, res, next) {
console.log(req.ip);
next();
}
app.js
var http = require("http")
, express = require("express");
, app = express()
, server = http.Server(app)
, ipLogger = require("./ipLogger.js");
app.use(ipLogger()); // log IP of all requests
// handle routes
server.listen(10022, function() {
console.log("server is up");
});

Resources