How to call an api from another api in expressjs? - node.js

I have an api like this:
app.get('/test', (req, res) => {
console.log("this is test");
});
and another api:
app.get('/check', (req, res) => {
//I want to call "test" api without redirect to it.
});
I want to call "test" api in "check" api without redirect to "test" api, just do the function in the "test" api.
Above is the example code. 'Cause I dont' want to rewrite function from "test" api to "check"

Simple solution is to define a method which can be called using both request routes.
app.get('/test', (req, res) => {
console.log("this is test");
callMeMayBe();
});
callMeMayBe()
{
//Your code here
}

To "call an API from another API", a quick and easy way is sending HTTP request inside Express server, browser would never know an internal HTTP invocation happens, not mention page-redirect. The benefit of this design includes:
There's no need to change the current API design.
The API invocation can be made exact like sent from browser.
Here is an example:
var http = require('http');
router.get('/test', function(req, res) {
res.end('data_from_test');
});
router.get('/check', function(req, res) {
var request = http.request({
host: 'localhost',
port: 3000,
path: '/test',
method: 'GET',
headers: {
// headers such as "Cookie" can be extracted from req object and sent to /test
}
}, function(response) {
var data = '';
response.setEncoding('utf8');
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', () => {
res.end('check result: ' + data);
});
});
request.end();
});
The result of GET /check would be:
check result: data_from_test

Create a common middleware which need to executed for both the routes.
Below is the code snippet for the same:
app.get('/test', test);
app.get('/check', check, test);
check and test are the middlewares which is used in common.

first define the /test handling function separately.
then you have two options.
// ========( 1 )====== testHandler as another function =============
// you can call this function where ever you want.
var testHandler = function(req, res){
//do something
}
app.get('/test', testHandler);
app.get('/check', function(req, res){
// you can call testHandler function here
testHandler(req, res);
});
// ========( 2 )======= testHandler as a middleware =================
// if you want to call testHandler before running check handler function.
//
var testHandler = function(req, res, next){
//do something
...
next();
}
app.get('/test', testHandler, function(req, res){});
app.get('/check', testHandler, function(req, res){
// you can call testHandler function here
testHandler(req, res);
});

Related

How to set Content-Type header in node.js

I am executing the following code in node.js. The code runs fine, but the tutorial tells us that :
Now go back and add the Content-Type header with a value of application/json and run the request again. You will get the “You sent
JSON” message back from the server.
1) I am not able to understand how can I set headers for this program!
2) Also If I am running the program without setting headers, then the message 'Server requires application/json' should be displayed. I am not seeing it being displayed anywhere. Where should it be displayed?
const express = require('express');
const app = express();
const requireJsonContent = () => {
return (req, res, next) => {
if (req.headers['content-type'] !== 'application/json') {
res.status(400).send('Server requires application/json')
} else {
next()
}
}
}
app.get('/', (req, res, next) => {
res.send('Welcome Home');
});
app.post('/', requireJsonContent(), (req, res, next) => {
res.send('You sent JSON');
})
app.listen(3000);
What I see In Your code is that, the function requireJsonContent that you defined Does not have parameters. So, you should add (req, res, next) as params to your function. Besides, inside it, you return a function without execution. However, I think You don't need that function, and your code should be like this:
app.post('/', (req, res) => {
if (req.headers['content-type'] !== 'application/json') {
res.status(400).send('Server requires application/json')
} else {
res.send('You sent JSON');
}
})
With express 4.x, you can either use res.set() or res.append(). Read differences between both methods here.

app.get - is there any difference between res.send vs return res.send

I am new to node and express. I have seen app.get and app.post examples using both "res.send" and "return res.send". Are these the same?
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.type('text/plain');
res.send('i am a beautiful butterfly');
});
or
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.type('text/plain');
return res.send('i am a beautiful butterfly');
});
The return keyword returns from your function, thus ending its execution. This means that any lines of code after it will not be executed.
In some circumstances, you may want to use res.send and then do other stuff.
app.get('/', function(req, res) {
res.send('i am a beautiful butterfly');
console.log("this gets executed");
});
app.get('/', function(req, res) {
return res.send('i am a beautiful butterfly');
console.log("this does NOT get executed");
});
I would like to point out where it exactly made a difference in my code.
I have a middleware which authenticates a token. The code is as follows:
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1] || null;
if(token === null) return res.sendStatus(401); // MARKED 1
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if(err) return res.sendStatus(403); // MARKED 2
req.user = user;
next();
});
}
On the // MARKED 1 line, if I did not write return, the middleware would proceed and call next() and send out a response with status of 200 instead which was not the intended behaviour.
The same goes for like // MARKED 2
If you do not use return inside those if blocks, make sure you are using the else block where next() gets called.
Hope this helps in understanding the concept and avoiding bugs right from the beginning.
app.get('/', function(req, res) {
res.type('text/plain');
if (someTruthyConditinal) {
return res.send(':)');
}
// The execution will never get here
console.log('Some error might be happening :(');
});
app.get('/', function(req, res) {
res.type('text/plain');
if (someTruthyConditinal) {
res.send(':)');
}
// The execution will get here
console.log('Some error might be happening :(');
});
To Add a little bit more context to the examples above. Express has layers. So if you return in your function you end the execution. If you not end that you can go further in your layered logic.
So the next function passed to each layer can be called to execute the next layer. If you don't call next the execution stops after your method excuted is executed. (Return just exits the function)
The response object is still available after sending. It is just not possible to write to it again because it has already completed after you did res.end() or res.send().
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
// a controller handles a http request and terminat it
const controller = (req, res, next) => {
// return http response to client
res.send('hello world');
// do something after you sended request
console.log('do something else');
// if you call next the request will go to the next layer -> afterSend,
// if you do not call next the execution will end
next();
};
// this middleware/layer is executed after response is send to client
const afterSend = (req, res, next) => {
// do something after you sended request, but not send again -> readonly
console.log(res);
// this would throw an error
// res.send()
// res.end()
// etc...
};
// we skip routers here
app.get('/hello', controller, afterSend);
app.listen(port, () => {
console.log(`Running on ports ${port}`);
});

Applying a middleware function to particular requests

I want to apply a particular middleware function to the two post requests but not the get request. How could I do this?
var router = express.Router();
var app = express();
router.post('/jobs',(req,resp)=>{
var messageString = JSON.stringify(req.body);
Job.accept(messageString,(statusCode,respObject)=>{
resp.status(statusCode).json(respObject);
});
});
router.get('/jobs',(req,resp)=>{
Job.status((statusCode,respObject)=>{
resp.status(statusCode).json(respObject);
});
});
router.post('/try',(req,resp)=>{
var messageString = JSON.stringify(req.body);
Job.ok(messageString,(statusCode,respObject)=>{
resp.status(statusCode).json(respObject);
});
});
I was reading about app.use, but couldn't really understand its usage.
Add the middleware you want to the function. Here is an example where I log the users IP
const myLogger = (req, res, next) => {
console.log('got a request from', req.connection.remoteAddress);
next();
}
app.post('/jobs', myLogger, (req, res) => {
//your code here...
}
Along with the answer mentioned above, write app.use(myLogger)

NodeJS Express: How to interrupt the routing from outside the middleware/router?

I implemented a very simple middleware to check the permissions for the user:
app.js
...
var security = require('./lib/security');
app.use(security.init);
...
lib/security.js
var session;
var request;
var response;
function init(req, res, next) {
request = req;
response = res;
session = req.session;
next();
}
function adminRequired(){
if (!isAdmin()){
response.redirect('/login');
response.end();
return true;
}
return false;
}
...
The best way I found to interrupt the flow is the following:
routes/mycontroller.js
router.get('/', function(req, res, next) {
if(security.adminRequiredHtml()){return;} // now it actually interrupt the execution
res.render('admin',{});
res.end();
});
However, I would like to use it like this:
routes/mycontroller.js
router.get('/', function(req, res, next) {
security.adminRequiredHtml(); // <- interrupt the request
res.render('admin',{});
res.end();
});
It correctly perform the redirect, but the execution continues :(
I've tried a few solutions like but it doesn't really work:
response.end() -> close the output but continues the execution
process.end() -> it's too radical, terminates the execution but it also kill the server :(
I've been thinking about using a throw but I don't know where to catch it and make it terminate gracefully (no stacktrace)
You could create a custom Router that is secured and add your secure Routes to that:
var secureRouter = express.Router();
// every request on this router goes throug this
secureRouter.use('*', function (req, res, next) {
if(isAdmin()) next();
// if you don't call next() you interrupt the request automaticly
res.end();
});
// protected routes
secureRouter.get('/user', function(req, res){/* whatever */});
secureRouter.post('/user', function(req, res){/* whatever */});
app.use(secureRouter);
// not protected
app.get('/api', function(req, res){/* whatever */});
Express doc for using middlewares
You're actually looking for middleware, I think.
function myMiddleware (req, req, next) {
if (!isAdmin()) {
res.redirect('/login');
res.end();
} else {
//Proceed!
next()
}
}
router.get('/', myMiddleware, function(req, res, next) {
res.render('admin',{});
res.end();
});
You can chain as many of those as you'd like to handle whatever logic you need. Just make sure you call next() if you're supposed to move on!

How to use asynchronous initialization in a Connect middleware?

I wrote a middleware for Connect and Express that requires some heavy lifting in its setup method. Due to the nature of the initialization tasks this stuff is asynchronous, so I have the problem that the middleware shall only be accessible once the initialization has been run.
Currently I have solved it using a callback:
function setupMiddleware(callback) {
doSomeAsyncInitialization(function () {
callback(function (req, res, next) {
// The actual middleware goes here ...
});
});
}
This works, but it's not nice for the caller. Instead of being able to do
app.use(setupMiddleware());
I have to do:
setupMiddleware(functin (middleware) {
app.use(middleware);
});
Now I was thinking whether there is a better approach, e.g. let the middleware initialize in the background and delay all incoming requests until the middleware is ready.
How could I solve this? Any ideas or best practices that I should use here?
I now solved it using an isInitialized variable and delaying the middleware function itself. See the following example:
var connect = require('connect');
var setup = function () {
var isInitialized = false;
setTimeout(function () {
isInitialized = true;
}, 10000);
function run (req, res, next) {
res.write('Foo');
res.end();
}
function delay (req, res, next) {
if (isInitialized) {
return run(req, res, next);
}
setTimeout(function () {
delay(req, res, next);
}, 1000);
}
return function (req, res, next) {
if (req.url === '/foo') {
delay(req, res, next);
return;
}
next();
}
};
var app = connect();
app.use(setup());
app.use(function (req, res) {
res.write('Fertig!');
res.end();
});
var http = require('http');
http.createServer(app).listen(5000);
Please note that this code has not been optimized or refactored in any way, it just is a demonstration that the idea itself works.
Why you don't do like as follows,
doSomeAsyncInitialization(function () {
//After doing all long running init process just configure your express as follows.
app.use(<middlewares>);
app.listen(<portnumder>);
});

Resources