400 Bad Request Error using URLFetchApp and Google sheets Script - google-apps-script

I have the below script, that is returning a 400 - bad request.
function createIssue(e)
{
var url = "https://jira.xxxx.com/rest/api/2/issue/";
var data = {'fields': {
'project': {'key':'DWH'},
'summary':'Resttest',
'description':'test',
'issuetype':{ 'name': 'Data Requests'},
'components':[{ 'name':'Data Warehouse'}],
'fixVersions':[{ 'name':'NA'}] }};
var payload = JSON.stringify(data);
Logger.log(payload);
var headers =
{
'content-type': 'application/json',
'Accept': 'application/json',
'authorization': 'Basic xxxxxxxxxxxxxx'
};
var options =
{
'content-type': 'application/json',
'method': 'POST',
'muteHttpExceptions' : true,
'headers': headers,
'payload': payload
};
var response = UrlFetchApp.fetch(url, options);
var rc = response.getResponseCode();
var responseText = response.getContentText();
var dataAll = JSON.parse(response.getContentText());
var issueKey = dataAll.key
Logger.log(dataAll)
}
I have tested out the actual payload via cURL and it was working, so Is there something else I am missing with this script?
Thanks a million for any assistance.
Best,
Neil
EDIT:
The curl command :
curl -D- -H
"Authorization: Basic xxxxxxxxxxxx1bXBraW5zMDQh" -X POST --data
"{ """fields""": { """project""": { """key""": """DWH""" }, """summary""":
"""REST test 11111.""", """description""": """test""", """issuetype""": {
"""name""": """Data Requests""" }
,"""components""":[{ """name""":"""Data Warehouse"""}] , """fixVersions""":
[{"""name""":"""NA"""}]} }" -H "Content-Type: application/json"
https://jira.xxxxxxxxx.com/rest/api/2/issue/
I was doing some further reading and it appears that the google apps scripts are run from the google servers. My jira instance is behind a company intranet, and as such not accessible from googles servers. I also note a useIntranet feature that is depreciated. Is there any way around this?
Many thanks,
Neil

Related

call an API from App script and send binary data as a POST parameter

I'm trying to use an API, the CURL command is this one :
curl --user "<your-client-id>:<your-client-secret>" "https://api.everypixel.com/v1/faces?url=https://labs.everypixel.com/api/static/i/estest_sample3.jpg"
In my use case, I'm sending images from those type of urls : https://media-exp1.licdn.com/dms/image/C5603AQFLzBsLRsZBXQ/profile-displayphoto-shrink_800_800/0/1652669513751?e=1674086400&v=beta&t=-NC598zxFjG9fDOMJeqmLuYrP0e9NnCv92aup4MK2Wk
My problem is handling the image as the image url is not a jpg / png like the example in the CRUL command.
My script looks like this :
var url = "https://api.everypixel.com/v1/faces";
const response = UrlFetchApp.fetch(url, {
"method": "POST",
"headers": {
"Cache-Control": "no-cache",
"Content-Type": "application/json",
"user": "<your-client-id>:<your-client-secret>"
},
"muteHttpExceptions": true,
"followRedirects": true,
"validateHttpsCertificates": true,
"contentType": "application/json",
"payload": JSON.stringify({
"url": "https://media-exp1.licdn.com/dms/image/C4D03AQEnKuhl53UqCA/profile-displayphoto-shrink_800_800/0/1563935310527?e=2147483647&v=beta&t=8x-OjnqJCg6U7jt9Zm2rRscO22pG5C5QvgSh7H9lfSI"
})
});
var data = JSON.parse(response.getContentText());
I believe your goal is as follows.
You want to convert the following curl command to Google Apps Script.
curl --user "<your-client-id>:<your-client-secret>" "https://api.everypixel.com/v1/faces?url=https://labs.everypixel.com/api/static/i/estest_sample3.jpg"
In this case, how about the following modification?
Modified script:
function myFunction() {
const url = `https://api.everypixel.com/v1/faces?url=${encodeURIComponent("https://labs.everypixel.com/api/static/i/estest_sample3.jpg")}`;
const response = UrlFetchApp.fetch(url, {
"headers": { "Authorization": "Basic " + Utilities.base64Encode("<your-client-id>:<your-client-secret>") },
"muteHttpExceptions": true,
});
const data = JSON.parse(response.getContentText());
}
The sample curl command is the GET method.
url=https://labs.everypixel.com/api/static/i/estest_sample3.jpg is the query parameter.
--user "<your-client-id>:<your-client-secret>" is the basic authorization.
Note:
I think that the request of this modified script is the same as the curl command. But, if an error occurs, please confirm the values of <your-client-id>:<your-client-secret> and the URL again.
Reference:
fetch(url, params)

Google Script urlFetchApp Post failing calling Jira Tempo worklogs

I trying to write a google script to query Jira Tempo worklogs.
This is what I have so far:
function postDataForAPI() {
var payloadData = {
"taskKey" : []
};
payloadData.taskKey.push("AA-123");
var payload = Utilities.jsonStringify(payloadData);
var url = "https://api.tempo.io/core/4/worklogs/search";
var digestfull = PropertiesService.getUserProperties().getProperty("digest"); //get username and password (base64 encrypted)
var options = { "Accept":"application/json",
"Content-Type":"application/json",
"method": "POST",
"headers": {"Authorization": digestfull},
"muteHttpExceptions": true,
"payload" : payload
};
var resp = UrlFetchApp.fetch(url,options);
if (resp.getResponseCode() != 200) {
Browser.msgBox("Error retrieving data for url " + url + ":" + resp.getContentText());
return "";
}
else {
return resp.getContentText();
}
}
When I execute the above it fails.
If I use curl then I can successfully make the request (I think this is essentially the same POST):
curl -u "username:password" -X POST https://api.tempo.io/rest/tempo-timesheets/4/worklogs/search -H 'Content-Type: application/json' -d '{"taskKey":["AA-123"]}'
Making GET requests against the same API works fine:
function getDataForAPI() {
var url = "https://api.tempo.io/core/4/worklogs/101112";
var digestfull = PropertiesService.getUserProperties().getProperty("digest"); //get username and password (base64 encrypted)
var options = { "Accept":"application/json",
"Content-Type":"application/json",
"method": "GET",
"headers": {"Authorization": digestfull},
"muteHttpExceptions": true
};
var resp = UrlFetchApp.fetch(url,options);
if (resp.getResponseCode() != 200) {
Browser.msgBox("Error retrieving data for url " + url + ":" + resp.getContentText());
return "";
}
else {
return resp.getContentText();
}
}
So I'm confident it is not Authorisation (GET request succeeds). The curl request succeeds and appears to be in the same form as the google script and yet the google script POST fails.
What do I have wrong?
I believe your goal is as follows.
You want to convert the following curl command to Google Apps Script.
curl -u "username:password" -X POST https://api.tempo.io/rest/tempo-timesheets/4/worklogs/search -H 'Content-Type: application/json' -d '{"taskKey":["AA-123"]}'
Modification points:
It seems that "Accept":"application/json" is not used in the sample curl command.
"Content-Type":"application/json" is required to be included in the request header. But, at UrlFetchApp, the property of contentType can be used.
Utilities.jsonStringify has been deprecated. Ref
When these points are reflected in your script, it becomes as follows.
Modified script:
function postDataForAPI() {
var payloadData = { "taskKey": [] };
payloadData.taskKey.push("AA-123");
var url = "https://api.tempo.io/core/4/worklogs/search";
var digestfull = PropertiesService.getUserProperties().getProperty("digest");
var options = {
"method": "POST",
"contentType": "application/json",
"headers": { "Authorization": digestfull },
"muteHttpExceptions": true,
"payload": JSON.stringify(payloadData)
};
var resp = UrlFetchApp.fetch(url, options);
if (resp.getResponseCode() != 200) {
Browser.msgBox("Error retrieving data for url " + url + ":" + resp.getContentText());
return "";
}
else {
return resp.getContentText();
}
}
Note:
When I saw your provided curl command, it seems that the URL is different. The sample curl command uses https://api.tempo.io/rest/tempo-timesheets/4/worklogs/search. But your script uses https://api.tempo.io/core/4/worklogs/search. I'm worried about this difference. So if the above-modified script didn't work, please check the URL again.
The request of this modified script is the same as the sample curl command. But if an error occurs, please check each value like digestfull and payloadData, again.
Reference:
fetch(url, params)

LinkedIn API OAUTH returning "grant_type" error

I am pretty new to coding, but trying to write a simple script using LinkedIn's API that will pull an organizations follower count into google app script. Before I can even query the API, I have to authenticate using oath explained in the LinkedIn API here.
This function returns with an error response
function callLinkedAPI () {
var headers = {
"grant_type": "client_credentials",
"client_id": "78ciob33iuqepo",
"client_secret": "deCgAOhZaCrvweLs"
}
var url = `https://www.linkedin.com/oauth/v2/accessToken/`
var requestOptions = {
'method': "POST",
"headers": headers,
'contentType': 'application/x-www-form-urlencoded',
'muteHttpExceptions': true
};
var response = UrlFetchApp.fetch(url, requestOptions);
var json = response.getContentText();
var data = JSON.parse(json);
console.log(json)
}
When I try sending the headers through I get this error as a response
{"error":"invalid_request","error_description":"A required parameter \"grant_type\" is missing"}
grant_type, client_id, client_secret do not go in the header of the request. Instead, try to put them in the body of the POST request with the content type x-www-form-urlencoded as you already had in the headers of the code you posted.
For example:
fetch('https://www.linkedin.com/oauth/v2/accessToken/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: '78ciob33iuqepo',
client_secret: 'deCgAOhZaCrvweLs'
})
})
.then(response => response.json())
.then(responseData => {
console.log(JSON.stringify(responseData))
})
Using Apps Script you should send the payload like so:
Example:
function callLinkedAPI() {
var payload = {
"grant_type": "client_credentials",
"client_id": "78ciob33iuqepo",
"client_secret": "deCgAOhZaCrvweLs"
}
var url = `https://www.linkedin.com/oauth/v2/accessToken/`
var requestOptions = {
'method': "POST",
'contentType': 'application/x-www-form-urlencoded',
'muteHttpExceptions': true,
"payload":payload
};
var response = UrlFetchApp.fetch(url, requestOptions);
var json = response.getContentText();
var data = JSON.parse(json);
console.log(json)
}

Error while calling freshchat APIs from google apps script

I am trying to call FreshChat API from google apps script. GET request of outbound-messages is working fine but POST request is failing with error
Exception: Request failed for http://api.in.freshchat.com returned code 400. Truncated server response: {"success":false,"errorCode":0,"errorMessage":"HTTP 405 Method Not Allowed","errorData":null,"errorName":null} (use muteHttpExceptions option to examine full response)
Below are the details of request
function myFunctiontest() {
var url = "http://api.in.freshchat.com/v2/outbound-messages/whatsapp";
var headersPOST = {
'Authorization': 'Bearer XXXXXX',
'Content-Type': 'application/json',
'Accept': 'application/json'
};
var bodyPayload = {"from": {"phone_number": "+XXXXXX"},"provider": "whatsapp","to": [{"phone_number": "+XXXXX"}],"data": {"message_template": {"storage": "none","template_name": "XXXXXX","namespace": "XXXXX","language": {"policy": "deterministic","code": "en"},"template_data": [{"data": "XXXXX"}]}}};
var options = {
'method': 'post',
'contentType': 'application/json',
'headers': headersPOST,
'payload': JSON.stringify(bodyPayload),
'muteHttpExceptions':true
};
var response = UrlFetchApp.fetch(url, options);
console.log(response.getAllHeaders());
Logger.log(JSON.parse(response.getContentText()));
}
Same headers are working for GET request. Also same post request is working from POSTMAN.
Freshchat support helped for solving the issue.
There are two major changes
use https instead of http
Added contentType inside headers.
function myFunctiontest() {
var url = "https://api.in.freshchat.com/v2/outbound-messages/whatsapp";
var headersPOST = 'Bearer XXXXXX';
var bodyPayload = {"from": {"phone_number": "+XXXXXX"},"provider": "whatsapp","to": [{"phone_number": "+ XXXXX"}],"data": {"message_template": {"storage": "none","template_name": "XXXXXX","namespace": "XXXXX","language": {"policy": "deterministic","code": "en"},"template_data": [{"data": "XXXXX"}]}}};
var options = {
method: 'POST',
//content-type: 'application/json',
headers: { Authorization: headersPOST, 'content-type': 'application/json'},
payload: JSON.stringify(bodyPayload),
muteHttpExceptions:true
};
var response = UrlFetchApp.fetch(url, options);
var text = response.getResponseCode();
}

How to use Google Apps Script to create issues in Redmine?

I'm trying to create an issue in Redmine using Google Apps Script, the code is following:
function create_issue() {
var payload = {
'project_id': 'helpdesk',
'subject': 'This is a test ticket',
'description': 'This is just a genius test ticket',
'category_id': 1
};
var headers = {
'X-Redmine-API-Key': '<myapikey>',
'Content-Type': 'application/json'
};
var url = 'http://myredmine.com/issues.json';
var options = {
'method': 'POST',
'headers': headers,
'payload': payload,
//uteHttpExceptions': true
};
var response = UrlFetchApp.fetch(url, options);
Logger.log(response);
}
Every time I ran that script, it threw the following exception:
Execution failed: Request failed for http://myredmine.com/issues.json
returned code 422. Truncated server response: {"errors":["Subject
can't be blank"]} (use muteHttpExceptions option to examine full
response) (line 25, file "Code") [0.645 seconds total runtime]
But as you see, the "subject" parameter was passed in the payload already. What am I missing?
Thanks,
Trinh
I found the problem, I need to indicate the issue in the payload:
function create_issue() {
var issue = {
"description": "Test ticket",
"subject": "Genius ticket"
}
var payload = {
"issue": issue,
"key": "<myapikey>",
"project_id": "helpdesk",
};
payload = JSON.stringify(payload);
var headers = {
'X-Redmine-API-Key': '<myapikey>',
'Content-Type': 'application/json'
};
var url = 'http://myredmine.com/issues.json';
var options = {
'method': 'POST',
'headers': headers,
'payload': payload,
'contentType': 'application/json',
//'muteHttpExceptions': true
};
var response = UrlFetchApp.fetch(url, options);
Logger.log(response);
}
And it works!