Upload json object to Google Cloud Storage with Google Apps Script - json

I'm calling an API in a Google Apps Script. The response is a json object. I'd like to send it to Google Cloud Storage.
Here is the script I wrote so far:
function uploadToGoogleCloudStorage() {
var api_response = '{ "var":"value"}'
var url = 'https://storage.googleapis.com/storage/v1/b/my_bucket_name/o/test?fields=OBJECT'.replace("OBJECT", JSON.stringify(api_response))
var response = UrlFetchApp.fetch(url, {
method: "POST"
});
}
I have the following error Exception: Invalid argument: https://storage.googleapis.com/storage/v1/b/gtm_container_export/o/test?fields="{%20\"var\":\"value\"}"
I didn't find any documentation on how to interact with Google Cloud Storage from Google Apps Script. I'm wondering if UrlFetchApp is the right way to do it or if I should activate a specific service.

Here is a basic example for you - your approach just needs to be modified a bit:
function uploadToGoogleCloudStorage() {
let url = "https://storage.googleapis.com/upload/storage/v1/b/[replace this with your bucket ID]/o?uploadType=media&name=my_test_json.json";
let token = "Bearer [replace this with your oauth token!]";
// this is the content of the document we will create in the bucket
let data = {
'name': 'Bob Smith',
'age': 35,
'pets': ['fido', 'fluffy']
};
let options = {
'method' : 'post',
'headers' : {
'Authorization' : token
},
'contentType': 'application/json',
// Convert the JavaScript object to a JSON string.
'payload' : JSON.stringify(data)
};
var response = UrlFetchApp.fetch(url, options);
console.log( response.getResponseCode() ); // 200 OK
console.log( response.getContentText() );
}
In this case, the file name in the bucket will be "my_test_json.json", as defined in name=my_test_json.json.
Replace [replace this with your bucket ID] with your bucket ID.
Replace [replace this with your oauth token!] with your oauth token.
If you are not familiar with tokens, that is a fairly large topic, and outside the scope of this question. But in case it helps, here are some very basic notes: To generate a test token, I used the OAuth 2.0 Playground to create a test token. I chose "Cloud Storage API" read/write scope. After step 2, I copy/pasted the access_token string out of the "response" box on the right had side of the page. This string is over 300 characters in length. This is not a production-strength solution - it's just for testing.

Related

Wordpress REST API ignoring POST request from Google Apps Script when using 'Body'

I am fiddling for the first time with REST APIs so my knowledge is very low.
I am using Google Apps Scripts to manage Wordpress data through REST API.
POST Requests are perfectly working when options are passed through the URL parameters, while they are ignored when using body.
I initially thought that this was due to some issues on the Wordpress endpoints, however, as sending requests using Postman the calls are being processed correctly, I suppose data is being sent incorrectly from my Google Apps Script.
Postman will expose sent data, offering an option to generate code for a given language, therefore I have used Javascript Fetch as a starting point.
Following is the Postman-generated code, which is correctly processed by Wordpress:
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer some-token-here");
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Cookie", "wordpress_google_apps_login=some-cookie-data-here");
var raw = JSON.stringify({
"acf": {
"class": "Nursery"
}
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://example.com/wp-json/wp/v2/users/442?context=edit&_fields=acf", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
With the above as a starting point, I have adapted code for Google Apps Script, as follows:
var raw = JSON.stringify({
"acf": {
"class": "Nursery"
}
});
var requestOptions = {
'method': 'POST',
'headers': {'Authorization' : 'Bearer some-token-here',
'Content-Type' : 'application/json'},
'body': raw,
'redirect': 'follow'
};
var response = UrlFetchApp.fetch("https://example.com/wp-json/wp/v2/users/442?context=edit&_fields=acf",requestOptions);
Google Apps Script will return a response with code 200, but the requested modifications will not occur. Please notice that the code generated by Postman, uses 'Content-Type', while Google Apps Script should use 'ContentType' parameter. I have tried both, with no success.
Are there some errors in the adapted code, or is there something missing, or even worst, Google Apps Script has some limitations or is it changing somehow the POST request in a way it is not correctly interpreted on the Wordpress end?
EDIT
A quick addition to #idfurw solution, is that it is also required to use 'Content-Type', as the request which includes 'ContentType' will be ignored!
To post the body, use payload property instead of body property.
Reference:
examples of fetch(url, params)
Advanced parameters

Google Apps Script - URL Fetch App returning random numbers

I am new to Apps Script and was trying to build an API and call that API through a different script. I created the web app and published it.
This is the URL:
https://script.google.com/macros/s/AKfycbxKVmGy3fxDfoHxyDtQh7psqj7IdKF7qHbgxLAwNRoiKTA-bpKN4QKtArzwsYdFb-Hb/exec
When I open this link, I can see the data correctly but when I try to fetch this data from a different script using urlfetchapp, it returns random numbers. I need help on what I am doing incorrectly.
Script which I am using to call this data:
function GetCopies()
{
var options = {
'contentType': "application/json",
'method' : 'get',
};
var Data = UrlFetchApp.fetch('https://script.google.com/macros/s/AKfycbxKVmGy3fxDfoHxyDtQh7psqj7IdKF7qHbgxLAwNRoiKTA-bpKN4QKtArzwsYdFb-Hb/exec',options)
Logger.log(Data.getContent())
}
This is the log I get:
I tried parsing it, but it throws an error:
How can I get data from URL correctly?
A working sample:
Create two Google Apps Script projects. In my case API and fetcher
API
const doGet = () => {
const myObj = {
"name": "Mr.GAS",
"email": "mrgas#blabla.com"
}
return ContentService
.createTextOutput(JSON.stringify(myObj))
.setMimeType(
ContentService.MimeType.JSON
)
}
fetcher
const LINK = "API_LINK"
const fetchTheAPI = async () => {
const options = {
'contentType': "application/json",
'method': 'get',
}
const res = UrlFetchApp.fetch(LINK, options)
const text = res.getContentText()
console.log(JSON.parse(text))
}
Deploy the API: Select type > Web app and Who has access > Anyone, copy the URL (it is important to copy that URL not the one redirected in the browser)
Replace the "API_LINK" by the URL.
Run the function.
You only need to adapt this example to suit your needs.
Documentation:
Content Service
Web Apps

Google Apps Script UrlFetchApp GET to a node.js endpoint results in an empty body

I am using Google Apps Script to make a UrlFetchApp call to a node.js API endpoint. I own both the Google Apps Script code and node.js code & endpoint, so I can watch what is happening.
When I use Postman, it works. But when I use GAS UrlFetchApp, it doesn't work, as req.body in node is empty { }. I even looked at the code that Postman creates for JavaScript Fetch and try to nearly duplicate it, except for things I know GAS' UrlFetchApp needs. I've done quite a few UrlFetchApp calls with GAS to various external endpoints. So, I'm not new, but can't figure this one out.
Here is my Google Apps Script code:
var url = 'https://xxxxxxxxxxx.azurewebsites.net/api/account';
var data = {
"email": address,
"apiKey": 'xxxxxxxxxxxxxxxxxxx'
}
var payLoadInfo = JSON.stringify(data);
var options = {
"method": "GET",
"headers": {'Content-Type': 'application/json'},
// 'Content-Type': 'application/json',
// "contentType": 'application/json',
redirect: 'follow',
"muteHttpExceptions": true,
"body": payLoadInfo,
// "payload": JSON.stringify(data)
// payload: payLoadInfo
};
var response = UrlFetchApp.fetch(url, options);
The commented out parts of "options" are several different ways I've tried to get it to work. I know in the past that I've usually used "payload" instead of "body" like I am this time (Postman suggested it). When I use "payload", it fails completely, not even getting to my node code. I also tried putting the apiKey in the header.
Here is the node.js API endpoint code:
router.get("/account", async (req, res) => {
var apiKey = process.env.API_KEY;
console.log('apiKey = ' + apiKey);
console.log('req.body = ' + JSON.stringify(req.body, null, 2));
console.log('req.body.apiKey = ' + req.body.apiKey);
if (req.body.apiKey != apiKey) {
console.log('apiKey is not equal');
res.status(401).send({ error: "You are not authorized." });
} else {
process the request...
}
When I use "payload" in "options" I get a 500, and the server code never executes.
When I use "body" in "options", I see the server code execute, but the console.log('req.body = ' + JSON.stringify(req.body, null, 2)), just comes back with an empty object {}, and then since req.body.apiKey != apiKey, it consoles "apiKey is not equal" and sends a 401. When using Postman, the req.body object consoles fine, showing the email & apiKey.
No matter what combinations of things I put into options, it fails either with 500 or 401. However, Postman works great with pretty much the same parameters, headers, etc.
Here is what Postman shows for the code:
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Cookie", "ARRAffinity=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ARRAffinitySameSite=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var raw = JSON.stringify({"email":"xxxxxxxxxxxxxxxxx#gmail.com","apiKey":"xxxxxxxxxxxxxxxx"});
var requestOptions = {
method: 'GET',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
I even tried including the cookie and "redirect: follow", but none works.
What am I missing?
I got it to work, thanks to help from #Tanaike (see comments above).
It seems that unlike normal "fetch" in node.js, URLFetchApp in Google Apps Script will not send a body along with a GET.
I still used GET, but changed to sending the param in the URL and the apiKey in the header.

Calling third party JIRA REST API in Cloud Function for Dialogflow always timeout

We need to call JIRA Rest API to get a specific information from the given query in Dialogflow.
We need to provide response to user based on the response from the API. However, the Dialogflow is unable to retrieve any response from JIRA API through the fulfillment in Firebase Cloud function as it's always timeout.
Based on the log in Firebase console, it always take more than 6000 ms for the execution.
Meanwhile if I use postman to call the JIRA REST API, it takes less than 1 second to get the response.
Some said we need to use promise but I does not seem to work as well.
Please help how should I solve this problem?
Please see my code below
function checkcontract(agent){
var parameters = request.body.queryResult.parameters;
var customer_id = parameters.customer_id;
var bodyData = JSON.stringify({"jql": "project = CDB AND 'Customer ID' ~ "+customer_id,
"maxResults": 1,
"fieldsByKeys": false,
"fields": [
"summary",
"customfield_11949", //Customer ID custom field
"customfield_11937", // Contract Start Date
"customfield_11938", //Contract End Date
"customfield_11936", //email
"customfield_11946", //default JSD request id
"customfield_11943", //project id
"customfield_11941" //project key
],
"startAt": 0
});
var options = {
method: 'POST',
url: '/rest/api/3/search',
auth: { bearer: authorization_token },
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: bodyData
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(
'Response: ' + response.statusCode + ' ' + response.statusMessage
);
console.log(body);
});
}
EDIT:
JIRA API returns a response to the function. But the agent.add("message") does not return anything to the chat.

Which calls need an access token in ActiveCollab v5 API

I'm playing with Google Apps Script utilizing the ActiveCollab HTTPS API as a way to link Google Forms to specific projects. I can't figure out where to use the access token in the HTTP request when creating a Task in a project.
Maybe I'm missing it, but which API calls in the documentation require the access token as part of the POST request?
The most basic POST request I've sent was:
var token = // token from authentication
{
"name": "Test task",
"token": token
}
...and it returned a 401 error, saying I wasn't authenticated.
So, I tried:
var token = // token from authentication
{
"name": "Test task",
"username": // my username,
"password": // my password,
"token": token
}
...with the same result. So, which calls require a token and does the token go in the POST payload? Or should it be in the POST options?
Update 3/10/2016
I have added the Authorization parameter to the POST request and am now receiving an invalid token error in the response. I've cleared my cache and reauthorized successfully. My test function is below.
function postTicket() {
// Retrieve the stored token after a successful authorization
var token = PropertiesService.getScriptProperties().getProperty("token");
var data = {
"name": "Testing task"
}
var headers = {
Authorization: 'Bearer ' + token
};
var options = {
"method": "post",
"contentType": "application/json",
"headers": headers,
"payload": JSON.stringify(data)
}
try {
var url = BASE_URL + "/projects/8/tasks";
var response = UrlFetchApp.fetch(url, options);
var json = response.getContentText();
var data = JSON.stringify(json)
Logger.log(data);
} catch (e) {
Logger.log(e);
}
}
The logged error is:
returned code
500.{"type":"ActiveCollab\Authentication\Exception\InvalidTokenException","message":"Authorization
token is not valid","code":0
I had the same problem, but after checking Active Collab SDK code i figured out, that we should use these headers:
var headers = {
'X-Angie-AuthApiToken': token
};
By using this code i'm allowed to create tasks via API.
Token needs to be sent using Authorization HTTP header:
Authorization: Bearer TOKEN_THAT_YOU_GOT_FROM_ACTIVE_COLLAB
This means that you need to send the token as part of request header, not payload. Please check the Google Apps documentation for details (I see that fetch has headers object as one of the arguments, so there is support for this type of interaction built into the platform).