Loopback timeout(no response from server) when make a time consume request - node.js

I have a request which processes thousands of data. So sometimes It takes more then 5 minutes to complete.
But unfortunately loopback returns timeout(no response from server) before process is completed.
In nodejs request. You can remove request timeout for specific request by below code.
request.setTimeout(0)
Can anyone tell me how can i do this for loopback remote method?

It was quite easy then it looked like.
All i had to do is pass http req object in my remote method and then set timeout to 0.
Visit.remoteMethod(
'caculateDistance',
{
description: 'Calculate distance from beacon using rssi',
accepts: [
{ arg: "req", type: "object", http: { source: "req" } },
{ arg: 'activationId', type: 'string', required: true }
returns: { arg: 'data', type: 'Object', root: true },
http: { verb: 'patch', path: '/:activationId/calculate-distance' },
}
);
Visit.caculateDistance = function (httpReq, activationId, callbackFn) {
httpReq.setTimeout(0);
/////calculations....
});
Thanks anyway!

I am not quite sure of this but you can give it a try as i feel this might work
You can create a interceptor for that particular route or all the routes in the server.js file.
app.all('/api/*', function(req, res, next){
request.setTimeout(0); // this is the statement and pass it to the next middle ware func.
next();
});
If not you can also use a remote method for that route and add the
same there.
Update
If you want it for a single api just use
app.all('<exact api path>', function(req, res, next){
request.setTimeout(0); // this is the statement and pass it to the next middle ware func.
next();
});

Related

How to access data on server side from AJAX post request

I have tried reading a lot of posts on this but none have really helped me. I don't get how to access the data I am sending from a post request. For context, I have a .ejs html file where I am making an asynchronous post request to the server. This is the code for that:
$("#commentButton" + thisPostId).click(function () {
$.ajax({
type: "POST",
url: "/comment",
data: {
comment: $("#commentInput" + thisPostId).val(),
postId: $("#postIdInput" + thisPostId).val()
},
success: function (data) {
if (data.success) {
let asyncComment = "<p>whatsupbro</p>";
$("#li" + thisPostId).append(asyncComment);
} else {
// ADD BETTER ERROR IMPL
alert('error');
}
}
});
On the server side, I want to retrieve the arguments in "data". This is what I have so far. I have tried so many things, like doing req.data.comment, req.comment, etc. Below is the start of my node.js function that is supposed to get the request and do some stuff with it. What matters is I want the comment in commentInfo and postId in commentInfo to be what I am sending in the post request as "comment" and "postId". I really am just not sure how to access this data (req.body.mycomment doesn't work either).
var createComment = function(req, res) {
var commentInfo = {
comment: req.body.myComment,
username: req.session.username,
commentId: new Date().getTime(),
postId: req.body.postId
};
console.log(req['comment']);
Thanks for the help. If there is anything else I should add let me know.
You need appropriate middleware to actually read the body of the POST request and to then parse it and place the contents into req.body.
Assuming you are using Express, then you need one of these placed before the route that receives the POST:
app.use(express.json()); // for application/json content-type
app.use(express.urlencoded()); // for application/x-www-form-urlencoded content-type

Express: express-unless breaking with simple example

https://github.com/jfromaniello/express-unless
Two questions..
Any idea why this does not work?
It appears this library is abandoned. Are there any other alternatives?
handleExpiredTokens.unless({
path: [{
url: '/foo',
methods: ['POST']
}]
});
function handleExpiredTokens(err, req, res, next) {
// stuff
}
handleExpiredTokens.unless = unless;
module.exports = handleExpiredTokens;
handleExpiredTokens runs on every request including POST /foo
getting a protectWithCSRF.unless is not a function

Loopback crash in callback when calling on resetPasswordRequest more then one

I am trying to make my own remote method to reset a password. The user just has to put the email in the path and the server will send the accessToken as response.
MyUser.remoteMethod('requestPasswordReset',
{
http: {path: '/reset/:usermail', verb: 'post'},
accepts: [{arg: 'usermail', type: 'string', required: true, http: {source: 'path'}}],
returns: {root: true, type: 'object'},
description: 'Allows Users to request a password reset, returns an error if the specified email does not exist'
}
);
MyUser.requestPasswordReset = function (usermail, next) {
MyUser.resetPassword({email: usermail}, function (err) {
if (err) {
next(err);
}
else {
MyUser.on('resetPasswordRequest', function (info) {
console.log('next will be executed, but crashes the second time');
next(null, info.accessToken.id);
});
}
})
};
The first time I make a request to /reset/:usermail everthing works perfect, but the second time I run the request the application crashes with follow error
Can't set headers after they are sent
I know this error typically occurs when calling more callbacks.
If I give an other error argument to the callback for. ex.next('abc') in stead of null next(null, info.accessToken.id); the application doesn't crashes
I have found the cause of the error. MyUser.on('resetPasswordRequest', function (info)) is making a listener. So every time requestPasswordReset is called, a new listener is created. When the user makes the request for the second time, there are two listeners and they both send a response. Putting MyUser.on('resetPasswordRequest', function (info)) in the root of the js file lost the problem.

Efficient way to handle error cases in REST Apis

I am writing a REST API in node.js. I expect at max 5 parameters to arrive in my GET Request. If there are unidentified parameters I wish to send 400 Bad Request.
Currently I am handling it in the following way:
server.route({
method: "GET",
path : "/test",
handler : function (request, reply) {
if (request.query.a || request.query.b || request.query.c || request.query.d || request.query.e)
{
// do some processing
}
else {
reply("No valid parameters").code(400);
}
}
});
Right now this does not handle the case if there are some valid and some invalid cases. I can solve that by using more if conditions. But I was just wondering if there is a standard or more efficient method which is used by developers
Hapi has built-in validation support. You can use Joi to validate the query:
var Joi = require('joi');
...
server.route({
method: 'GET',
path: '/test',
config: {
validate: {
query: {
a: Joi.string(),
b: Joi.string(),
c: Joi.string(),
d: Joi.string(),
e: Joi.string()
}
}
},
handler: function (request, reply) {
return reply('ok');
}
});
If you send a request to /test?g=foo, then you get the following response:
{ statusCode: 400,
error: 'Bad Request',
message: '"g" is not allowed',
validation: { source: 'query', keys: [ 'g' ] } }
You can manually do this, but you are better off using a REST framework like mongoose or loopback (strongloop) to do the validation and error handling and other boilerplate code like model binding.
Perhaps you should consider the use of a framework, like Express, to use a middleware which is simply code you can reuse in different routes.
A simple pseudo/example looks like this
var app = express();
// a middleware with no mount path; gets executed for every request to the app
app.use(function (req, res, next) {
if (req.query.a && req.query.b) {
return next()
}
else {
return res.status(400).send('Not OK');
}
});
// a route and its handler function (middleware system) which handles GET requests to /user/:id
app.get('/user/:id', function (req, res, next) {
return res.send('OK');
});
// a different route, same middleware
app.get('/customer/:id', function (req, res, next) {
return res.send('OK');
});

How do I send a JSON object from server to my view using Node/Express and Angular

I'm trying to build a webapp and I'm stuck at this part: I want to use Contentful to serve my data. Since it's a RESTful service I thought it would be relatively easy to use. They also have a node module, to make my life even easier. Unfortunately, I can't get the data in my view. After hours of googling and on here I've come up with this, but unfortunately it isn't working.
Server:
var client = contentful.createClient({
accessToken: 'token',
space: 'id',
secure: true,
host: 'cdn.contentful.com'
});
var log = console.log.bind(console);
var movies = client.entries({
'content_type': '207BVEIb7GcYeCumc2Cmk4'
}).then(log, log);
app.get('/api/data/movies', function(req, res) {
res.json(movies);
});
JSON:
[ { sys:
{ id: '6nEC5yrZwA0YoikiMeQYky',
revision: 1,
type: 'Entry',
locale: 'en-US',
contentType: [Object],
createdAt: Mon Sep 15 2014 22:16:10 GMT+0200 (CEST),
updatedAt: Mon Sep 15 2014 22:16:10 GMT+0200 (CEST),
space: [Object] },
fields: { movieTitle: 'Guardians of the Galaxy' } } ]
My Controller:
angular.module('MyApp')
.controller('MainCtrl',['$scope', '$http', function($scope, $http) {
$http.get("/api/data/movies").success(function(data){
$scope.movieTitle = data.movieTitle;
alert(JSON.stringify(data));
});
}]);
I want to get the movieTitle into my view, but the retrieved data is this:
{"isFulfilled":true,"isRejected":false}
The issue is in your server side code. This example code:
var movies = client.entries({
'content_type': '207BVEIb7GcYeCumc2Cmk4'
}).then(log, log);
Is assigning a Promise to the movies variable. Unfortunately, it's a promise for the result of the log function, so you should change it to this:
var movies = client.entries({
'content_type': '207BVEIb7GcYeCumc2Cmk4'
});
The next problem is that you are never calling then on the promise to get it's resolved value. The simplest way to deal with this (assuming you never want the movie list to be refreshed) is to just call then inside your request handler:
app.get('/api/data/movies', function(req, res, next) {
movies.then(res.json, next);
});
This sets up res.json to run if the movies promise resolves successfully, and next to handle any errors.
If you want the list of movies to be re-retrieved on each request, then you could move the client.entries call into your request handler as well:
app.get('/api/data/movies', function(req, res, next) {
client.entries({
'content_type': '207BVEIb7GcYeCumc2Cmk4'
}).then(res.json, next);
});
One final note: it's also possible (and encouraged) to perform these requests directly from the browser, so you wouldn't even need the express app to proxy requests.

Resources