How can I improve the elegancy of my code that uses axios? - node.js

I am trying to migrate from request to axios, since request has been deprecated.
Suppose that the url 'https://www.example.com' receives a post request with formdata that contains login information, and also suppose that I need to maintain the current session across multiple requests(for that I need a cookieJar).
Using axios I need cookieJar support from an external library therefor I use axios-cookiejar.
Also to send formdata using axios I have to use the external library form-data, and I also have to set the headers manually since axios doesn't do that for me.
I have the following code, which uses axios that does just that:
axios = require('axios')
FormData = require('form-data')
axiosCookieJarSupport = require('axios-cookiejar-support').default
tough = require('tough-cookie')
axiosCookieJarSupport(axios)
cookieJar = new tough.CookieJar()
form = new FormData()
form.append('email', 'example#gmail.com')
form.append('password', '1234')
axios({
method: 'post',
url: 'https://www.example.com',
data: form,
headers: {'Content-Type': `multipart/form-data; boundary=${form._boundary}` },
jar: cookieJar,
withCredentials: true
}).then(function (response) {
console.log(response['data'])
})
Using request this becomes much simpler:
request = require('request')
requestCookieJar = request.jar()
request.post({
url: 'https://www.example.com',
method: 'POST',
jar: requestCookieJar,
formData: {
'email': 'example#gmail.com',
'password': '1234'
}
}, function(error, response, body) {
console.log(body)
})
As you can see the request API is much more elegant.
Is there a way to use axios more elegantly or is there a different elegant API, which isn't deprecated, that I could use to support my needs stated at the beginning of this question?

Related

send formData POST request with nodejs

I want to send a post request that contain a form data, i want to do that from nodejs to another external api, i don't have the front-end to send the formData, so all i have a javascript object that has keys and values, so how can i do that?, when i tried sending a normal object, i didn't get the right api response, but when i sent it with a POSTMAN client, i got the correct response.
If you have a correct result in Postman, it's interesting to use the code generator in the same tools to have the desired code :). The button "</>" is on the right bar of the screen.
Here is the code generated from the tool :
var axios = require('axios');
var FormData = require('form-data');
var data = new FormData();
data.append('data', 'asldkfjalsdkjf');
var config = {
method: 'post',
url: 'https://some-domain.com/formdata',
headers: {
...data.getHeaders()
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
It's cool, isn't it?
One more thing, you have many options from NodeJS to C#, PHP.. :)
So you want to make a post request with nodejs? In order to do so, you can use the axios library and send the data in the following way.
const axios = require('axios');
let formData = new FormData();
formData.append('x': 'some test data');
axios({
method: 'post',
url: 'https://stackoverflow.com/posts/67709177',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
})
.then(res => {
console.log(`statusCode: ${res.statusCode}`)
console.log(res)
})
.catch(error => {
console.error(error)
})
You can install axios using this command.
npm i axios

UrlFetchApp Google Scripts VS Node Fetch

I'm having some problems to do a simple POST request with UrlFetchApp on Google Scripts.
This code works fine on NodeJS with node-fetch lib.
const fetch = require('node-fetch');
const URL = "https://login.XXXXXXXXXXXXX.com.br/api/login"
fetch(URL, {
"body": "{'my_json_data': 'login data'}",
"method": "POST",
}).then(res => res.text())
.then(body => console.log(JSON.parse(body)));
The same request on a Google Scripts project using UrlFetchApp give me a 403 Forbidden HTTP error.
var url = 'https://login.XXXXXXXXX.com.br/api/login';
var data = {
'email':'EMAIL',
'password':'PASS'
}
var options = {
method: 'POST',
payload: JSON.stringify(data)
}
var response = UrlFetchApp.fetch(url, options);
Logger.log(response)
What am I missing here?
Edit: Already tried with payload.
I believe your goal as follows.
You want to convert the following Node.js script to Google Apps Script.
const fetch = require('node-fetch');
const URL = "https://login.XXXXXXXXXXXXX.com.br/api/login"
fetch(URL, {
"body": "{'my_json_data': 'login data'}",
"method": "POST",
}).then(res => res.text())
.then(body => console.log(JSON.parse(body)));
Modification points:
In your Node.js script, the data of "{'my_json_data': 'login data'}" is sent to data as text/plain. So in this case, when UrlFetchApp is used, the content type is required to be set. Because when the content type is not set, the data is sent as form-data.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
var options = {
method: 'POST',
payload: JSON.stringify(data)
}
To:
var options = {
method: 'POST',
payload: JSON.stringify(data),
contentType: "text/plain"
}
If contentType: "text/plain" occurs an error, please modify it to contentType: "text/plain;charset=UTF-8".
Although I'm not sure about the specification of your API, I thought that contentType: "application/json" might be able to be also used. But this is my guess.
Reference:
Class UrlFetchApp

how to send xml response to a given url from express route?

I need to send a XML response from express route to an url given as a POST Request?
const xml = `<sourcedGUID>
<sourcedId>ASSMT12345</sourcedId>
</sourcedGUID>
<contextID>
<textString>cls1234</textString>
</contextID>
<userID>
<textString>usr123</textString>
</userID>`
I am in express route of /status and I need to send the xml variable to the url: 'https://example.com/cli' using express.
How can I achieve this use case?
You need to use something like request or axios or http, I will use request here
var request = require('request');
request.post({
url: <the-url-where-to-send-xml>,
method: 'POST',
headers:{
'Content-Type': 'application/xml',
},
body: xml
},
function(error, response, body){
console.log(response.statusCode);
console.log(body);
console.log(error);
});

Node JS upload file streams over HTTP

I'm switching one of my projects from request over to something a bit more light-weight (such as got, axios, or fetch). Everything is going smoothly, however, I'm having an issue when attempting to upload a file stream (PUT and POST). It works fine with the request package, but any of the other three return a 500 from the server.
I know that a 500 generally means an issue on the server's end, but it is consistent only with the HTTP packages that I'm testing out. When I revert my code to use request, it works fine.
Here is my current Request code:
Request.put(`http://endpoint.com`, {
headers: {
Authorization: `Bearer ${account.token.access_token}`
},
formData: {
content: fs.createReadStream(localPath)
}
}, (err, response, body) => {
if (err) {
return callback(err);
}
return callback(null, body);
});
And here is one of the attempts using another package (in this case, got):
got.put(`http://endpoint.com`, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${account.token.access_token}`,
},
body: {
content: fs.createReadStream(localPath)
}
})
.then(response => {
return callback(null, response.body);
})
.catch(err => {
return callback(err);
});
Per the got documentation, I've also tried using the form-data package in conjunction with it according to its example and I still get the same issue.
The only difference between these 2 I can gather is with got I do have to manually specify the Content-Type header otherwise the endpoint does give me a proper error on that. Otherwise, I'm not sure how the 2 packages are constructing the body with the stream, but as I said, fetch and axios are also producing the exact same error as got.
If you want any of the snippets using fetch or axios I'd be happy to post them as well.
I know this question was asked a while ago, but I too am missing the simple pipe support from the request package
const request = require('request');
request
.get("https://res.cloudinary.com/demo/image/upload/sample.jpg")
.pipe(request.post("http://127.0.0.1:8000/api/upload/stream"))
// Or any readable stream
fs.createReadStream('/Users/file/path/localFile.jpeg')
.pipe(request.post("http://127.0.0.1:8000/api/upload/stream"))
and had to do some experimenting to find similar features from current libraries.
Unfortunately, I haven't worked with "got" but I hope the following 2 examples help someone else that are interested in working with the Native http/https libraries or the popular axios library
HTTP/HTTPS
Supports piping!
const http = require('http');
const https = require('https');
console.log("[i] Test pass-through: http/https");
// Note: http/https must match URL protocol
https.get(
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
(imageStream) => {
console.log(" [i] Received stream");
imageStream.pipe(
http.request("http://localhost:8000/api/upload/stream/", {
method: "POST",
headers: {
"Content-Type": imageStream.headers["content-type"],
},
})
);
}
);
// Or any readable stream
fs.createReadStream('/Users/file/path/localFile.jpeg')
.pipe(
http.request("http://localhost:8000/api/upload/stream/", {
method: "POST",
headers: {
"Content-Type": imageStream.headers["content-type"],
},
})
)
Axios
Note the usage of imageStream.data and that it's being attached to data in the Axios config.
const axios = require('axios');
(async function selfInvokingFunction() {
console.log("[i] Test pass-through: axios");
const imageStream = await axios.get(
"https://res.cloudinary.com/demo/image/upload/sample.jpg",
{
responseType: "stream", // Important to ensure axios provides stream
}
);
console.log(" [i] Received stream");
const upload = await axios({
method: "post",
url: "http://127.0.0.1:8000/api/upload/stream/",
data: imageStream.data,
headers: {
"Content-Type": imageStream.headers["content-type"],
},
});
console.log("Upload response", upload.data);
})();
Looks like this was a headers issue. If I use the headers directly from FormData (i.e., headers: form.getHeaders()) and just add in my additional headers afterwards (Authorization), then this ends up working just fine.
For me just works when I added other parameters on FormData.
before
const form = new FormData();
form.append('file', fileStream);
after
const form = new FormData();
form.append('file', fileStream, 'my-whatever-file-name.mp4');
So that way I can send stream from my backend to another backend in node, waiting a file in multipart/form-data called 'file'

Box API Irregular Headers

I am trying to upload an image with the box API and the request module. I tried the provided curl example without any problems.
I have a request all setup like this
var request = require("request");
var fs = require("fs");
var path = require("path");
request({
url: "https://api.box.com/2.0/files/content",
method: "POST",
form: {
filename: fs.createReadStream(path.join(__dirname, "midguts.jpg")),
folder_id: "0"
},
headers: {
api_key: "<API_KEY>",
auth_token: "<AUTH_TOKEN>"
}
}, function (error, response, body) {
console.log(error);
console.log(body);
});
The problem arises when I get to the headers part. The box API call for a headers string of
"Authorization: BoxAuth api_key=API_KEY&auth_token=AUTH_TOKEN"
but I with the request module I can only send an object of key, value pairs. I also looked at the docs for nodes http.request and found it has the same issue.
So the question is, why does the API not follow the standard key pair format and how can I send a POST request that will work?
Authorization is the name of the HTTP Header (see also). This might work better:
headers: {
Authorization: "BoxAuth api_key=API_KEY&auth_token=AUTH_TOKEN"
}

Resources