Add a json object to req.body - node.js

I have learnt about sending form values via req.body. How can I append a new value/json to it? For eg. if the form contains only one or two input fields and submit, which sends a post request, how do i append a json object to the req.body recieved by express server?
I am designing a rest api with express for angular to access. I need to send json to express for post requests. It is a shopping cart(as a json object of products and rates) which i have to send to the backend to place an order(store in mongo).
Any suggestions?

You have to set the content-type to application/json. You can build your JSON object from the form data:
var data = {
id: form-model-id,
name: form-model-name
}
For more information see ng-http
$http.post('http://127.0.0.1:3000/something/cool', data, {
headers: {'Content-Type': 'application/json'},
}).then(function (response) {
callback(null, response.data);
}, function (response) {
if (response.status === 0) {
throw { message: 'api_timeout' };
} else {
if (response.status === 409) {
throw { message: 'api_login_failed' };
} else {
callback(response.status, response.data);
}
}
});

Related

Nodejs + Axios Post returns undefined value

I am using React + NodeJS & Axios but have been trying to send a post request but experiencing difficulties.
The request seems to be posting successfully, but all actions at the nodejs server is returning in the "undefined" data value, even if the data is passed successfully shown in the console.
REACT
const fireAction = (data1, data2) => {
const data = JSON.stringify({data1, data2})
const url = `http://localhost:5000/data/corr/fire`;
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'AUTHCODE',
}
}
axios.post(url, data, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
fireAction("Oklahoma", "Small apartment")
NODE
app.post('/data/corr/fire', async (req, res) => {
try {
const data = req.body.data1;
console.log(data)
} catch(e) {
res.send({success: "none", error: e.message})
}
});
Result of node: "undefined"
I have added the following body parser:
app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
I am not sure why this error is happening. I see there is similar questions to mine: however none of them are applicable as I'm using both express and body parser which is already suggested.
You're POSTing JSON with a content-type meant for forms. There's no need to manually set content-type if you're sending JSON, but if you want to manually override it, you can use 'Content-Type': 'application/json', and access the response in your route with req.body. If it does need to be formencoded, you'll need to build the form:
const params = new URLSearchParams();
params.append('data1', data1);
params.append('data2', data2);
axios.post(url, params, config);

Angular Convert POST request data to array

I have a post request that sends some data to a NodeJS app and then that returns an array. My problem is that I can't turn the data I receive as a response from the POST request to an array.
My Angular is set up like this:
newWord = '';
keyword = '';
onClick() {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
this.http.post('http://localhost:3000/search',
{ keyword: this.keyword },
{
headers: headers
})
.subscribe((data) => {
console.log(data);
})
}
}
The data inside the node app looks like this:
I want to get this data in angular as an array so I can iterate over it or do anything else with the fields. Any help would be appreciated!
Provide the type to the http request. Otherwise angular expects any, which is not necessarily an array. That is where the error comes from.
this.http.post<{ id: string, text: string }[]>('http://localhost:3000/search',
{ keyword: this.keyword },
{
headers: headers
})
.subscribe((data) => {
console.log(data);
})

send file from nextjs API Routes

I use nextjs API Routes to connect to an external API
when I use a POST request to send a file, the file doesn't handled correctly in API Routes and I get 422 Unprocessable Entity Error
when I send only text it's OK, but when I add a file this error occur.
my request
const data = new FormData();
data.append('first_name', firstName);
data.append('last_name', lastName);
data.append('phone_number', phoneNumber);
image && data.append('avatar', image);
axios.post(`${API_ROUTE}`, data, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(res=>{
alert(JSON.stringify(res.data, null, 2));
})
my API Route
const config = {
headers: {
'Content-Type': req.headers['content-type']
}
};
axios.post(address, req.body, config)
.then(r=>{
res.statusCode = 200
res.json( r.data )
})
.catch(err=>{
res.json(err)
})
in the request that API Route sending to the external API, there are some ? in the content of the file, but in the request that sending from browser to the API Route seems there are different characters

How to post an image as a File with Axios after Getting it as an Arraybuffer from an attachment

As a POC I would like to make pictures of my receipts (gas, shop etc) and use a chatbot to send them to my accounting software. My problem has to do with the sending of the collected receipt (an image) to the accounting software using its API.
The first part (getting the attachment) results in an Arraybuffer with an image. I used one of the NodeJS samples for that (nr 15).
const attachment = turnContext.activity.attachments[0];
const url = attachment.contentUrl;
let image;
axios.get(url, { responseType: 'arraybuffer' })
.then((response) => {
if (response.headers['content-type'] === 'application/json') {
response.data = JSON.parse(response.data, (key, value) => {
return value && value.type === 'Buffer' ? Buffer.from(value.data) : value;
});
}
image = response.data;
}
).catch((error) => {
console.log(error);
});
I am struggling with the second part. Posting the image to the accounting software
const requestConfig = {
headers: {
'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/x-www-form-urlencoded'
}
};
axios.post(postUrl, image, requestConfig)
.then((response) => { console.log(response); }
).catch((error) => {
console.log(error);
});
};
This results in 400. bad request. Probably the API needs a file and I cannot just send the buffer. I tested with Postman and the request is accepted by using application/x-www-form-urlencoded (by using a locally stored image file).
What is best practice to post an image retrieved in a bufferarray?
I think your comment is right on the money that you need to convert it to a file first. The channel isn't an issue because the file will be stored wherever the bot is hosted. The Attachments Sample actually has this code, which gets you close:
fs.writeFile(localFileName, response.data, (fsError) => {
if (fsError) {
throw fsError;
}
// Send the file
const url = '<yourApiUrl>';
const formData = new FormData();
formData.append('file',fs.createReadStream('<pathToFile>'), { knownLength: fs.statSync('<pathToFile>').size });
const config = {
headers: {
...formData.getHeaders(),
'Content-Length': formData.getLengthSync()
}
};
axios.post(url, forData, { headers });
});
I'm not super confident in the // Send the file section only because I can't test against your API. I got most of the code from here.

How to post multipart/form-data with node.js superagent

I am trying to send the content-type in my superagent post request to multipart/form-data.
var myagent = superagent.agent();
myagent
.post('http://localhost/endpoint')
.set('api_key', apikey)
.set('Content-Type', 'multipart/form-data')
.send(fields)
.end(function(error, response){
if(error) {
console.log("Error: " + error);
}
});
The error I get is:
TypeError: Argument must be a string
If I remove the:
.set('Content-Type', 'multipart/form-data')
I don't get any error but my back end is receiving the request as content-type: application/json
How can I force the content type to be multipart/form-data so that I can access req.files()?
First, you do not mention either of the following:
.set('Content-Type', 'multipart/form-data')
OR
.type('form')
Second, you do not use the .send, you use .field(name, value).
Examples
Let's say you wanted to send a form-data request with the following:
two text fields: name and phone
one file: photo
So your request will be something like this:
superagent
.post( 'https://example.com/api/foo.bar' )
.set('Authorization', '...')
.accept('application/json')
.field('name', 'My name')
.field('phone', 'My phone')
.attach('photo', 'path/to/photo.gif')
.then((result) => {
// process the result here
})
.catch((err) => {
throw err;
});
And, let's say you wanted to send JSON as a value of one of your fields, then you'd do this.
try {
await superagent
.post( 'https://example.com/api/dog.crow' )
.accept('application/json')
.field('data', JSON.stringify({ name: 'value' }))
}
catch ( ex ) {
// .catch() stuff
}
// .then() stuff...
Try
.type('form')
instead of
.set('Content-Type', 'multipart/form-data')
See http://visionmedia.github.io/superagent/#setting-the-content-type
It is not clear what is in the fields variable that you are sending, but here is some information that may help you determine where your problem lies.
To begin with, if you are actually trying to build a multi-part request, this is the official documentation for doing so: http://visionmedia.github.com/superagent/#multipart-requests
as for the error that you got...
The reason is that during the process of preparing the request, SuperAgent checks the data to be sent to see if it is a string. If it is not, it attempts to serialize the data based on the value of the 'Content-Type', as seen below:
exports.serialize = {
'application/x-www-form-urlencoded': qs.stringify,
'application/json': JSON.stringify
};
which is used here:
// body
if ('HEAD' != method && !req._headerSent) {
// serialize stuff
if ('string' != typeof data) {
var serialize = exports.serialize[req.getHeader('Content-Type')];
if (serialize) data = serialize(data);
}
// content-length
if (data && !req.getHeader('Content-Length')) {
this.set('Content-Length', Buffer.byteLength(data));
}
}
this means that to set a form 'Content-Type' manually you would use
.set('Content-Type', 'application/x-www-form-urlencoded')
or
.type('form') as risyasin mentioned
any other 'Content-Type' will not be serialized, and Buffer.byteLength(data) will subsequently throw the TypeError: Argument must be a string exception if the value of your fields variable is not a string.
Here is what worked for me. I had a single field form, that was uploading a file. I turned the form into a HTML5 FormData element and then did it as follows:
var frm = new FormData(document.getElementById('formId'));
var url = 'url/here';
superagent.post(url)
.attach('fieldInFormName', frm.get('fieldInFormName'))
.end( function (error, response) {
//handle response
});
Please note, I tried various ways of setting the 'Content-Type' manually in superagent, and it never worked correctly because of the multipart identifier needed in the Content-Type.

Resources