Trying to read JSON data in request in NodeJS - html

I'm sending the below request from an angular app to my node backend. However, I cant seem to access the body of the request, instead just getting undefined being printed by the console. Where am I going wrong?
Request
Angular post request
logIn(email: string, password: string) {
return this.http.post('http://localhost:8080/login', { email: email, password: password });
}
NodeJS backend
var http = require('http');
http.createServer(function (req, res) {
let chunks = [];
req.on('data', chunk => chunks.push(chunk));
req.on('end', () => {
let data = Buffer.concat(chunks);
let schema = JSON.parse(JSON.stringify(data));
console.log('Data: ', schema.email);
});
}).listen(8080);

Related

Why can't send form-data in postman

Trying to send form-data in postman and sequelize return error:
value cannot be null
But when send raw request with json all ok. Trying body-parser and multer, but nothing working
This is my index.ts
import express from "express";
import fileUpload from "express-fileupload"
...
const app = express()
const PORT = process.env.PORT || 5100
app.use(cors())
app.use(express.json())
app.use('/api', router)
app.use(fileUpload({}))
app.use(errorHandler)
const start = async () => {
try {
await sequelize.authenticate()
await sequelize.sync()
console.log(chalk.cyanBright('Successful conection to data base'));
app.listen(PORT, () => { console.log(chalk.cyanBright(`Server has been started on port ${PORT}`)) })
}
catch (e) {
console.log(e);
}
}
start()
And this is my controller
export const DeviceController = {
async create(req: Request, res: Response, next:nextType) {
try {
const { brandId, typeId, name, price } = req.body
const img = req.files
let filename = 'uuid.v4()' + '.jpg'
img?.mv(path.resolve(__dirname, '..', 'static', filename))
const device = await Models.Device.create({ brandId, typeId, name, price, img: filename })
return res.json(device)
} catch (error: any) {
next(ApiError.badRequest(error.message))
console.log(error);
}
app.use(express.json())
You have body parsing middleware for JSON request bodies.
You don't have body parsing middleware for multipart/form-data request bodies. The documentation for body-parser lists a several middlewares you could use.
Trying body-parser
… which says it doesn't support that format
and multart
… that doesn't appear to exist. Do you mean multiparty? Or maybe multer?
We can't tell you what you did wrong without seeing your attempt.
Re edit:
You said:
const img = req.files
img?.mv(path.resolve(__dirname, '..', 'static', filename))
But the documentation says:
console.log(req.files.foo); // the uploaded file object
The files property contains all the files, indexed by the the names given to them in the multipart request.
You're trying to read that collection of files as if it were a single file.

Unexpected string in JSON at position <position> by sending a body with Postman

I am trying to implement the ability of the server to generate and validate JWT. I didn't have experience in TypeScript and Postman before so I got this error from the server:
json: Unexpected string in JSON at position 26
This is the request I am sending with Postman
This is the function I use to generate JWT:
app.post("/generate", async (req, res) => {
console.log("req.body: " + req.body)
let body: any = await req.body;
const { name } = await body.value;
let token = await generateUserJWT(name)
res.json({ status: true, data: name, token:token });
});
What is wrong with my request?

Node.js + body-parser object format changes when it reaches backend

I'm trying to send an object inside an another object from React frontend to Node/express backend using jquery ajax. The problem the data is received at the backend, it no longer looks follows the syntax of an object. Instead, it looks something like this:
{ 'data[name]': 'test name',
'data[size][height]': '123',
'data[size][weight]': '50' }
Here is the front end ajax call...
lendItem(){
let id = "5af3348742afc60ab71d7d80"
$.ajax({
url: '/api/items/' + id,
method: 'put',
data: {
'data': {
name: "test name",
size: {
height: 123,
weight: 50
}
}
},
success: (res) => {console.log(res)}
});
}
backend server...
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
// connect to mongodb
mongoose.connect('mongodb://localhost/promedical');
mongoose.Promise = global.Promise;
const app = express();
const port = process.env.PORT || 5000;
// parsing data that was received
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// initialize routes
app.use('/api', require('./routes/api'));
// error handling
app.use((err, req, res, next)=>{
res.status(422).send({error: err.message});
});
app.listen(port, () => {
console.log(`Listening on port ${port}`)
});
...and here is the route I'm interested in.
router.put('/items/:id', (req, res, next)=>{
console.log(req.body);
res.send("success");
});
I think this problem might have something to do with that body-parser. Is is possible to send objects inside an object via jquery ajax and have it keep it's form once it reaches the backend? If not, should I just send all the data inside one object and then parse it at the backend?
It turns out that the object called 'data' becomes a string after the backend has accepted the ajax call. Is there any way to prevent this from happening? I need to store that object into a database as an object, not as a string.

POSTing json to API with Angular 2/4

I am new to angular 4 and REST API development. I have developed a Login API in back-end and it works fine when I call it using Postman:
In the front-end application which is an Angular 4 project, I have created a service to call this login API. Here is the method I created in this service:
sendCredential(username: string, password: string) {
const url = 'http://localhost:8080/authenticate/user';
const body = '{"username": "' + username + '", "password": "' + password + '"}';
const headers = new Headers(
{
'Content-Type': 'application/json'
});
return this.http.post(url, body, {headers: headers});
}
My first question is:
Is this the correct way to pass the json object and call this API?
And I also created a component which calls the method in the service. Here is the method/event-handler I created in this component:
onSubmit(uname: string, pwd: string) {
this.loginService.sendCredential(uname, pwd).subscribe(
res => {
this.loggedIn = true;
localStorage.setItem('PortalAdminHasLoggedIn', 'true');
location.reload();
},
err => console.log(err)
);
}
My second question is:
How should I check whether a token is returned back or an error?
Question 1:
You do not need to stringify the body object when you do a http.post() in angular. Just use a normal object will do, and the Http class will help you parse it internally:
sendCredential(username: string, password: string) {
const url = 'http://localhost:8080/authenticate/user';
//do not need to stringify your body
const body = {
username, password
}
const headers = new Headers(
{
'Content-Type': 'application/json'
});
return this.http.post(url, body, {headers: headers});
}
Question 2:
As for your error, note that Angular also catch every http error. and by http error, it means that any status code that is <200 or >=300 will be an error. So only status codes that is in between 200 and 300 is considered successful. Upon an error received, angular will throw an Observable error, which you will need to handle explicitly (which you did it correctly):
onSubmit(uname: string, pwd: string) {
this.loginService.sendCredential(uname, pwd).subscribe(
res => {
//token should be in your res object
this.loggedIn = true;
localStorage.setItem('PortalAdminHasLoggedIn', 'true');
location.reload();
},
err => {
//handle your error here.
//there shouldn't be any token here
console.log(error);
}
);
}
With your above code, you should receive your token in your successful callback, and it will be in the res object. If there's an error, no token should be received and you should handle the error at the error callback.

nodeJS - make HTTPS request, sending JSON data

I would like to send an HTTPS POST from one nodeJS server to another. I have some JSON data I would like to send with this request (populated by a html form).
How can I do this? I am aware of https.request() but there does not seem to be an option to include JSON as a part of the query. From my research it seems possible with an HTTP request, but not an HTTPS request. How can I solve this?
const pug = require('pug');
var cloudinary = require('cloudinary');
var express = require('express');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });
var request = require('request');
var bodyParser = require('body-parser');
var options = {
hostname: 'ec2-54-202-139-197.us-west-2.compute.amazonaws.com',
port: 443,
path: '/',
method: 'GET'
};
var app = express();
var parser = bodyParser.raw();
app.use(parser);
app.set('view engine', 'pug');
app.get('/', upload.single('avatar'), function(req, res) {
return res.render('index.pug');
});
app.get('/makeRequest*', function(req, res) {
query = req['query'];
/*
Here, I would like to send the contents of the query variable as JSON to the server specified in options.
*/
});
You can send JSON data through a POST http request with the native https node module, as stated in the documentation
All options from http.request() are valid.
So, taking the http.request() example you can do the following:
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = https.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
You should edit postData to your desired JSON object
I believe the below is what you want. Using the request library. See comments in the code for my recommendations.
...
var options = {
hostname: 'ec2-54-202-139-197.us-west-2.compute.amazonaws.com',
port: 443,
path: '/',
method: 'POST',
json: true
};
...
//making a post request and sending up your query is better then putting it in the query string
app.post('/makeRequest', function(req, res) {
var query = req.body['query'];
//NOTE, you cannot use a GET request to send JSON. You'll need to use a POST request.
//(you may need to make changes on your other servers)
options.body = { payload: query };
request(options, function(err, response, body) {
if (err) {
//Handle error
return;
}
if (response.statusCode == 200) {
console.log('contents received');
}
});
});
as matt mentioned you need to use request
to send JSON object not JSON.Stringify so that at the server you can receive it using:
app.post('/makeRequest', function(req, res) {
console.log (req.body.param1);
}
Use the following code:
var request = require("request");
request({
'url':"http://www.url.com",
method: "POST",
json: true,
body: {'param1':'any value'}
}, function (error, resp, body) {
console.log ("check response.");
});