Express: res.send() returns an empty object - node.js

I have a setup that uses a MySQL server node and express, I have created an update statement on a SQL file and got it to work with the node via patch request on the postman.
It seems to work and it updates the server, however, when I try to get the recently updated object or even a success message, I get an empty object or nothing, even though the data has been updated.
Can anyone help me get some sort of response on postman?
update.sql
UPDATE [dbo].[RetailerThemes]
SET [Name] = #name,
[PrimaryColourPalette_main] = #primaryColourPalette_main
WHERE [UniqueThemedPageName] = #UniqueThemedPageName
router.js
router.patch("/update", internal, async (req, res) => {
try {
//do the update
const updateRetailer =
await retailerController.updateRetailerConfigByName(req, res)
console.log(`Update Retailer Routes: ${updateRetailer}`)
res.status(200).send(
{updateRetailer}
);
} catch (error) {
console.log(error);
}
});
controller.js
const updateRetailerConfigByName = async (req, res) => {
try {
// Credentials from Request
let retailername = req.retailername;
// Data from Repository
const thisRetailerConfig = await retailerRep.updateRetailerConfigDetails(
retailername
);
console.log( `thisRetailerConfig: ${thisRetailerConfig}`)
} catch (error) {
console.log(error)
}
};
repo.js
async function updateRetailerConfigDetails(retailername) {
try {
//RetailerTheme
const sqlcommanda = await tsql.loadSql(
"tsql",
//"GetRetailerThemeByThemedPageName.sql"
"UpdateRetailer.sql"
);
let pool = await sql.connect(sqlConfig);
const themes = await pool
.request()
.input("name", sql.VarChar(150), "b") // change 80700 to variable
.input("UniqueThemedPageName", sql.VarChar(150), retailername)
.input("primaryColourPalette_main", sql.VarChar(9), "#c00")
.query(sqlcommanda)
;
if (themes.rowsAffected != 1) {
console.log("Retailer not found for ", retailername, sqlcommanda);
return { isFound: false };
}
const theme = themes.recordset[0];
console.log(`The Theme: ${theme}`)
return theme;
} catch (error) {
console.log(error.message);
return {};
}
}
Here is a screenshot of what I get on the postman, the update works but the response is an empty object.

Related

getting photos from one endpoint and saving in another one - nodejs

Basically what I want to do is get photos from another endpoint in spacex API. The photos are on endpoint rockets/rocket_id, and im trying to get them but always gets an empty values.
spaceX api is someone want to see it : https://docs.spacexdata.com/
api = require("./api")
// ...
server.get('/rockets', async (req, res) => {
try {
const { data } = await api.get('/v3/launches');
var lista = [];
for (var i = 0; i < data.length; i++) {
const img = api.get('/v3/rockets/' + data[i].rocket['rocket_id']);
lista.push({
name_rocket: data[i].rocket['rocket_name'],
first_stage: data[i].rocket['first_stage']['cores'][0]['core_serial'],
second_stage: data[i].rocket['second_stage']['payloads'][0]['payload_mass_kg'],
link_patch: data[i]['links']['mission_patch'],
link_video: data[i]['links']['video_link'],
details: data[i]['details'],
launch_site: data[i]['launch_site']['site_name'],
img: img
});
}
return res.send(lista);
} catch (error) {
res.send({ error: error.message });
}
});
server.get('/link', async (req, res) => {
try {
const { data } = await api.get('/v3/rockets/falcon9');
var lista = [];
lista.push({
imagem: data['flickr_images']
});
return res.send(lista);
} catch (error) {
res.send({ error: error.message });
}
});
api.js:
const axios = require("axios");
const api = axios.create({ baseURL: 'api.spacexdata.com', });
module.exports = api;
The issue is coming from the URL. You need "http://" or "https://".
axios.create({ baseURL: 'https://api.spacexdata.com'})
To debug this in the future, consider a try/catch and some logging. The console.log(err) below gave me a much more detailed error that I was able to google.
try{
const result = await api.get(...)
console.log(result)
catch (err) {
console.log(err)
}
Related: StackOverflow issue
In case these were also causing problems, it looks like you're missing an await and some object drilling here:
const img = api.get('/v3/rockets/' + data[i].rocket['rocket_id']);
Should be changed to this:
const { data } = await api.get('/v3/rockets/' + data[i].rocket['rocket_id']);
const imgs = data.flickr_images
You could probably use GET /rockets once instead of GET /rockets/:id in a loop in the first endpoint for performance.
v3 of this API is deprecated. Would suggest moving to v4.

Can not get data from controllers using Express NodeJS

I need to get data from two controllers, but when I call them, returns this error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Plus, I want to know if I must write all the logic inside the try section. This is my code:
[UPDATED from Shariful Islam Mubin's reply]
DataMatching: controller that matches user tags and activities
const { response } = require('express');
const { userData } = require("./userData");
const { getActivities } = require("./activities");
const DataMatching = async (req, res = response) => {
let userTags = [];
let activities = [];
let state = false;
let topActivities= {};
try {
userTags = await userData(req, res);
activities = await getActivities(req, res);
if (userTags.data.tags && activities){
userTags = userTags.data.tags;
state = true;
//doSomething
}
return res.json({
ok: state,
response: topActivities
});
}
catch (error) {
return res.status(500).json({
ok: state,
response: error
});
}
}
module.exports = {
DataMatching
}
userData: controller that gets user data
const { response } = require('express');
const axios = require('axios');
const userData = async (req, res = response) => {
try {
let res_user = await axios.get(somePath, someConfig)
if (res_user.data.success === true) {
return res.json({
ok: true,
response: res_user.data
})
} else {
return res.status(500).json({
ok: false,
error: res_user.data.message
})
}
} catch (error) {
return res.status(500).json({
ok: true,
response: res_user
})
}
}
module.exports = {
userData
}
getActivities: controller that gets activities data
const { response } = require('express');
const Activity = require('../models/activity');
const getActivities = async (req, res = response) => {
const activities = await Activity.find().populate('tags')
try {
return res.json({
ok: true,
activities
});
}
catch (error) {
return res.status(500).json({
ok: false,
error: error
});
}
}
As soon as you call res object, you must have to return it. Because, res or response object sends data to the client. And you cannot return anything after sending a response to the client.
So, you've to write
return res.json({/*.. YOUR_CODE_GOES_HERE ..*/})
and,
return res.status(500).json({/*.. YOUR_CODE_GOES_HERE ..*/})
I also noticed you called other 2 functions which are also responsible for responding to the client. You shouldn't do that.
Try to return response only from the requested controller, which may be DataMatching function in this case.
Youu can wrap all code inside DataMatching function in a try-catch block to handle any exception that occurs in the function.

How to dynamically delete MongoDB entry using API route

I would just like to simply delete a record from a dynamically displayed list. I've tried every permutation of the backend code and ai just can't get it to work.
The backend is called like this:
async function deletePost() {
setLoading(true)
try {
await axios.delete(`/api/delete/${id}`)
alert("Post deleted")
}
catch (err) {
// notify user that something went wrong
console.log(err)
}
finally {
setLoading(false)
}
setLoading(false)
}
And /api/delete/${id} looks like this:
import { connectToDatabase } from "util/mongodb"
export default async (req, res) => {
const { id } = req.query;
console.log(id)
try {
const { db } = await connectToDatabase()
await db.collection("users").deleteOne({'_id': `ObjectId("${id}")`})
res.sendStatus(200).send({ done: true })
}
catch (error) {
return res.json({ error })
}
}
The console log shows the correct post id, the alert in the 'try' frontend code displays, but the dam post just wont delete. Can anyone offer any advice please? I have tried ".deleteOne({'_id': id})" but that does nothing either.
I believe you are searching for a string, instead of the ObjectId, so no documents match.
You can fix it by converting to ObjectId and then using the value converted, .deleteOne.
var ObjectId = require('mongodb').ObjectId;
const { id } = req.query;
const convertedObjectId = new ObjectId(id);
db.collection("users").deleteOne({_id: convertedObjectId })
Actual example from documentation:
try {
db.orders.deleteOne( { "_id" : ObjectId("563237a41a4d68582c2509da") } );
} catch (e) {
print(e);
}
Reference: MongoDB Documentation - Delete One.
Fixed problem:
app.delete("/cars/:id", async (req, res) => {
const carsId = req.params.id;
const query = { _id: ObjectId(carsId) };
const result = await carCollection.deleteOne(query);
res.send(result);
});

Retrieve the GET query string parameters using Express

I seem to have troubles on getting the query string parameter on my Postman.
First, I wanted to get all of the game types API by using the url of:
localhost:3000/api/gameType/dota2
Here is the code below:
const router = require('express').Router();
const GameTypeRepository = require('../../repository/GameTypeRepository');
router.get('/', async (req, res) => {
try {
const game_types = await GameTypeRepository.findByName(req.query.name);
res.json(game_types);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
GameTypeRepository.js
const BaseRepository = require('../../../shared/repository/BaseRepository');
const GameType = require('../models/GameType');
class GameTypeRepository extends BaseRepository {
constructor(model) {
super(model);
}
findByName(name, fields) {
const options = {
where: { name }
};
if (!!fields && fields) {
options.attributes = fields;
}
return this.model.findOne(options);
}
}
module.exports = new GameTypeRepository(GameType);
But when I execute the url to my Postman, I get this log on my terminal that says:
Executing (default): SELECT `id`, `name`, `description` FROM `game_types` AS `game_types` WHERE `game_types`.`id` = 'dota2';
Which should be 'name' = 'dota2'
Any ideas on how to work with this? TYIA.
I have solved this problem by adding /type in my router.get('/type/:name,
router.get('/type/:name', async (req, res) => {
try {
const game_types = await GameTypeRepository.findByName(req.params.name);
res.json(game_types);
} catch (error) {
res.sendStatus(404);
}
});

Mongodb not updating the data after put request returns successful

In trying to use the objectid in the mongoose schema as a reference to do a put to update a document in a collection. The console logs its as a success but when I refresh the page or look in the mongo shell nothing changes.
Heres the put in the expressjs router:
router.put('/messageupdate/:empId', function (req, res) {
var values = req.body;
console.log(values);
var empId = req.params.empId;
console.log(empId);
Message.update({empId: empId}, values, function(err, values) {
if (!err) {
res.json("okay");
} else {
res.write("fail");
}
});
})
Heres the service method:
updateServiceWithId(message: Message): Observable<any> {
console.log(message);
const body = JSON.stringify(message);
console.log(body);
const headers = new Headers({'Content-Type': 'application/json'});
return this.http.put('http://localhost:3000/messageupdate/:empId', body, {headers: headers});
}
Heres the client side method that triggers the put:
onUpdateMessage() {
var retVal = confirm("Do you want to continue ?");
if( retVal == true ){
const message = new Message(this.fname,this.lname,this.empId,this.number,this.occu);
console.log(this.fname);console.log(this.lname);
console.log(this.empId);console.log(this.occu);
this.messages.push(message);
this.messageService.updateServiceWithId(message)
.subscribe(
() => console.log('Success!'),
error => console.error(error)
);
}
else{
alert("Edit cancled!");
return false;
}
}

Resources