GAS: Error when using UrlFetchApp - google-apps-script

I am using the senotp serverside api to verify a number. When it is run using soap ui with the same content there's no error. But when I do it with UrlFetchApp it gives the error:
{"status":"error","response":{"code":"INVALID_REQUEST_BODY"}}
whereas the correct response should be:
{
"status": "success",
"response": {
"code": "OTP_SENT_SUCCESSFULLY",
"oneTimePassword": "34859"
}
}
The code I used is as foll0ws:
var payload =
{
"countryCode": "94",
"mobileNumber": "0766075555",
"getGeneratedOTP": true
};
var header=
{
"application-Key":"application_key_value"
};
var options =
{
"method" : "POST",
"headers":header,
"muteHttpExceptions": true,
"contentType":"application/json",
"payload" : payload
};
var request=UrlFetchApp.getRequest("https://sendotp.msg91.com/api/generateOTP", options)
Logger.log(request)
var response=UrlFetchApp.fetch("https://sendotp.msg91.com/api/generateOTP", options);
Logger.log(response);
I am not sure what is the problem here. Please help me debug it or let me know what is the problem with the code.

It seems as if using payload in GAS fetchService automatically results in contentType : application/x-www-form-urlencoded or contentType : multipart/form-data.
See documentention: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)
Unfortunately, I have not yet found a workaround.

Related

Send data to Influxdb using Google app script

I'm trying to send the data to Influxdb using Google app script with the below code but I always run into Bad Request error. The same works when I send the data using the Influxdb API. Unable to figure out what am I missing here. Any suggestions would be appreciated.
function dataentry() {
var response;
var tags = {
"PROGRAM":"Migration"
}
var fields = {
"TESTED_BY": "Peter",
"RESULT":1,
"STATUS":"Fail"
}
var data = {"measurement":"testing","tags":tags,"time":,"fields":fields};
Logger.log(JSON.stringify(data));
var options = {
"method" : "post",
"muteHttpExceptions" : true,
"contentType": "application/json",
"payload" : JSON.stringify(data)
//"payload" : data
};
try {
response = UrlFetchApp.fetch('http://xx.xx.xx.xx:8086/write?db=mydbb', options);
Logger.log(response.getContentText());
}
catch(err) {
Logger.log(err);
}
}
Output: Exception: Bad request: http://xx.xx.xx.xx:8086/write?db=mydbb
Example of the Influxdb http write API -
curl -i -XPOST http://xx.xx.xx.xx:8086/write?db=mydbb --data-binary "testing,PROGRAM=Migration TESTED_BY=\"Peter\",STATUS=\"Fail\",RESULT=1"

Slack API call to postMessage not working

I'm just trying to make a simple postMessage call from a google apps script with an image attached, but I get the following response:
"{"ok":false,"error":"invalid_arg_name"}"
Here is the function that creates the payload:
function getPostMessagePayload(fileUrl) {
var content = {
"channel":"#data-vis",
"token": ACCESS_TOKEN,
"text":"Chart update:",
"attachments": [
{
"title": "Chart",
"fallback": "Fallback",
"text": "Testing chart",
"image_url": fileUrl
}
]
};
return content;
}
And here is where I make the request:
var POST_MESSAGE_ENDPOINT = 'https://slack.com/api/chat.postMessage';
function performPostMessage(payload) {
var res = UrlFetchApp.fetch(
POST_MESSAGE_ENDPOINT,
{
method: "post",
payload: JSON.stringify(payload),
muteHttpExceptions: true,
}).getContentText();
return res;
}
It's impossible to tell what the actual problem is. I've tried making my token obviously incorrect, the URL obviously incorrect, and deleting/adding random args and it gives the same response every time.
When I use the webhook to do this rather than the API, it works fine.
My app has the following permissions in Slack:
chat:write:bot
incoming-webhook
Problem
You are sending a JSON object as payload with your POST request, whilst the contentType parameter of the fetch() method is defaulted to application/x-www-form-urlencoded.
Solution 1
In addition to JSON.stringify(), to ensure the payload is sent correctly, wrap it in an encodeURIComponent() built-in function. If the issue persists, continue to solution 2.
Update to solution 1
Nearly forgot how fetch() method treats objects passed to payload with default x-www-form-urlencoded content type. Remove the JSON.stringify() entirely (and add encodeURI() / encodeURIComponent() if needed).
Solution 2
Slack API supports application/json content type of POST requests. In your case it might be easier to send the request with contentType parameter set to application.json (note that you will have to move authorization from payload to headers):
//fetch part;
var res = UrlFetchApp.fetch(
POST_MESSAGE_ENDPOINT,
{
method : 'post',
contentType : 'application/json',
headers : {
Authorization : 'Bearer ' + ACCESS_TOKEN
},
payload : JSON.stringify(payload),
muteHttpExceptions : true,
})
//payload part;
var payload = {
"channel" : "#data-vis",
"text" : "Chart update:",
"attachments" : [
{
"title" : "Chart",
"fallback" : "Fallback",
"text" : "Testing chart",
"image_url" : fileUrl
}
]
};
Useful links
fetch() method reference;
postMessage method reference (Slack API);

Apps Script API returning 404 error for existing project. Error returned as HTML rather than JSON

I was attempting to run an Apps Script function using the Apps Script API. I set up the script in the console, and created an oauth client ID for the script. I configured the authorisation screen and deployed the script as API executable. I tested the api function calling in the same script but got a 404 error saying:
The Requested URL /v1/scripts/{{my_script_id}}:run was not found on this server.
The response came back as HTML. I also noticed that the script seems to make it's own client ID when it's called from the API.
I tried disabling and re-enabling the API which didn't work. I think it may be a problem with the calling application not being in the same project but I'm not sure how to do that as the Google documentation is unclear.
function trigger(){
var bogus = DriveApp.getRootFolder();
var argument = ["Value0", "Value1", "Value2", "Value3", "Value4", "Value5"];
// https://www.googleapis.com/auth/script.external_request
// https://www.googleapis.com/auth/spreadsheets
var postRequest = {
"Content-Type": "application/json",
"headers": { "Authorization" : "Bearer " + ScriptApp.getOAuthToken()},
"function": "setStatus",
"muteHttpExceptions": true,
"parameters": [argument],
"devMode": false
};
try{
var response = UrlFetchApp.fetch("https://script.googleapis.com/v1/scripts/{{my_script_id}}:run", postRequest);
Logger.log(response);
}catch(err){
Logger.log(err);
}
}
I expected some form of error in the form of JSON or maybe even for the function to run, what I got was a HTML document which displayed a 404 error when displayed.
You're not POSTing the request. Default .fetch method is GET.
Add this in postRequest object:
method: "POST",
payload is also missing from your postRequest.
Snippet:
var postRequest = {
"method":"POST", //added
"contentType": "application/json", //key changed
"headers": { "Authorization" : "Bearer " + ScriptApp.getOAuthToken()},
"muteHttpExceptions": true,
"payload": JSON.stringify({ //added
"function": "setStatus",
"parameters": argument, //removed []
"devMode": false
})
};
References:
UrlfetchApp
Script:run

How to use google url shortner api by UrlFetchApp.fetch correctly?

I spent a lot of time reading google manuals and other resources and didn't find out what I'm doing wrong when trying to get short url using this script:
function test_short_link() {
var apiKey, post_url, options, result;
post_url = "https://www.googleapis.com/urlshortener/v1/url";
apiKey = 'xxx';//here is real apiKey
post_url += '?key=' + apiKey;
var options =
{ 'method':'post',
'headers' : {'Content-Type' : 'application/json'},
"resource": {"longUrl": "https://google.com/"},
'muteHttpExceptions': true
}
result = UrlFetchApp.fetch(post_url, options);
Logger.log(result);
}
I did various modifications but it returns:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Required",
"locationType": "parameter",
"location": "resource.longUrl"
}
],
"code": 400,
"message": "Required"
}
}
It drives me mad!
Please help! What is wrong with this code?
You will need to modify this code as it hard codes the longUrl and does no error checking. Some of the important parts are that the API options are sent in the payload of the UrlFetchApp options object and that you need to pass the current users OAuth token in the header.
function ShortenUrl(){
var url = "https://www.googleapis.com/urlshortener/v1/url"
var payload = {"longUrl":"www.google.com"};
var parameters = { method : 'post',
headers : {'Authorization': 'Bearer '+ScriptApp.getOAuthToken()},
payload:JSON.stringify(payload),
contentType:'application/json',
muteHttpExceptions:true};
var response = UrlFetchApp.fetch(url, parameters);
Logger.log(response);
}
There is also an advanced Google service to do it more simply.
You'll need to activate it from the script editor ressource menu (see illustrations below.)
Code is as simple as that :
function shortenUrl(longUrl) {
var toShorten = UrlShortener.newUrl().setLongUrl(longUrl);
var shortened = UrlShortener.Url.insert(toShorten);
return shortened.id;
}
Just use it as in this test function below :
function test(){
var shortUrl = shortenUrl("http://stackoverflow.com/questions/tagged/google-apps-script");
Logger.log(shortUrl);
}

How to send a JSON payload with UrlFetchApp service?

I'm trying to POST to a web service that is expecting to get JSON as payload using Google Apps Script. I'm using the following code:
var options =
{
"method" : "post",
"contentType" : "application/json",
"headers" : {
"Authorization" : "Basic <Base64 of user:password>"
},
"payload" : { "endDate": "2012-06-03" }
};
var response = UrlFetchApp.fetch("http://www.example.com/service/expecting/json", options);
On the server side I'm getting the following error:
WARN [facade.SettingsServlet] 04 Jun 2012 15:30:26 - Unable to parse request body: endDate=2012-06-03
net.liftweb.json.JsonParser$ParseException: unknown token e
I'm assuming that the server is expecting to get
{ "endDate": "2012-06-03" }
instead of
endDate=2012-06-03
but I don't know how to make the UrlFetchApp do it.
I do not understand the server side error but the 'payload' parameter must be a string as specified here: https://developers.google.com/apps-script/class_urlfetchapp?hl=fr-FR#fetch.
try:
var options =
{
"method" : "post",
"contentType" : "application/json",
"headers" : {
"Authorization" : "Basic <Base64 of user:password>"
},
"payload" : '{ "endDate": "2012-06-03" }'
};
If you set payload as a String, it will be passed directly (as a
UTF-8 string).
If you set payload as an Object, it will be sent like
an HTML form (which means either 'application/x-www-form-urlencoded' if the
fields are simple, or 'multipart/form-data' if the Object includes a
blob/file).
For your use case (the server is expecting to receive JSON), it sounds like Utilities.jsonStringify() is the way to go.
Something like this worked for me in a similar situation:
Instead of creating payload and adding to options, I built the parameters into a string to append to the URL:
var params = "id=2179853&price=62755";
then, I appended params to the url string:
var result = UrlFetchApp.getRequest(url + '?' + params, options);
So, my options was passed containing only the header.
For my project, this worked like a charm.
Here goes the code that should work with some important comments:
function testMe() {
var products_authkey = "------------";
try {
var url = "https://app.ecwid.com/api/v1/---------/product?id=----------&secure_auth_key=" + products_authkey;
//url= "http://requestb.in/----------"; // you can actually debug what you send out with PUTs or POSTs using Requestb.in service
var payload = {
id: "21798583", // id is necessary and should be a string, or it might be sent in scientific representation (with E)
price: 62755
};
payload = JSON.stringify(payload); // the payload needs to be sent as a string, so we need this
var options = {
method: "put",
contentType: "application/json", // contentType property was mistyped as ContentType - case matters
payload: payload
};
var result = UrlFetchApp.getRequest(url, options);
Logger.log(result) // a better way to debug
var result = UrlFetchApp.fetch(url, options); // works perfectly in my case
Logger.log(result)
} catch (e) {
Logger.log(e)
}
}