Why #Body() in Post request is not working properly? [Nest.js] - nestjs

I'm starting to learn Nest.js, so I am following an Academind Tutorial (link).
My code is not working as expected when I try to get the body variable with the #Body() decorator in the POST request. Following this part of the code in products.controller.ts
#Post()
async addProduct(#Body() body: Product) {
console.log(body);
const generatedId = this.productService.insertProduct(body.title, body.description, 5.99);
return generatedId;
}
In the terminal the output is just an empty object: {}
I have searched for other examples to look at how to do it properly. I found a tutorial in DigitalOcean where they also use #Body in the POST request; they leave a the end of the tutorial a repo with the example. This example is neither working for me.
I just did a small change in addBook() function on book.service.ts file for returning the new book instead of all books
addBook(book): Promise<any> {
return new Promise(resolve => {
this.books.push(book);
// resolve(this.books);
resolve(book);
});
}
I do the following POST request from Postman but an empty object is being the response.
All other HTTP requests are working just nice, except for the POST one.
Any ideas what could be wrong with the code? Thanks in advance. 😃

You're sending form-data which NestJS does not correctly parse by default. You can use application/x-www-url-form-encoded or application/json along with the raw option in Postman. The JSON body would look like so:
{
"id": "7",
"title": "Whatever Title",
"desscription": "whats doc",
"author": "Me"
}
And then your server will recognize the body properly. The other option would be to add in a body parser that properly parses form-data. There are several options out there like multer, form-parser, formidable, and others.

i also faced the same issue, first i tried to send the data as raw format but it didn't worked properly, then i used x-www-urlencoded tab on postman and it solved the issue for me.
Edit: i had a typo in raw format, now it's working fine!

Remove the type (Product) for body works for me.

Not related to the example but related to the title.
If you use ValidationPipe with whitelist=true on your app.
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
whitelist — removes any property of query that is not part of DTO.
And do not use decorators from the 'class-validator' on your DTO object
import { IsNotEmpty, MaxLength } from 'class-validator';
export class Cat {
#MaxLength(200)
#IsNotEmpty()
name: string;
age: number; // would be removed by ValidationPipe when whitelist=true
}
The properties would be removed. And you will get the empty object.

Related

How do I use the the post method with fetch and koa?

This is a function on my front-end that makes the request.
function postNewUser(){
fetch(`http://12.0.0.1:8080/users/test`, {
method: 'POST',
body: {nome: name, email: "test#test.com.br", idade: 20}
})
}
This is my back-end code to receive the request.
router.post('/users/:id', koaBody(), ctx => {
ctx.set('Access-Control-Allow-Origin', '*');
users.push(ctx.request.body)
ctx.status = 201
ctx.body = ctx.params
console.log(users)
})
For some unknown reason I receive nothing. Not even a single error message. The "console.log()" on the back-end is also not triggered, so my theory is that the problem is on the front-end.
Edit
As sugested by gnososphere, I tested with Postman, and it worked. So now i know the problem must be on the fron-end code.
You can try your backend functionality with Postman. It's a great service for testing.
the request would look something like this
If the problem is on the frontend, double check your fetch method by posting to a website that will return data and logging that in your app.

Modiy axios request 'data' field into 'body'

I'm trying to create a POST request using axios to a Notification API. So this Notification API have been developed before thus I cannot change anything related to it.
It accepts the request more or less like below.
I need to have the request body in the field called body as shown below. However, axios sends the request body in the field called data rather than body
Expected request
{
"head": {
...
},
"body":{
"publicUserId":"abcd",
"merchantId":"123888",
}
},
}
My request composed automatically by axios:
Axios request
{
"head": {
...
},
"data":{
"publicUserId":"abcd",
"merchantId":"123888",
}
},
}
I did try searching for how to alter the request body field name to body instead of data but I'm pretty sure I haven't found the solution. Maybe if anyone here has some workarounds, I'd be glad to try.
Should any details need to be provided, please tell me. Thank you.

Getting a bad request 400 when trying to upload zipped wkt file to here-maps rest api

We have a problem with the fleet.ls.hereapi.com when uploading a new layer for geofencing.
const myId = 'MYLAYER'; // just a id to check
zip.file('data.wkt', `NAME\tWKT\n${myId}\t${wkt}`);
const content = await zip.generateAsync({ type: 'nodebuffer' });
const formData = new FormData();
formData.append('zipfile', content);
await axios.post(config.HERE_MAPS_UPLOAD_ENDPOINT, formData, {
headers: {
'content-type': 'multipart/form-data',
},
params: {
apiKey: config.HERE_MAPS_REST_API_KEY,
layer_id: myId,
},
});
We get a bad request without a message and do not know what the problem is. The same implementation works in the Frontend (with 'blob' as zip type). Is there a parameter to get a better error message from the api?
We got the instructions how to implement it from this tutorial: https://www.youtube.com/watch?v=Ayw9GcS1V-8 and as I mentioned it works fine in the frontend. Also it works if I write a file in node and upload it via curl. Thank you for any help in advance!
Edit: I'm getting the following issue from the API: 'Multipart should contain exactly one part but contains 0'
I fixed it!
The problem was that the api needed a filename for the form data. This filename can be provided as third parameter as described here.
So I basically changed formData.append('zipfile', content); to formData.append('zipfile', content, zipfile.zip); and it worked.
Hope this will help somebody in the future!

Very simple Node.js POST form inquiries

I have a simple node.js app using express static and nodemailer with a POST form that emails the filled fields to myself. My problems are very simple, I'm just quite new to Node so I can't find a way to do them.
My first problem is that I can't find a way to put all the form data into the email's text. Below, I am trying to store my form data in a JSON and call it in the email text, but it doesn't work. It has only correctly worked for me when I only used one variable (ex. just req.body.name) for the text. How can I format my data together in the email?
My second problem is that I can find a way to handle the app after the email is sent. I want it to redirect to a success page, as shown in the marked line, but it does not work. Instead, the page goes to /reqform and displays an error message saying success.html doesn't exist (it is in the same public folder as my html file). I believe the problem lies in my sendFile usage, but I'm not sure.
app.post('/reqform', urlencodedParser, function (req, res) {
response = {
name: req.body.name,
email: req.body.email,
phone: req.body.phone
};
var mailContent = {
from: 'myemail#gmail.com',
to: 'myemail#gmail.com',
subject: 'Service Request From req.body.name',
text: response //*** Problem #1
};
transporter.sendMail(mailClient, function (error, info) {
if (error) {
console.log(error);
} else {
res.sendFile("success.html"); //** Problem #2
}
});
})
Any help is greatly appreciated. Thanks!
The default string value for a JavaScript Object is just "[object Object]". If you want anything else, you'll have to be specific with how you want it represented.
For example, JSON is a text/string format that represents values like Objects. It's separate from the Object itself, so you'll need to convert to use it:
var mailContent = {
// ...
text: JSON.stringify(response)
}
Or, provide your own formatting:
var mailContent = {
// ...
text: `Name: ${response.name}\nEmail: ${response.email}\nPhone: ${response.phone}`
}
It might be better to use res.redirect() in this case, allowing the client/browser to request success.html via your application's static() middleware:
res.redirect('/success.html');
res.sendFile() doesn't collaborate with any static() middleware to know about your public folder. It expects you to provide a full path either directly or with its root option:
res.sendFile(path.join(__dirname, 'public/success.html'));

Accessing response headers using NodeJS

I'm having a problem right now which I can't seem to find a solution to.
I'm using Uservoice's NodeJS framework to send some requests to UserVoice regarding Feedback posts. A problem I've run into are ratelimits so I want to save the header values X-Rate-Limit-Remaining, X-Rate-Limit-Limit and X-Rate-Limit-Reset locally. I've made a function for updating and getting that value and am calling it like this:
var content = "Test"
c.post(`forums/${config.uservoice.forumId}/suggestions/${id}/comments.json`, {
comment: {
text: content
}
}).then(data => {
rl.updateRL(data.headers['X-Rate-Limit-Limit'],data.headers['X-Rate-Limit-Remaining'],data.headers['X-Rate-Limit-Reset'])
When running this code I get the error Cannot read property 'X-Rate-Limit-Limit' of undefined.
This is not a duplicate, I've also tried it lowercase as described here but had no luck either. Thanks for helping out!
EDIT:
The function takes the following parameters:
module.exports = {
updateRL: (lim, rem, res) {SAVING STUFF HERE}
}
It is defined in the file rates.jsand is imported in the above file as const rl = require('../rates').

Resources