How to get the response time in node js - node.js

Recently I started putting response time to my API's.I tried putting to my routes but I am not sure how to use it.My aim is to get the response time in the console for each request.
var responseTime = require('response-time')
app.use(responseTime());
app.route('/getAllUsers').get(users.getUsers);
Can anyone please suggest help.Thanks.

For getting the response time in your routes -
var start = new Date();
router.get('/dummy', function(req, res, next){
console.log('Request took:', new Date() - start, 'ms');
});
output ex - Request took: 1596 ms

You can pass a function that will get called after a request:
app.use(responseTime((req, res, time) => {
console.log(req.method, req.url, time + 'ms');
}));
Or use a more elaborate logger middleware like morgan that also provides the option to log response times.

Related

Web don´t load when i use cookie-parser in NodeJS

I'm trying to get the value of a cookie with a cookie-parser.
The code is as follows (app.js):
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.get('/', function (req, res) {
console.log('Cookies: ', req.cookies);
});
The log shows the cookies and their value but the page shows the error ERR_EMPTY_RESPONSE
If I do not use this, the web loads perfectly.
I hope you can help me, thanks in advance.
Every middleware function must either invoke the next one in the chain to continue request processing, or finish the response by itself (using res.end() or res.send(...) or similar functions). In your case you're not passing control to next middleware, so response is ending with your function - but you're not properly ending the response either. That's why the error.
If you just want to print cookie value, you can invoke the next middleware in chain by using :
app.get('/', function (req, res, next) {
console.log('Cookies: ', req.cookies);
next(); //--> Added to call next middleware in chain
});
Do you have this at the bottom?
app.listen(8080)

Log requests to nodejs express

I want to log all requests like this:
8:04:20 PM - info: /api/v2 200
8:04:22 PM - info: /api/v2/asdf 200
However, in express, the middleware is called before the request is processed, so I cannot get the real response code. I always get 200. What is the right approach to accomplish this?
You can use morgan to log your requests:
const morgan = require("morgan");
app.use(morgan('dev'));
For more documentation visit morgan. Yo may also be interested in
on-finished package to execute arbitrary code on request completion.
Here you go:
app.use((req, res, next)=> {
console.log('I run on every request!');
next();
})
Have your middleware below your routes and in your routes add a third parameter on the callback like this:
app.get( "/", function( req, res, next ) {
res.send(something);
next();
});
app.use(function(req, res, next) {
console.log('after request is done');
});

How to get the url parameter?

I am very new to Express, I want to parse the url parameter. My code as below:
router.get('/', function (req, res) {
var aCustomerIdValue = req.param.aa;
console.log('In / Function be called: %s',aCustomerIdValue);
res.redirect('/checkouts/new');
});
But the console show "undefine". Any clue for it?
My express is 4.0.
Thank you in advanced!
Parameter types
req.params
It should be req.params.aa instead of req.param.aa - see:
http://expressjs.com/en/api.html#req.params
but it would work only for ":aa" parameters in the path of routes like router.get('/:aa', ...) - it would save XXX from request to GET /XXX in req.params.aa
req.query
For query parameters (most likely for GET requests) use req.query - see:
http://expressjs.com/en/api.html#req.query
It will save XXX from request to GET /?aa=XXX in req.query.aa
req.body
For the parameters passed in the request body use req.body - see:
http://expressjs.com/en/api.html#req.body
It will save aa parameters passed in the body of the request (most likely for POST requests) in req.body.aa
req.param()
There is also req.param('name') for either one of those, searched in order of:
req.params
req.body
req.query
but it is deprecated - thanks to Ben Fortune for pointing it out in the comment - see: http://expressjs.com/en/api.html#req.param
Your example
Try:
router.get('/', function (req, res) {
var aCustomerIdValue = req.query.aa;
console.log('In / Function be called: %s', aCustomerIdValue);
res.redirect('/checkouts/new');
});
if the parameter is passed in the query string, or:
router.get('/', function (req, res) {
var aCustomerIdValue = req.body.aa;
console.log('In / Function be called: %s', aCustomerIdValue);
res.redirect('/checkouts/new');
});
if the parameter is passed in the request body.
Make sure to put body-parser code in your server file above all the routes
Like this
var app=repress();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
And if you are passing query parameters then get it on server side by
req.query
And if you are passing parameters then get it server side by
req.params

Express.js Response Timeout

PROBLEM
I've been looking for request/response timeouts for Express.js but everything seems to be related to the connection rather than the request/response itself.
If a request is taking a long time, it should be timed out. Obviously this shouldn't happen but even a simple mistake as having a route handler without a call to the callback or without res.send(), the browser will keep waiting for a reply forever.
An empty route handler is a perfect example of this.
app.get('/sessions/', function(req, res, callback){});
FIX
I added the following before app.use(app,router); and it seemed to add the timeout functionality. Does anyone have any experience/opinion on this?
app.use(function(req, res, next){
res.setTimeout(120000, function(){
console.log('Request has timed out.');
res.send(408);
});
next();
});
Note that I've set the timeout to 2 minutes.
There is already a Connect Middleware for Timeout support:
var timeout = express.timeout // express v3 and below
var timeout = require('connect-timeout'); //express v4
app.use(timeout(120000));
app.use(haltOnTimedout);
function haltOnTimedout(req, res, next){
if (!req.timedout) next();
}
If you plan on using the Timeout middleware as a top-level middleware like above, the haltOnTimedOut middleware needs to be the last middleware defined in the stack and is used for catching the timeout event. Thanks #Aichholzer for the update.
Side Note:
Keep in mind that if you roll your own timeout middleware, 4xx status codes are for client errors and 5xx are for server errors. 408s are reserved for when:
The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time.
You don't need other npm modules to do this
var server = app.listen();
server.setTimeout(500000);
inspired by https://github.com/expressjs/express/issues/3330
or
app.use(function(req, res, next){
req.setTimeout(500000, function(){
// call back function is called when request timed out.
});
next();
});
An update if one is using Express 4.2 then the timeout middleware has been removed so need to manually add it with
npm install connect-timeout
and in the code it has to be (Edited as per comment, how to include it in the code)
var timeout = require('connect-timeout');
app.use(timeout('100s'));
In case you would like to use timeout middleware and exclude a specific route:
var timeout = require('connect-timeout');
app.use(timeout('5s')); //set 5s timeout for all requests
app.use('/my_route', function(req, res, next) {
req.clearTimeout(); // clear request timeout
req.setTimeout(20000); //set a 20s timeout for this request
next();
}).get('/my_route', function(req, res) {
//do something that takes a long time
});
If you need to test your api, this solotion can you help.
I used this in middleware to test my frontend.
For exmaple: if you need to test loader in frontend.
const router = require('express').Router();
const { data } = require('./data');
router.get('/api/data', (req, res, next) => {
setTimeout(() => {
res.set('Content-Type', 'application/json')
res.status(200).send(data)
next()
}, 2000)
})
module.exports = router;
request.setTimeout(< time in milliseconds >) does the job
https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback
You can try:
return await new Promise((resolve) =>
setTimeout(() => {
resolve(resp);
}, 3000),
);
In above code, 3000 = 3 sec.
Change it according to your requirement.
I have not tried for very long scenarios though. Let me know the results in comments.
Before you set your routes, add the code:
app.all('*', function(req, res, next) {
setTimeout(function() {
next();
}, 120000); // 120 seconds
});

AngularJS $resource makes HTTP OPTIONS request instead of HTTP POST for $save method

I'm in the process of writing a simple library application to get ready for a larger project with AngularJS. After reading a lot online about using $resource to interact with a RESTful API, I decided that it would probably offer some time-saving and scaling benefits to implement it instead of using $http for each request. The problem is that for some reason (I'm no expert on CORS and the request is being sent cross-domain) when using the $save method my Node.js console shows:
OPTIONS /books 200 1ms - 161b
Using the query() method works fine - the Node console shows:
GET /books 200 1ms - 228b
I've been stuck for several hours at this point, trying variations on the below but it always ends up being an OPTIONS request instead of POST (which is what it should be according to the Angular documentation) for the $save method.
AngularJS Web App
app.js
var libraryApp = angular.module('libraryApp', ['ngResource', 'ngRoute', 'libraryControllers']);
libraryApp.factory('$book', ['$resource', function ($resource) {
return $resource('http://mywebserver\\:1337/books/:bookId', { bookId: '#bookId' });
}]);
controllers.js
var libraryControllers = angular.module('libraryControllers', []);
libraryControllers.controller('BookCtrl', ['$scope', '$book', function($scope, $book) {
...
$scope.addBook = function () {
var b = new $book;
b.isbn = "TEST";
b.description = "TEST";
b.price = 9.99;
b.$save();
};
}]);
Node.js with Express REST API
app.js
var express = require('express'),
books = require('./routes/books'),
http = require('http'),
path = require('path');
var app = express();
...
// enable cross-domain scripting
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
// routing
app.get('/books', books.getAll);
app.get('/books/:isbn', books.get);
// This is what I want to fire with the $save method
app.post('/books', books.add);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
./routes/books.js
...
exports.add = function(req, res) {
console.log("POST request received...");
console.log(req.body.isbn);
};
Tried putting this line in my config function delete $httpProvider.defaults.headers.common["X-Requested-With"]; but no change.
I'm no Angular/Node pro but right now I'm thinking that it's something to do with it being cross domain and, like I said, I'm no expert on CORS.
Thanks in advance.
I know it may be in bad taste to answer my own question but I figured out the problem a few days after posting this.
It all comes down to how browsers manage CORS. When making a cross-domain request in JavaScript that is not "simple" (i.e. a GET request - which explains why the query() function worked), the browser will automatically make a HTTP OPTIONS request to the specified URL/URI, called a "pre-flight" request or "promise". As long as the remote source returns a HTTP status code of 200 and relevant details about what it will accept in the response headers, then the browser will go ahead with the original JavaScript call.
Here's a brief jQuery example:
function makeRequest() {
// browser makes HTTP OPTIONS request to www.myotherwebsite.com/api/test
// and if it receives a HTTP status code of 200 and relevant details about
// what it will accept in HTTP headers, then it will make this POST request...
$.post( "www.myotherwebsite.com/api/test", function(data) {
alert(data);
});
// ...if not then it won't - it's that simple.
}
All I had to do was add the details of what the server will accept in the response headers:
// apply this rule to all requests accessing any URL/URI
app.all('*', function(req, res, next) {
// add details of what is allowed in HTTP request headers to the response headers
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Credentials', false);
res.header('Access-Control-Max-Age', '86400');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
// the next() function continues execution and will move onto the requested URL/URI
next();
});
And then insert these few lines before the Express routing to simply return a HTTP 200 status code for every OPTIONS request:
// fulfils pre-flight/promise request
app.options('*', function(req, res) {
res.send(200);
});
Hopefully this will help anyone who stumbles on this page suffering from the same problem.
I didn´t actually try this, but wouldn´t it be enough to tell the Ressource how to handle the $save request?
$resource('http://mywebserver\\:1337/books/:bookId', { bookId: '#bookId' }, {save: {method: 'POST'});

Resources