axios multipart request failing - node.js

Im trying to send a post request for convert doc to pdf using a service. The service is working fine with postman, y can send the doc to the endpoint and it return me the pdf, nice.
But i cant make the request from my nodejs server, im using axios to make the request and it fails with this is the error:
{"time":"2019-09-24T14:39:46.89404124Z","id":"","remote_ip":"000.00.000.00","host":"pdf-doc-convert.example","method":"POST","uri":"/convert/office","user_agent":"axios/0.19.0","status":500,"error":"getting multipart form: no multipart boundary param in Content-Type","latency":221460,"latency_human":"221.46µs","bytes_in":0,"bytes_out":36}
This is the service documentation, is a simple post with a multipart/form-data request (come with a curl example):
https://thecodingmachine.github.io/gotenberg/#office
And this is my request with axios:
async function request() {
const endpoint =
"http://pdf-doc-convert.example/convert/office";
const data = new FormData();
data.append('files', fs.createReadStream("my/file/path/example.docx"));
const config = {
headers: {
"content-type": "multipart/form-data"
}
};
const pdf = await axios.post(endpoint, data, config);
}
How can i make the request?

Maybe the quickest way to debug this would be to intercept the call you're making with the Axios request using Postman Intercept and to compare the cURL request info from the one that's working to the one that's not. It could be either a headers issue or file encoding issue.
I've encountered something similar previously and this could be related to the formData headers which require additional configuration in Axios as mentioned here: https://github.com/axios/axios/issues/789#issuecomment-508114703
const data = new FormData();
data.append("firstFile", fs.createReadStream(firstFilePath), { knownLength: fs.statSync(firstFilePath).size });
const headers = {
...data.getHeaders(),
"Content-Length": data.getLengthSync()
};
const endpoint = "http://pdf-doc-convert.example/convert/office";
const pdf = await axios.post(endpoint, data, config);

Related

Sending FormData through 2 API's (NextJS)

So I'm sending some formdata, including images to my backend. To obfuscate/secure my backend even more - I'm learning that it's good practice to take advantage of the NextJS api (send calls from client to NextJS server/api, NextJS api acts as a middleman and sends data to backend api). I'm also using Auth0 - and the most secure way to get tokens is via the NextJS api itself.
I have no issues reading the data on my backend when I make an api call directly from client to backend. However, I'm having issues actually getting the data (primarily the images/files) OUT of the request on my NextJS api for repackaging and sending to my actual backend. I can't use FormData within the NextJS api either, so I'm just confused all around.
Client submit function:
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("title", brand.name);
formData.append("slug", brand.slug);
formData.append("bio", brand.bio);
formData.append("logo", brand.logo[0]);
const response = await fetch("/api/brands", {
method: "post",
body: formData,
});
});
NextJS api code (does not work - I am getting an access token perfectly, it's just the sending of the formdata/files I'm stuck on)
import { getAccessToken, withApiAuthRequired } from "#auth0/nextjs-auth0";
export default withApiAuthRequired(async function products(req, res) {
const { accessToken } = await getAccessToken(req, res, {});
const response = await fetch("http://localhost:5000/brands", {
method: "post",
headers: {
Authorization: `Bearer ${accessToken}`,
},
body: {
title: req.body.title,
slug: req.body.slug,
bio: req.body.bio,
logo: req.file,
},
});
const products = await response.json();
res.status(200);
});
You might be missing the "Content-Type: multipart/form-data" on the 2nd API call that you make. On the client side it's inferred from the FormData object, but on the server side you have to specify it manually. Altough, I couldn't find a way to do that on the server. This could indicate that the use case is wrong, I think making another request to your own server is a no-no. Next.js is meant to use this function called "withApiAuthRequired" as a wrapper, from which you call your services, or business logic. There is no need to make a second HTTP Request here.

How can I send post request with base64 image?

I am making an image upload component in vue js with custom cropping option. The cropped version is being saved in my state as a base64 string. This is it:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeAAAAHgCAYAAAB91L6VAAAgAElEQVR4Xu2dCdh+1dT/v3+UDA1KMiQhlCEylDGZSqbI0Jy8JMmYUEloRFIpVJK5EpL0ilJmr6IQKiXzrCKESP2v72vfb8/z/O7hnH2fc/be53z2df2uoj1+9vrd6+y1117r/4kCAQhAAAIQgEDnBP5f5yMyIAQgAAEIQAACQgEjBBCAAAQgAIEEBFDACaAzJAQgAAEIQAAFjAxAAAIQgAAEEhBAASeAzpAQgAAEIAABFDAyAAEIQAACEEhAAAWcADpDQgACEIAABFDAyAAEIAABCEAgAQEUcALoDAkBCEAAAhBAASMDEIAABCAAgQQEUMAJoDMkBCAAAQhAAAWMDEAAAhCAAAQSEEABJ4DOkBCAAAQgAAEUMDIAAQhAAAIQSEAABZwAOkNCAAIQgAAEUMDIAAQgAAEIQCABARRwAugMCQEIQAACEEABIwMQgAAEIACBBARQwAmgMyQEIAABCEAABYwMQAACEIAABBIQQAEngM6QEIAABCAAARQwMgABCEAAAhBIQAAFnAA6Q0IAAhCAAARQwMgABCAAAQhAIAEBFHAC6AwJAQhAAAIQQAEjAxCAAAQgAIEEBFDACaAzJAQgAAEIQAAFjAxAAAIQgAAEEhBAASeAzpAQgAAEIAABFDAyAAEIQAACEEhAAAWcADpDQgACEIAABFDAyAAEIAABCEAgAQEUcALoDAkBCEAAAhBAASMDEIAABCAAgQQEUMAJoDMkBCAAAQhAAA....
now I am trying to send this image to my node js server using post request API. In Postman, I am writing the body selecting "raw" and "json" in this the body in this way:
{
"image" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeAAAAHgCAYAAAB91L6VAAAgAElEQVR4Xu2dCdh+1dT/v3+UDA1KMiQhlCEylDGZSqbI0Jy8JMmYUEloRFIpVJK5EpL0ilJmr6IQKiXzrCKESP2v72vfb8/z/O7hnH2fc/be53z2df2uoj1+9vrd6+y1117r/4kCAQhAAAIQgEDnBP5f5yMyIAQgAAEIQAACQgEjBBCAAAQgAIEEBFDACaAzJAQgAAEIQAAFjAxAAAIQgAAEEhBAASeAzpAQgAAEIAABFDAyAAEIQAACEEhAAAWcADpDQgACEIAABFDAyAAEIAABCEAgAQEUcALoDAkBCEAAAhBAASMDEIAABCAAgQQEUMAJoDMkBCAAAQhAAAWMDEAAAhCAAAQSEEABJ4DOkBCAAAQgAAEUMDIAAQhAAAIQSEAABZwAOkNCAAIQgAAEUMDIAAQgAAEIQCABARRwAugMCQEIQAACEEABIwMQgAAEIACBBARQwAmgMyQEIAABCEAABYwMQAACEIAABBIQQAEngM6QEIAABCAAARQwMgABCEAAAhBIQAAFnAA6Q0IAAhCAAARQwMgABCAAAQhAIAEBFHAC6AwJAQhAAAIQQAEjAxCAAAQgAIEEBFDACaAzJAQgAAEIQAAFjAxAAAIQgAAEEhBAASeAzpAQgAAEIAABFDAyAAEIQAACEEhAAAWcADpDQgACEIAABFDAyAAEIAABCEAgAQEUcALoDAkBCEAAAhBAASMDEIAABCAAgQQEUMAJoDMkBCAAAQhAAAWMDEAAAhCAAAQSEEABJ4DOkBCAAAQgAAEUMDIAAQhAAAIQSEAABZwAOkNCAAIQgAAEUMDIAAQgAAEIQCABARRwAugMCQEIQAACEEABIwMQgAAEIACBBARQwAmgMyQEIAABCEAABYwMQAACEIAABBIQQAEngM6QEIAABCAAARQwMgABCEAAAhBIQAAFnAA6Q0IAAhCAAARQwMgABCAAAQhAIAEBFHAC6AwJAQhAAAIQQAEjAxCA.....
}
The request not detecting this json data in the body and returning error:
{
"image": "\"image\" is required"
}
Also tried the form_data sending method in this way:
var axios = require('axios');
var FormData = require('form-data');
// var fs = require('fs');
var data = new FormData();
data.append('image', formdata.logoFinalImage);
var config = {
method: 'post',
url: myurl,
headers: {
'Authorization': this.state.token,
'Content-Type': 'application/json'
},
data: data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Same issue.
How can I send the final cropped version to the node api endpoint?
Solved the issue. There were two ways of doing it. One is required changes in the backend to configure the code in a way that can receive base64 and convert it to image. Reference: https://medium.com/js-dojo/how-to-upload-base64-images-in-vue-nodejs-4e89635daebc
Other is to make the base64 image file, and then send it to the backend as form-data. Used this one for my case. Reference of this solution: https://gist.github.com/ibreathebsb/a104a9297d5df4c8ae944a4ed149bcf1
if its working in postman then you can create the code from postman itself , select code and search for axios
v8<
if using v8

Axios GET request sends empty req.body to server

I'm trying to make a GET request in my React app but Axios seems to send an empty request body for some reason. I know there's (most likely) nothing wrong in the backend as I'm able to make the requests perfectly fine with Insomnia. I've tried the following till now and none of the seem to work:
const response = await axios.get(URL, { email })
const response = await axios({
method: "get",
url: URL,
data: { email }
})
I'm using the express.json() middleware in the backend.
From the RFC 7231
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
So do not rely on body data for GET request and use appropriate HTTP method like POST, PUT etc.
Moreover, if you want to send Query params with your GET request, both code snippets you shared above will not work. Instead do it like below.
// using get method
const response = await axios.get(URL, {
params: {
ID: 12345
}
});
// using Axios API
const response = await axios({
method: "get",
url: URL,
params: {
ID: 12345
}
});

How to upload file using axios post request

I am trying to upload a file to url using axios post request. But i am getting 500 internal server error.
If the same request I tried from postman file gets uploaded with 200 status code.
I am not sure what should be the content-Type here.
here is my code.
const axios = require('axios')
var FormData = require('form-data');
var fs = require("fs");
var request = require('request');
const formData = {
file: fs.createReadStream('myfile.txt')
}
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
};
axios.post('myurl',formData,config)
.then((res) => {
console.log(`statusCode: ${res.status}`)
console.log(res.data)
})
.catch((error) => {
console.log(error)
})
Please check your frontend, when you click submit, do you call event.preventDefault();
const formData = {
file: fs.createReadStream('myfile.txt')
}
It's a plain javascript object, not a ready-to-use formData. You just forget to transform it into a real FormData object. Just check for the document of form-data module.
Also it seems that when you post a real FormData, the "Content-type" header is unnecessary as axios will automaticly handle it for you.

How to send binary stream from string content to third party api using axios nodejs

I have an API that takes a binary file stream. I am able to hit the API using postman.
Now on the server-side, the content of XML is in string object, So I have created stream first then posted it using axios lib (to call third party API) with form data. This is how I am doing
const Readable = require("stream").Readable;
const stream = new Readable();
stream.push(myXmlContent);
stream.push(null); // the end of the stream
const formData = new FormData();
formData.append("file", stream);
const response = await axios({
method: "post",
url: `${this.BASE_URL}/myurl`,
data: formData
});
return response.data;
but this is not sending data properly as third party API throws Bad Request: 400.
How can I send XML string content to API as a stream?
Used Buffer.from method to send the stream. This worked for me
const response = await axios({
method: "post",
url: `${this.BASE_URL}/myUrl`,
data: Buffer.from(myXmlContent),
headers: { "Content-Type": `application/xml`, }
});
return response.data;

Resources