ERR_CONNECTION_RESET upon Backbone.save() to update model by Mongoose - node.js

Please, tell me what I am doing wrong:
My backbone view creates and saves document in mongodb by mongoose and uses the data in the view allright upon the backbone save() and fetch() methods. But when i use Backbone model.save({option: 'modified'}); with route.put() on the backend, jquery fires ERR_CONNECTION_RESET. I tried lots of things i found in the net, but they did not work. Maybe i need to use ajax.Prefilter or something of this kind, but i do not know exactly what to do.
the piece of code in backbone view firing update is:
this.user.save({ options: 'modified' }, {
wait: true,
success: function(model, response) {
console.log('saved');
},
error: function(model, error) {
console.log(error);
}
});
in router index.js
router.put('/user/:id', require('./user').put);
it works because on GET route it works perfectly well.
in user.js
exports.put = function(req, res) {
var query = { _id: req.params.id };
User.update(query, { options: req.body.options }, function(){
res.send('ok');
});
};
I also experimented a lot with id or _id, and various ways of using mongoose update, like
User.findOne({ _id: req.params.id }, function (err, doc){
if (err) return console.log(err);
doc.options = req.body.options;
doc.save(function(err){
res.json(doc);
});
});
and others such like. It did not work. Here is the error (it must be the key to my problem, but i cannot figer it out)
Synchronous XMLHttpRequest on the main thread is deprecated because of
its detrimental effects to the end user's experience.
PUT http://localhost:3000/user/56349be42b19125405c2d66a
net::ERR_CONNECTION_RESET

It was silly: maximum req size exceeded. Cured by setting
app.use(bodyParser.json({limit: '16mb'}));
app.use(bodyParser.urlencoded({ limit: '16mb', extended: true }));

Related

Getting "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client" even though I only have one res.render()

I am using Mongoose and Express/Node.js to build a simple api, but when I try to click on the "Read More" link (which uses Express routing parameters), I get "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client". I understand that this happens when multiple responses are sent for a single post, but I can't for the life of me find where this is happening.
My code is below:
Post.find({}, function(err, foundPosts) {
res.render("home", {homeStartingContent: homeStartingContent, posts: foundPosts});
res.redirect("/");
});
})
app.get("/compose", function(req, res) {
res.render("compose");
})
app.post("/compose", function(req, res) {
const post = new Post({
title: req.body.title,
body: req.body.newPost,
teaser: req.body.newPost.substring(0,99) + "...",
});
// save the post and refresh home page to display most recent post
post.save(function(err) {
if(!err) {
res.redirect("/");
}
});
});
// express routing parameters; uses whatever comes after : to decide what to do
app.get("/posts/:postId", function(req, res) {
const requested = _.lowerCase(req.params.postId);
Posts.findOne({_id: requested}, function(err, post) {
res.render("post", {post: post});
});
});```
I'm pretty sure the issue is in the last app.get("/posts/:postID"...), but I can't figure it out.
I understand that this happens when multiple responses are sent for a single post
It also happens when you send more headers after already having sent a response. And that's what you do by calling first res.render and then res.redirect near the top of your code snippet. Also, this does not make sense, because the redirection will prevent the user from reading what you rendered before.

Get method - Why can't I return the values from an Oracle view?

I searched for a good example of Node+Express+Oracle. I need to read values from an Oracle view to create the response to a GET operation.
Most examples does not use "Express" (my choice of framework) and simply log the database information. Here are some of the best I found : from Express, from Oracle 1, from Oracle 2
Here is the one I preferred to base my code on. I like it because it includes Express, and actual manipulation of the response data. Sadly, it still does not work for me. And I am wondering what the issue is.
I think I understand the asynchronous nature of the JavaScript language (ie: callbacks), and I am beginning to suspect my problem might be tied to : A stupid variable name snafu, My version of Oracle (12c) or the fact that the source is a view (replicated from another schema).
I tried the following code in many other forms (including async functions), and also tried to switch from node 10 to 11... no changes.
Any help would be welcomed.
As of now, the code "works", in the sense that the row data from the database is printed on screen, but the response in Postman (my test tool) is empty, with no http error code... just like the connection would have been cut before replying.
Note the commented, misplaced response code, that returns a response if uncommented (and then crashes the program since the header is written twice).
Here is the code.
It is based on this project/file (and simplifed):
var express = require('express');
var oracledb = require('oracledb');
var app = express();
var connAttrs = {
"user": "user",
"password": "pass",
"connectString": "some_host/SCHEMANAME"
}
// Http Method: GET
// URI : /myObj
app.get('/myObj', function (req, res) {
"use strict";
oracledb.getConnection(connAttrs, function (err, connection) {
if (err) {
// Error connecting to DB
res.set('Content-Type', 'application/json');
res.status(500).send(JSON.stringify({
status: 500,
message: "Error connecting to DB",
detailed_message: err.message
}));
return;
}
// THIS works if uncommented. This is obviously the wrong place to put this.
//res.contentType('application/json').status(200);
//res.send("Test.1.2");
connection.execute("SELECT * FROM SCHEMA.SOMEVIEW", {}, {
outFormat: oracledb.OBJECT // Return the result as Object
}, function (err, result) {
if (err) {
res.set('Content-Type', 'application/json');
res.status(500).send(JSON.stringify({
status: 500,
message: "Error getting the user profile",
detailed_message: err.message
}));
} else {
//log first row... THIS WORKS !
console.log(result.rows[0]);
//This does not work, like if "res" could not be touched here !!!
res.contentType('application/json').status(200);
res.send(JSON.stringify(result.rows[0]));
}
// Release the connection
connection.release(
function (err) {
if (err) {
console.error(err.message);
} else {
console.log("GET /myObj: Connection released");
}
});
});
});
});
var server = app.listen(3000, function () {
"use strict";
var host = server.address().address,
port = server.address().port;
console.log(' Server is listening at http://%s:%s', host, port);
});
Here is a representation of the console:
{ field1: 'some data',
field2: 'some more data' }
GET /myObj : Connection released
And here is the behaviour in postman:
ARGGG ! It was a simple timeout ! Postman DOES mention it as a possibility (see image), but I would like the program to make it flash it bright letters !!!
Closing the question. Sorry for the disturbance.

Define/Use a promise in Express POST route on node.js

I currently have a POST route defined in an Express Node.js application as so:
var locationService = require("../app/modules/locationservice.js");
app.post('/createstop', isLoggedIn, function(req, res) {
locationService.createStop(res, req.body);
});
(for this question, please assume the routing in & db works.. my record is created on form submission, it's the response I am struggling with)
In the locationservice.js class I then currently have
var models = require('../models');
exports.createStop = function(res, formData) {
models.location.build({ name: formData.name })
.save()
.then(function(locationObj) {
res.json({ dbResult : locationObj });
});
};
So as you can see, my route invokes the exported function CreateStop which uses the Sequelize persistent layer to insert a record asynchronously, after which I can stick the result on the response in the promised then()
So at the moment this only works by passing the response object into the locationservice.js method and then setting res.json in the then() there. This is sub-optimal to me with regards to my service classes, and doesn't feel right either.
What I would like to be able to do is "treat" my createStop method as a promise/with a callback so I can just return the new location object (or an error) and deal with it in the calling method - as future uses of this method might have a response context/parameter to pass in/be populated.
Therefore in the route I would do something more like:
var locationService = require("../app/modules/locationservice.js");
app.post('/createstop', isLoggedIn, function(req, res) {
locationService.createStop(req.body)
.then(dataBack) {
res.json(dataBack);
};
});
Which means, I could call createStop from else where in the future and react to the response in that promise handler. But this is currently beyond me. I have done my due diligence research, but some individual expert input on my specific case would be most appreciated.
Your locationservice.js could look like that
exports.createShop = function(data){
// here I have used create instead of build -> save
return models.location.create(data).then(function(location){
// here you return instance of saved location
return location;
});
}
And then your post() method should be like below
app.post('/createstop', isLoggedIn, function(req, res){
locationService.createShop(req.body).then(function(location){
// here you access the location created and saved in createShop function
res.json(location);
}).catch(function(error){
// handle the error
});
});
Wrap your createStop function with a promise like so:
exports.createStop = function(res, formData) {
return new Promise(function(resolve, reject) {
models.location.build({ name: formData.name })
.save()
.then(function(locationObj) {
resolve({ dbResult : locationObj });
});
//in case of error, call reject();
});
};
This will allow you to use the .then after the createStop within your router.

Node js (Express) freezing in mongodb operation

I have a code that accepts a post request and inserts a string into mongodb database.
app.post('/post_comment', function(req, res) {
Predicts.findOne({'id': parseInt(req.body.id)}, function(err, card) {
console.log('')
console.log(card)
console.log('')
if (card) {
Users.findOne( { 'userid': req.user ? req.user.userid : undefined }, function(err, user) {
console.log(user)
console.log('')
Predicts.update({'_id': card._id},
{$push : {comments: {login: user ? user.login : 'anonymous', content: '123'}}},
function(err, card1) {throw(err);
console.log('---')
console.log(card1);
})
})
}})
res.redirect('back')
})
This code result in total freezing of node process. Only restart of the node process can help.
Debugging shows, that first four console.log operations work as supposed, but console.log('---') doesn't happen. This means that Predicts.update doesn't work, but it is really works, and I can see the result of this request in the database. What's the hitch?
Upd: I have replaced Predicts.update to Predicts.find but result is still the same. Collback doesn't work, and node process freezing.
Upd2: I established that node is not freezing, but returns only content that doesn't require to mongodb.
According to the node-mongodb docs, the update function looks like:
collection.update(criteria, objNew, options, [callback]);
So if you want to use a callback, it should be the 4th parameter, and the 3rd should be your options (e.g. multi:true) or else {}.

Unit Testing Express Controllers

I am having trouble unit testing with Express on a number of fronts, seems to be a lack of documentation and general info online about it.
So far I have found out I can test my routes with a library called supertest (https://github.com/visionmedia/superagent), but what if I have broken my routes and controllers up, how can I go about testing my controllers independently of their routes.
here is my test:
describe("Products Controller", function() {
it("should add a new product to the mongo database", function(next) {
var ProductController = require('../../controllers/products');
var Product = require('../../models/product.js');
var req = {
params: {
name: 'Coolest Product Ever',
description: 'A very nice product'
}
};
ProductController.create(req, res);
});
});
req is easy enough to mockup. res not so much, I tried grabbing express.response, hoping I could just inject it but this hasn't worked. Is there a way to simulate the res.send object? Or am I going the wrong way about this?
When you are testing your routes, you don't actually use the inbuilt functions. Say for example, ProductController.create(req, res);
What you basically need to do is, run the server on a port and send a request for each url. As you mentioned supergent, you can follow this code.
describe("Products Controller", function() {
it("should add a new product to the mongo database", function(next) {
const request = require('superagent');
request.post('http://localhost/yourURL/products')
.query({ name: 'Coolest Product Ever', description: 'A very nice product' })
.set('Accept', 'application/json')
.end(function(err, res){
if (err || !res.ok) {
alert('Oh no! error');
} else {
alert('yay got ' + JSON.stringify(res.body));
}
});
});
});
You can refer to superagent request examples here.

Resources