i want to send a post request using node-fetch with a body payload encoded in the x-www-form. I tried this code but unfortunately it doesnt work:
paypalSignIn = function(){
var username = process.env.PAYPALID;
var password = process.env.PAYPALSECRET;
var authContent = 'Basic '+base64.encode(username + ":" + password);
fetch('https://api.sandbox.paypal.com/v1/oauth2/token', { method: 'POST',
headers: {
'Accept': 'application/json',
'Accept-Language' :"en_US",
'Authorization': authContent,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'grant_type=client_credentials' })
.then(res => res.json()) // expecting a json response
.then(json => console.log(json));
}
I'm not sure if this way is possible but i need to use this standard for die paypal api.
I'm getting statu code 400 with error
grant_type is null
Thx
I don't know if this is the only error, but at the very least you need a space between the word Basic and the encoded username/password.
Next time you ask a question, also post what your script returned. I'm guessing it was a 401 error in this case.
I used the PayPal sandbox today, here is how I managed to get my access token and a successful response (and also answering the OP's question about sending application/x-www-form-urlencoded POST requests with data) =>
I did it with node-fetch but the plain fetch API should work the same.
import fetch from "node-fetch";
export interface PayPalBusinessAccessTokenResponseInterface {
access_token: string;
}
export interface PayPalClientInterface {
getBusinessAccessToken: (
clientId: string,
clientSecret: string
) => Promise<PayPalBusinessAccessTokenResponseInterface>
}
const paypalClient: PayPalClientInterface = {
async getBusinessAccessToken(
clientId: string,
clientSecret: string
): Promise<PayPalBusinessAccessTokenResponseInterface> {
const params = new URLSearchParams();
params.append("grant_type", "client_credentials");
const paypalAPICall = await fetch(
"https://api-m.sandbox.paypal.com/v1/oauth2/token",
{
method: "POST",
body: params,
headers: {
"Authorization": `Basic ${Buffer.from(clientId + ":" + clientSecret).toString('base64')}`
}
}
);
const paypalAPIRes = await paypalAPICall.json();
return paypalAPIRes;
}
};
export default paypalClient;
I am using reactjs in my front end, so I am converting an image into base64 data and pass it to nodejs, In my backend I am trying send the base64 data to 3rd part API using fetch call, But it returns
401 unauthorization error
If I pass authorization in header nothing happens
const formData = new FormData();
formData.append('file', url);
const resp = await fetch(requestURL, {
method: 'POST',
headers: {
'Authorization': accessToken,
'Content-Type': 'multipart/form-data',
},
body: formData,
});
Can anyone help me with this?
I have tried everything and can't get Axios to work with SAP Odata Post services. The problem is CSRF token validation failing but its working fine in Postman.
My request looks like this:
const postNewTasks = async (body, headers) => (await axios.get(getHeadersandCFRSURL, {
headers: { 'authorization': auth, 'x-csrf-token': 'fetch' },
withCredentials: true
}).then((response) => {
axios({
method: 'POST',
url: postBatchOperationsURL,
headers: {
"Authorization": auth,
"Content-Type": "multipart/mixed; boundary=batch_1",
"X-CSRF-Token": response.headers["x-csrf-token"], // set CSRF Token for post or update
},
withCredentials: true,
body: body
}).then(function (response) {
console.log(response)
return response
}).catch(function (err) {
console.log(err)
return err
})
})
)
Anybody has idea why the CSRF token validation fails with this axios request?
I had this issue recently and a solution that worked for me was to add a Cookie header with the cookies from the initial response set-cookie headers.
Postman does this automatically, but axios doesn't it would seem. My code from that part after "x-csrf-token":"fetch":
var xcsrftoken = response.headers["x-csrf-token"];
var cookies = '"';
for (var i = 0; i < response.headers["set-cookie"].length; i++) {
cookies += response.headers["set-cookie"][i] + ";";
}
cookies += '"';
axiosClient.defaults.headers.common[this.xcsrftokenName] = xcsrftoken;
axiosClient.defaults.headers.common["Cookie"] = cookies;
axiosClient is the object made from axios.create. I've set those headers as default so that I don't need to include them later in the requests. There were multiple set-cookie headers as well and it was necessary to combine them into one.
I have an API endpoint that lets the client post their csv to our server then post it to someone else server. I have done our server part which save uploaded file to our server, but I can't get the other part done. I keep getting error { message: 'File not found', code: 400 } which may mean the file never reach the server. I'm using axios as an agent, does anyone know how to get this done? Thanks.
// file = uploaded file
const form_data = new FormData();
form_data.append("file", fs.createReadStream(file.path));
const request_config = {
method: "post",
url: url,
headers: {
"Authorization": "Bearer " + access_token,
"Content-Type": "multipart/form-data"
},
data: form_data
};
return axios(request_config);
Update
As axios doc states as below and the API I'm trying to call requires a file
// data is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', and 'PATCH'
// When no transformRequest is set, must be of one of the following types:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - Browser only: FormData, File, Blob
// - Node only: Stream, Buffer
Is there any way to make axios send a file as a whole? Thanks.
The 2 oldest answers did not work for me. This, however, did the trick:
const FormData = require('form-data'); // npm install --save form-data
const form = new FormData();
form.append('file', fs.createReadStream(file.path));
const request_config = {
headers: {
'Authorization': `Bearer ${access_token}`,
...form.getHeaders()
}
};
return axios.post(url, form, request_config);
form.getHeaders() returns an Object with the content-type as well as the boundary.
For example:
{ "content-type": "multipart/form-data; boundary=-------------------0123456789" }
I'm thinking the createReadStream is your issue because its async. try this.
Since createReadStream extends the event emitter, we can "listen" for when it finishes/ends.
var newFile = fs.createReadStream(file.path);
// personally I'd function out the inner body here and just call
// to the function and pass in the newFile
newFile.on('end', function() {
const form_data = new FormData();
form_data.append("file", newFile, "filename.ext");
const request_config = {
method: "post",
url: url,
headers: {
"Authorization": "Bearer " + access_token,
"Content-Type": "multipart/form-data"
},
data: form_data
};
return axios(request_config);
});
This is what you really need:
const form_data = new FormData();
form_data.append("file", fs.createReadStream(file.path));
const request_config = {
headers: {
"Authorization": "Bearer " + access_token,
"Content-Type": "multipart/form-data"
},
data: form_data
};
return axios
.post(url, form_data, request_config);
In my case, fs.createReadStream(file.path) did not work.
I had to use buffer instead.
const form = new FormData();
form.append('file', fs.readFileSync(filePath), fileName);
const config = {
headers: {
Authorization: `Bearer ${auth.access_token}`,
...form.getHeaders(),
},
};
axios.post(api, form.getBuffer(), config);
I have made an interceptor you can connect to axios to handle this case in node: axios-form-data. Any feedback would be welcome.
npm i axios-form-data
example:
import axiosFormData from 'axios-form-data';
import axios from 'axios';
// connect axiosFormData interceptor to axios
axios.interceptors.request.use(axiosFormData);
// send request with a file in it, it automatically becomes form-data
const response = await axios.request({
method: 'POST',
url: 'http://httpbin.org/post',
data: {
nonfile: 'Non-file value',
// if there is at least one streamable value, the interceptor wraps the data into FormData
file: createReadStream('somefile'),
},
});
// response should show "files" with file content, "form" with other values
// and multipart/form-data with random boundary as request header
console.log(response.data);
I had a same issue, I had a "pdf-creator-service" for generate PDF document from html.
I use mustache template engine for create HTML document - https://www.npmjs.com/package/mustache
Mustache.render function returns html as a string what do I need to do to pass it to the pdf-generator-service ? So lets see my suggestion bellow
//...
async function getPdfDoc(props: {foo: string, bar: string}): Promise<Buffer> {
const temlateFile = readFileSync(joinPath(process.cwd(), 'file.html'))
mustache.render(temlateFile, props)
const readableStream = this.getReadableStreamFromString(htmlString)
const formData = new FormData() // from 'form-data'
formData.append('file', options.file, { filename: options.fileName })
const formHeaders = formData.getHeaders()
return await axios.send<Buffer>(
{
method: 'POST',
url: 'https://pdf-generator-service-url/pdf',
data: formData,
headers: {
...formHeaders,
},
responseType: 'arraybuffer', // ! important
},
)
}
getReadableStreamFromString(str: string): Readable {
const bufferHtmlString = Buffer.from(str)
const readableStream = new Readable() // from 'stream'
readableStream._read = () => null // workaround error
readableStream.push(bufferHtmlString)
readableStream.push(null) // mark end of stream
return readableStream
}
For anyone who wants to upload files from their local filesystem (actually from anywhere with the right streams architecture) with axios and doesn't want to use any external packages (like form-data).
Just create a readable stream and plug it right into axios request function like so:
await axios.put(
url,
fs.createReadStream(path_to_file)
)
Axios accepts data argument of type Stream in node context.
Works fine for me at least in Node v.16.13.1 and with axios v.0.27.2
we are facing an issue in production that the 'Content-Length' header is not being sent, even if we hard-code it in the headers properties, so we are receiving back from the server the 411 Length Required error.
We are using:
Axios 0.16.2
NodeJS 6.10
Application deployed inside AWS Lambda environment
The code that is causing the issue is the following:
let cookieJar;
const postBody = "MyBody=MyBodyContentGoesHere";
const url = "https://my-url.com";
return axios
.post(url,
postBody,
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
timeout: 10000,
jar: cookieJar,
withCredentials: true
}
);
I wrote an application in .NET and the header is sent properly (without to pass it manually). This .NET application was written just to test, it's not the real application.
Do you have some idea?
I open a issue in the axios github project, but I want to know from you guys some ideas.
Thank you.
have you tried adding a "data" field to the config object?
let cookieJar;
const postBody = "MyBody=MyBodyContentGoesHere";
const url = "https://my-url.com";
return axios
.post(url,
postBody,
{
data: postBody,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
timeout: 10000,
jar: cookieJar,
withCredentials: true
}
);
I'd the same issue as you. Using querystring as suggested in the offical docs solved it for me.
'use strict';
let querystring = require('querystring');
let cookieJar;
const postBody = querystring.stringify({ MyBody: 'MyBodyContentGoesHere' });
const url = 'https://my-url.com';
return axios.post(url, postBody, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
timeout: 10000,
jar: cookieJar,
withCredentials: true
}
);