500 Internal Server Error: cannot update user in mongoose - javascript

I am trying to run a put function to update a user in my mongoDB, but I am getting a 500 Internal Service error. I am using the angular-fullstack generator
I use this resource in my controller:
update(User) {
User.$update();
}
Here are the functions I call in the backend to try and put the data everything seems to be working fine except for when I call saveUpdates, it seems like that is triggering the 500 error.:
function handleError(res, statusCode) {
statusCode = statusCode || 500;
return function(err) {
res.status(statusCode).send(err);
};
}
// this seems to be the function giving me the problem.
function saveUpdates(updates) {
return function(entity) {
var updated = _.merge(entity, updates);
return updated.saveAsync()
.spread(updated => {
return updated;
});
};
}
function respondWithResult(res, statusCode) {
statusCode = statusCode || 200;
return function(entity) {
if (entity) {
res.status(statusCode).json(entity);
}
};
}
function handleEntityNotFound(res) {
return function(entity) {
if (!entity) {
res.status(404).end();
return null;
}
return entity;
};
}
export function updateUser(req, res) {
if (req.body._id) {
delete req.body._id;
}
User.findByIdAndUpdate(req.params.id)
.then(handleEntityNotFound(res))
.then(saveUpdates(req.body))
.then(respondWithResult(res))
.catch(handleError(res));
}
I have tried following recommendations on this page for angular-full stack, such as changing ._merge to ._extend to no avail.

I answered my question:
Angular-full stack utilizes lodash, so if you want to make put requests using ._merge like this:
function saveUpdates(updates) {
return function(entity) {
var updated = _.merge(entity, updates);
return updated.saveAsync()
.spread(updated => {
return updated;
});
};
}
then you need to import lodash into the user.contoller set up by the angular-fullstack yeoman generator.
import _ from 'lodash';

Related

how to cleanly handle errors in nextjs getStaticProps

I'm very busy at the moment with building my first Next.JS application (Next and Strapi). Now everything is working but i'm curious about what the best way is to implement error handling when using getStaticProps.
I tried a few things myself (passing multiple props etc, but that all didn't work (typical unserialized JSON error). The thing I want to achieve is an error message on the page itself (e.g. /about) that no data was found. With an error message attached (statusCode).
I hope it's possible, I did a lot research and found: https://github.com/vercel/next.js/pull/17755 this. But it's not exactly what I'm looking for.
You can create custom 404 and 500 error pages. There is an option to show the statusCode however, you can tell Next to use the 404 page by returning notfound: true in getStaticProps.
If you return notfound: true, the statusCode will always show the 404 page, and you know the status code will be 404.
Here is a example of catching errors in getStaticProps- this will generate your page or show your custom error page that is designed to your specifications.
export const getStaticProps = async () => {
try {
const { data, errors } = await someQuery();
if (errors || !data) {
return { notFound: true };
}
return { props: { data } };
} catch () {
return { notFound: true };
}
};
A not so obvious additional use case of notFound is to use it to exclude a directory or page from production. The below check will skip the whole page or directory during next/export (SSG). This check be used to produce development only static pages.
If a single page in a directory has the check below, that page is skipped during the build process. If every page in a directory has the check - the whole directory will be skipped, including the folder.
export const getStaticProps = async () => {
if (process.env.NODE_ENV === 'production') {
return { notFound: true };
}
...
};
Make sure you don't include the routes you don't want built in getStaticPaths too.
This worked for me.
api.js
export async function fetcher(url, options = {}) {
try {
let response;
if (!options) {
response = await fetch(url);
} else {
response = await fetch(url, options);
}
const data = await response.json();
return data;
} catch (error) {
return {
notFound: true,
};
}
}
in pages/index.js
import { fetcher } from "/lib/api";
...
export async function getStaticProps() {
const { data, notFound } = await fetcher(
`${process.env.NEXT_PUBLIC_STRAPI_API}/homepage?publicationState=live&populate[seo][populate]=%2A&populate[pageHeading][populate]=%2A&populate[socialMedia][populate]=%2A&populate[block][populate]=%2A`
);
if (notFound) {
return {
notFound: true,
};
}
return { props: { data } };
}

Jest test is not passing through any parameters (becomes 'undefined')

EDIT: The variable username becomes undefined for some reason. I tried passing other variables too, but none of them appear as they should with console.log().
I have a jest file ("index.test.js") for testing my API:
'use strict';
const request = require('supertest');
const app = require('./index');
describe('Test login', () => {
test('POST /login', () => {
return request(app)
.post('/login')
.send({username: 'preset1'}) //suggestion by #acincognito
.expect(301)
});
});
and a corresponding POST route in my nodejs file ("index.js"):
...
function contains(arr, key, val) {
for (var i = 0; i < arr.length; i++) {
if(arr[i][key] === val) {
return true
};
}
return false;
}
app.post("/login", async (req, res) => {
try {
var username = req.body.username;
const data = await readFile("results.json");
var json = JSON.parse(data);
if (contains(json, "name", username) === true){
...
return res.redirect(301,"/");
} else {
return res.redirect(401,"/");
}
} catch (error) {
return res.redirect("/");
}
});
JSON file ("results.json") has the following format:
[
{"name":"preset1","otherstuff":[]},
...
{"name":"preset5","otherstuff":[]}
]
I am getting the error message :
expected 301 "Moved Permanently", got 401 "Unauthorized"
NOTE: When I run the code manually on a local server, everything works as it should which seems to contradict the output of the test.
Add a console.log(json) to your app.post function to see what gets parsed.
After looking at the docs for supertest: apparently .set('username','preset1') is for setting headers in your request, but according to your app.post username is inside the request's body, therefore try .send({username: 'preset1'}) .
I needed to encode a Javascript Object into a string.
function serialize(obj){
return Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
}
// Code from : https://stackoverflow.com/questions/1714786/query-string-encoding-of-a-javascript-object
Instead of:
.send({username: 'preset1'})
Replace with:
.send(serialize({username: 'preset1'}))
Edit: This did not work for all parameters.

What would be necessary to code the callback function to receive the access token?

I am trying to retrieve the access token from an API (https://github.com/Axosoft/node-axosoft/)
To receive an access token we have to follow this process:
var axo = nodeAxosoft(axosoftUrl, credentials);
axo.Api.getLoginUrl(function(url) {
// open browser using authorizationUrl and get code parameter from
//redirected Url after login
var code = 'code received from redirect';
axo.Api.exchangeCodeForToken(code);
});
As I did not understood exactly how to get the code following that example nor what is the url parameter on getLoginUrl, I did it on my own.
I have a login route that redirects the user to the axosoft website for authentication and redirects the user to the /authorization-process route on my application.
On the /authorization-process I get the code returned by the login and call a function that should get the access token by calling:
axo.Api.exchangeCodeForToken(code);
Code:
var axosoft_code = req.query.code;
console.log(axosoft_code);
var token = request.exchangeAuthCodeForAccessToken(axosoft_code)
.then(function(token)
{
res.send(token);
})
The Method:
var connection = nodeAxosoft(client_url, credentials);
return new Promise(function(resolve, reject){
console.log("CODE: ", axosoft_code)
var token = connection.Api.exchangeCodeForToken(axosoft_code, function(token){
console.log(token);
resolve(token)
})
The problem is that returns null
I had a look at the API lib api.js and found that:
https://github.com/Axosoft/node-axosoft/blob/master/lib/api.js
function exchangeCodeForToken(code, callback) {
_credentials.code = code;
_access_token = '';
_authenticateCredentails(function (err) {
if (!err) {
callback(null, _access_token);
} else {
callback(err);
}
})
}
So I have two questions:
Does anyone has an Idea what am I doing wrong?
What would be necessary to code the callback function?
The method expects a callback function but I don't really know how to do it.
EDIT:
return new Promise(function(resolve, reject){
var token = connection.Api.exchangeCodeForToken(axosoft_code, function(response,err){
if(!err){
console.log("token",response)
resolve(token);
}
else{
console.log("error",err)
resolve(token);
}
});
})
OR
var token = connection.Api.exchangeCodeForToken(axosoft_code, function(response,err){
if(!err){
console.log("token",response.body)
return response.body;
}
else{
console.log("error",err)
return err;
}
});
I am giving to my callback function two args (response and err), my problem is that I am falling at the else condition.
The output of err is something similar to a token though the documentation here shows that it should be like that:
{
"error" : "invalid_request",
"error_description" : "One or more parameters are missing: client_secret"
}
Another point is that the page is frozen waiting for something to happen but nothing happens.
Given that this is the input:
function exchangeCodeForToken(code, callback) {
_credentials.code = code;
_access_token = '';
_authenticateCredentails(function (err) {
if (!err) {
callback(null, _access_token);
} else {
callback(err);
}
})
}
You should format your call as:
exchangeCodeForToken(axosoft_code, function(err, response) {
if (err) {
// Deal with error
} else {
// Deal with response
}
}
Node functions often pass through error variables first so that you have to receive them, which is considered good practice.

Trying to create a function nodejs express

Im trying to create a function so i dont use the same code again and again but i keep getting internal error.I get the data and then i get the internal error so if i change something i need to refresh the page to be updated.I cant understand why i get the error.Here is the error
GET http://localhost:3000/api/pages 500 (Internal Server Error)
Object {data: "", status: 500, config: Object, statusText: "Internal Server Error"}
code:
function Get(some,that,res){
return some.find(function(err,that) {
if (!err) {
return res.send(that);
} else {
return res.send(500, err);
}
});
};
router.get('/pages', sessionCheck, function() {
Get(Page,pages,res);
});
UPDATE: i might doing something wrong so lets take it from the start.How can i create a function that do that so i dont reuse the same code again and again.
router.get('/pages', function(request, response) {
return Page.find(function(err, pages) {
if (!err) {
return response.send(pages);
} else {
return response.send(500, err);
}
});
});
and here is my full code
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Page= require('../models/page.js');
var bcrypt = require('bcrypt-nodejs');
function Get(some,that,response){
return some.find(function(that,err) {
if (!err) {
return response.send(that);
} else {
return response.send(500, err);
}
});
};
router.get('/pages', sessionCheck, function(request,response) {
Get(Page,pages,response);
});
router.METHOD will first call your function sessionCheck. You will then need to call next() within sessionCheck to call the next function, in which you are not defining any parameters (typically you would define req, res).
If you are using express your function call should probably be:
function someGetFunc(req, res, next)
You have res as the third parameter, so that might be the problem.
Now the Get function you have above is internal to an anonymous function that doesn't take in params, so what you are passing into it are either undefined or reference global scope variables.
ok i fixed it like that i shouldnt have left the function empty it required res,req
function Get(Some,that,res){
return Some.find(function(err,that) {
if (!err) {
return res.send(that);
} else {
return res.send(500, err);
}
});
};
router.get('/pages', sessionCheck,function(req,res) {
Get(Page,pages,res);
});

Meteor: visible on console (server), sends undefined to client

Finally diving into meteor. I have a small problem regarding http get requests.
On the client a simple call is executed to get data from the server.
if (Meteor.isClient) {
Template.liveprice.helpers({
price: function() {
Meteor.call('getPrice', function(error, response) {
if (error) {
return error;
} else {
return response;
}
})
}
})
}
On the server data is retrieved from a live and public API. It works fine on the server, but an undefined result is send back to the client. What am I missing here?
if (Meteor.isServer) {
Meteor.methods({
getPrice: function() {
var url = 'https://www.bitstamp.net/api/ticker/';
var req = HTTP.call('GET',url,function(error, result) {
//console.log(result);
if (result.statusCode == 200) {
var last = result.data.last;
console.log(last);//this shows the desired result in the server's console
return last;//sends back undefined to the client
} else {
return error;
}
});
}
})
}
#epascarello is right. Luckily, Meteor's HTTP works synchronously as well thanks to fibers. Try this:
Meteor.methods({
getPrice: function() {
var url = 'https://www.bitstamp.net/api/ticker/';
var result;
try {
result = HTTP.get(url);
check(result.data.last, String);
return result.data.last;
} catch (error) {
throw new Meteor.Error('get-price-failed', 'Could not retrieve the price.');
}
}
});

Categories

Resources