Converting Javascript Fetch to Google Apps Script URL Fetch - javascript

Have the JavaScript code from a successful API call but when I try to change it to use Google Apps Scripts URL Fetch function I get an error.
Here's the JavaScript from successful Postman Call
...
var myHeaders = new Headers();
myHeaders.append("X-Auth-Token", "Token");
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Cookie", "laravel_session=eyJpdiI6InpSaXcxVk1KQzd4cGMrT1BkWGlOQkQ0Tmt5TjhDRWRLVnlXQVwvYlJlV1EwPSIsInZhbHVlIjoiZGUyc21wWlZERHVJYkVhYks3MCswWXFOZllOQU5kSHdWeDJMbkdSZk5rNFV0N1BuUEI3N1FQT3RpbkhEU3JFRU56Wml4eE9NMmlKVGRqXC9OQ1pwNEJ3PT0iLCJtYWMiOiJjM2Q1NjBkYTAyMGFmNDY3NWJiY2VkMzZjODg0ZDViMDBlM2NmZDVkODBlMzk1YTc0ZTFlOGU4MTM3ODUxYjkxIn0%3D");
var raw = JSON.stringify({"description":"Test Description","invitees":"test#test.com","priority":"10","remind":{"popup":"0","mail":"1","hour":"09:00:00","date":"2020-12-22"},"sync_calendar":true,"task_name":"Test Name"});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://private-anon-0eef3aeb66-ricochet.apiary-mock.com/api/v4/leads/lead_id/tasks/", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
...
And here is what I have in Google Apps Script
...
var raw = JSON.stringify({"description":"Test Description",
"invitees":"test#test.com",
"priority":"10",
"remind":{"popup":"0","mail":"1","hour":"09:00:00","date":"2020-12-22"},
"sync_calendar":true,
"task_name":"Test Name"});
var headers = { "X-Auth-Token" : "Token"};
var params = {
"method" : "POST",
'contentType': 'application/json',
"headers" : headers,
"payLoad" : raw
};
var url = "https://private-anon-0eef3aeb66-ricochet.apiary-mock.com/api/v4/leads/lead_id/tasks/";
var res = UrlFetchApp.fetch(url,params);
...
Here is the error I get when using Google Apps Script
Exception: Request failed returned code 500. Truncated server response: {"status":false,"message":"Validation failed"}

Related

“TypeError: Failed to fetch” when the request hasn’t actually failed Error

I'm using an API to make my login page validate the user and password with this code:
function ola() {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
//WITH USERNAME AND PASSWORD LIKE THIS VVVVVV
var raw = "{\r\n \"password\": \"Olasou1!\",\r\n \"username\": \"bernardo\"\r\n}\r\n";
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://api.secureme.pt/api/v1/auth/login", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
};
I get a success message so I know that it worked
But when I try to use the user inputs on the variable raw like this:
function ola() {
var user = document.getElementById("user").value;
var password = document.getElementById("password").value;
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
var raw = {
password: password,
username: user
};
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://api.secureme.pt/api/v1/auth/login", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
};
And when I put the same username and password, I get an error saying that it failed to fetch:
error TypeError: Failed to fetch
at ola (:5500/js/loginRegister.js:36:3)
at HTMLButtonElement.onclick (loginRegister.html:22:74)
I can't figure out why, can someone help me with this?
This is where I call the function on html file:
<button type="submit" class="submit-btn" onclick="ola()">Log In</button>
Try to serialize your raw data:
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(raw),
redirect: 'follow'
}
You can check fetch documents for more details about which data types allowed by request body:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#body
https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters

Request for JavaScript works, but not for GoogleScreen. What's the difference?

Please, help. I can't find the error and I don't understand why the request is not working. It seems to me that it's just Google's IP blocked by the site I'm making a request to. The same request for JavaScript works.
function pleaseWork() {
var myHeaders = {
'contentType': 'application/json',
'Authorization': 'Bearer 5cd4ac65-f71b-3eaa-93af-78610a7aa320',
}
var raw = ["1111111111111"]
var requestOptions = {
'method': 'POST',
'headers': myHeaders,
'payload': JSON.stringify(raw)
};
result = UrlFetchApp.fetch("https://www.ukrposhta.ua/status-tracking/0.0.1/statuses/last", requestOptions)
Logger.log(result)
}
Working Javascript request:
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer 5cd4ac65-f71b-3eaa-93af-78610a7aa320");
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify([
"1111111111111"
]);
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
};
fetch("https://www.ukrposhta.ua/status-tracking/0.0.1/statuses/last", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
How to do it right?
In your Google Apps Script, the data is sent as form by default. When I saw your Javascript, it seems that the data is required to be sent as data with application/json. So you'll need to modify the script as follows.
From:
var requestOptions = {
'method': 'POST',
'headers': myHeaders,
'payload': JSON.stringify(raw)
};
To:
var requestOptions = {
'method': 'POST',
'headers': myHeaders,
'payload': JSON.stringify(raw),
'contentType': 'application/json',
};
Reference:
fetch(url, params)
Note:
I think that this modification is the same as the request of your Javascript. But, if an error occurs, please confirm your values of raw and your access token, again.
Added 1:
Your showing script was modified for testing. Please set your access token and the value of raw and test it again.
function modified_pleaseWork() {
var myHeaders = { 'Authorization': 'Bearer ###' };
var raw = ["1111111111111"];
var requestOptions = {
'method': 'POST',
'headers': myHeaders,
'payload': JSON.stringify(raw),
'contentType': 'application/json',
};
var result = UrlFetchApp.fetch("https://www.ukrposhta.ua/status-tracking/0.0.1/statuses/last", requestOptions);
Logger.log(result.getContentText())
}
Added 2:
From your following reply,
but the solution doesn't work for me. I saw you added a modified script. You can also test it with the parameter "Bearer ###" Error 403. But it is not in the JavaScript code. I don't understand what's wrong?
I confirmed the status code 403 from your reply. In this case, it is considered that the site cannot be directly accessed from the Google side. Ref I think that the reason for your issue is due to this.
But, in the case of this situation, there is a workaround. Here, I would like to propose using this workaround. Ref
Sample script:
In this case, the request is run on the custom function. By this, I thought that the status code 403 might be able to be avoided. Actually, when I tested this script using your provided access token, the result value could be obtained.
In this script, the custom function is used. So, please copy and paste the following script to the container-bound script of Google Spreadsheet. And run main(). By this, the request is run on the custom function. And, the returned value can be retrieved with the script.
function modified_pleaseWork() {
var myHeaders = { 'Authorization': 'Bearer 5cd4ac65-f71b-3eaa-93af-78610a7aa320' };
var raw = ["1111111111111"];
var requestOptions = {
'method': 'POST',
'headers': myHeaders,
'payload': JSON.stringify(raw),
'contentType': 'application/json',
};
var result = UrlFetchApp.fetch("https://www.ukrposhta.ua/status-tracking/0.0.1/statuses/last", requestOptions);
return result.getContentText();
}
// Please run this function.
function main() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getRange("A1");
range.setFormula("=modified_pleaseWork()");
SpreadsheetApp.flush();
const value = range.getValue();
range.clearContent();
console.log(value)
}

ReferenceError: Headers is not defined in Google scripts

I am trying to automate between reply.io and Gsheets, to automatically do API calls, so I can create a 'live' dashboard in Google Sheets through script editor.
I am using the documentation on their website (https://apidocs.reply.io/#b24cfec9-3e95-4409-b520-8dfecd75e682). I only work with Python and I succeed there, but somehow I can't seem to make it work in JavaScript.
The script I use is:
function myFunction() {
var myHeaders = new Headers();
myHeaders.append("x-api-key", "{{Your_apiKey}}");
var raw = "";
var requestOptions = {
method: 'GET',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://api.reply.io/v2/schedules/default", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
The error I am getting is:
ReferenceError: Headers is not defined
myFunction # Code.gs:2
Google Apps Script do not use the browser built ins, instead they have their own builtins. In this case you would need to use UrlFetchApp.
function myFunction() {
let myHeaders = {
"x-api-key": "{{Your_apiKey}}"
};
let params = {
method: 'get',
headers: myHeaders,
followRedirects : true,
};
let response = UrlFetchApp.fetch("https://api.reply.io/v2/schedules/default", params);
Logger.log(response.getContentText());
}

How to send a request to a Heroku app through another webpage?

I have a herokuapp deployed on heroku and it can pass all of my postman test. However, when I try to send a request to the herokuapp link through fetch using another project's button, it always fail and break the herokuapp. I'm trying to use the herokuapp as a server and it is already connected with my mongo database.
I copy pasted the code from var myHeaders straight from postman's code generating function.
Here is the code for my request, I have a username and a password input on the page and this function is designed for the sign in button:
function signin() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("username", "dandan");
urlencoded.append("password", "123");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
***mode: 'no-cors'***// This will make it work, but I don't know why
};
fetch("https://emma-game-server.herokuapp.com/signin", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
[UPDATED] I figured out adding mode:'no-cors' will give me the response, but as a noob I don't totally understand.
[UPDATED AGAIN] I figured out that I don't need 'no-cors' and I need to change the request form, here's the final alteration that worked:
function signin() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({"username":username,"password":password});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://emma-game-server.herokuapp.com/signin", requestOptions)
.then(response => response.json())
.then(result => {
console.log(result);
if (result.success){
alert("Signed in as " + result.username);
document.getElementById("user").innerHTML=username;
}
else{
alert(result.message);
}
})
.catch(error => console.log('error', error));
}

Creating form data without using FormData in node-fetch

I'm using node fetch to make API Calls inside a platform.
I need to make an API Call to pass file in form-data.
Below is my stub code:
const fetch = require("node-fetch")
var myHeaders = {"Authorization": "Basic Y2hhdEJvdDpJRkxjYkAxMjM="
,'cache-control': 'no-cache'
,"content-type": "multipart/form-data;"
};
let file_content = "base 64 file content";
let getFormDataForWhatsAppStatement = (data,fileContent,fileExt)=>{
let jsonData = { "data":{ "templateName":"Test_123", "fieldName":"Document_Purpose,Policy_Number,Document_Category", "fieldValue":`AttachDocument, ${data.policyNumber}, Customer_Requirement`, "docList":"Test_Doc" } }
let formDataPairs = [];
let finalFormData = '';
formDataPairs.push(encodeURIComponent("") + '=' + encodeURIComponent(jsonData));
formDataPairs.push(encodeURIComponent("") + '=' + encodeURIComponent(fileContent));
finalFormData = formDataPairs.join('&').replace(/%20/g, '+');
return finalFormData;
}
let formdata = getFormData({"policyNumber":"006558144"},file_content,"png");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata
};
fetch(url, requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));
The error I get here is boundary parameter is not defined.
So I removed the content-type header as stated in the below thread:
Boundary Issue
But then it gives me connection timeout error(since the request format is incorrect).
So is there a way to create formData Similar to the below code without using FormData Object?
const FormData = require('form-data');
const fetch = require("node-fetch")
var formdata = new FormData();
var myHeaders = {"Authorization": "Basic Y2hhdEJvdDpJRkxjYkAxMjM="
//,"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu"
};
formdata.append("", "{ \n \"data\":{ \n\n \"templateName\":\"Test_123\",\n \"fieldName\":\"Document_Purpose,Policy_Number,Document_Category\",\n \"fieldValue\":\"AttachDocument, G0000784, Customer_Requirement\",\n \"docList\":\"Test_Doc\" \n}\n}\n");
formdata.append("", "base 64 file data", "close.png");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow'
};
fetch(API_URL, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Instead of literally inputting the boundary have you tried using the form-data function getBoundary() and assigning it to a variable like so:
let boundary = formdata.getBoundary();
var myHeaders = {"Authorization": "Basic Y2hhdEJvdDpJRkxjYkAxMjM="
"Content-Type": `multipart/form-data; boundary=${boundary}`
};

Categories