UrlFetchApp.fetch Link Length Limit - google-apps-script

I'm having some trouble with the UrlFetchApp class, fetch() method. I've singled out the issue, and it seems to be the fact that the actual link I'm fetching is just too long
When I eliminate some needed data(resulting in ~1900 characters), it send the fetch request fine
The length limit is somewhere between 2040 and 2060 characters, as that is where it stops working and I receive a "Bad request" error. I'm assuming it's 2048, as that seems to have been the industry standard some time ago.
I'm needing to fetch data from a link that's upwards of 3400 characters! Is this just too long? 2048 characters might have been understandable a while back, but in this day in age it's a limit that is going to be met quite often
My question is this: Is there a way around this? I'm assuming Google set the limit, is there some way to request this limit be raised?
Thank you!

The restriction is on the size (2kB) and not on the length of the url.
On March 30, 2018, Google deprecated the URL Shortener service that was used in the accepted answer.
I wrote a script to use the Firebase Dynamic Links Short Links API service.
The docs are here if you want to cook your own.

You can try UrlShortener to shorten the URL and then use UrlFetchApp with the shortened URL

I used the POST method with payload data instead, showed here:
Google Apps Script POST request UrlFetchApp
The classic code is:
// Make a POST request with form data.
var resumeBlob = Utilities.newBlob('Hire me!', 'text/plain', 'resume.txt');
var formData = {
'name': 'Bob Smith',
'email': 'bob#example.com',
'resume': resumeBlob
};
// Because payload is a JavaScript object, it is interpreted as
// as form data. (No need to specify contentType; it automatically
// defaults to either 'application/x-www-form-urlencoded'
// or 'multipart/form-data')
var options = {
'method' : 'post',
'payload' : formData
};
UrlFetchApp.fetch('https://httpbin.org/post', options);

Related

Custom WP API endpoint NULL body data

I have a weird issue, that bashes my head in. It's probably something minor that I am overlooking, but for the life of me I cannot figure it out.
Here's the premise:
I am making a POST request to a custom registered api endpoint in a wp environment, to which i am sending json data from a form. Content type is set correctly and if i debug by dumping $request->get_body() it shows the correct data that i've passed on.
however, i also send base64 encoded image data, resulted from a file reader. If i add another item to the data being send and the base64 string as the value for it, the dump becomes NULL. Taking the base64 string out of the json, makes the dump become ok again.
I have also tried to increase the max upload size, and post size however, since the file i am using as test is 20 KB, I do not think this is the issue.
I am hoping somebody can help me see the error of my ways.
Here's a code snippet. Note that the URL is not real here, but real in my environment. Also, due to char limit, I could not post the whole base64 image in the snippet, but rest assured it is correct. I even tried with a 1px by 1px transparent image and I had the same problem.
var image = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4QDeRXhpZgAASUkqAAgAAAAGABIBAwABAAAAAQAAABoBBQABAAAAVgAAABsBBQABAAAAXgAAACgBAwABAAAAAgAAABMCAwABAAAAAQAAAGmHBAABAAAAZgAAAAAAAAA4YwAA6AMAADhjAADoAwAABwAAkAcABAAAADAyMTABkQcABAAAAAECAwCGkgcAFgAAAMAAAAAAoAcABAAAADAxMDABoAMAAQAAAP//AAACoAQAAQAAABgCAAADoAQAAQAAAGIBAAAAAAAA...";
var data = {
'test': 'hello world',
'image': image
};
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify(data);
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("/wp-json/test/v1/testapi", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
I have solved the issue. It was unrelated to json / javascript / api.
It was a simple issue of tmp folder ownership. Since there were no errors spewing out by the php managing the request, I never noticed a PHP NOTICE saying to check permissions in temp folder as php was unable to upload the temp file there. And indeed, while the permissions were fine, the group ownership was not.
Sorry to have wasted everybody's time. Thank you.

"Invalid argument" when sending GET to spaces.members.list

I'm trying to create a Google Hangouts Chat chatbot (in G Suite) using Apps Script. I want to get a list of everyone in the chatroom, but this isn't directly supported in Apps Scripts yet, so I'm using the rest API. The API call list seems straightforward:
The command is
GET https://chat.googleapis.com/v1/{parent=spaces/*}/members
I've created a service account for authorization and then used
var endpoint = 'https://chat.googleapis.com/v1/{parent="spaces/pQkgxxxxxxx"}/members'
var options = {
method: "GET",
contentType : "application/json" ,
muteHttpExceptions : true,
headers: {
"Authorization": "Bearer " + goa.getToken(),
}
};
var response = UrlFetchApp.fetch(endpoint, options)`
To which I get
Invalid argument: https://chat.googleapis.com/v1/{parent="spaces/pQkgxxxxxxxx"}/members
I've tried encoding the parent parameter, but the error persists. Any ideas?
Per official documentation on the page you linked, the expected format of the path parameter parent is of the form spaces/*. The example value given is spaces/AAAAMpdlehY
In other words, you are not expected to write the {parents= and } bits, even though the template URL
GET https://chat.googleapis.com/v1/{parent=spaces/*}/members
has them. This template url format is explained in-depth on the Google API HTTP annotation website.
In your example, the correct URI to GET is https://chat.googleapis.com/v1/spaces/pQkgxxxxxxx/members
You should also consider that it may take multiple calls to resolve all members of the space pQkgxxxxxxx, by checking for a nextPageToken in the response (and passing that as the URL parameter pageToken in the next call).
You should also consider that the MemberShip returned by this query may include members with various states of membership.

weird file listing response differences between v2 and v3

I am using the google-drive-sdk with our company-made device. We upload pictures made by our device to google drive. After that I try to list the files with a GET request to https://www.googleapis.com/drive/v2/files to get thumbnailLink and webContentLink. Everything is working fine except that when I switch to v3 I don't get the response I should. The documentation says I should get a metadata response like https://developers.google.com/drive/v3/reference/files
but I only get: id, kind, name and mimeType. What am I doing wrong?
As stated in Migrate to Google Drive API v3 documentation, there are changes on how fields were returned.
Full resources are no longer returned by default. You need to use the fields query parameter to request specific fields to be returned. If left unspecified only a subset of commonly used fields are returned.
You can see examples on Github. This SO question might also help.
In v3 they made all the queries parametric. So you can query passing some parameter like
var request = gapi.client.drive.files.list({
'pageSize': 10,
'fields': 'files,kind,nextPageToken'
});
This block of code will return you all the information of every file just like v2.
If you are sending a get request then for fetching all the information you can try GET https://www.googleapis.com/drive/v3/files?fields=files%2Ckind%2CnextPageToken&key={YOUR_API_KEY}
Suppose you need ownsers and permissions only then set
var request = gapi.client.drive.files.list({
'pageSize': 10,
'fields':'files(owners,permissions),kind,nextPageToken'
});
For GET request use GET https://www.googleapis.com/drive/v3/files?fields=files(owners%2Cpermissions)%2Ckind%2CnextPageToken&key={YOUR_API_KEY}
for reference you can use Google Developers Documentation for fetching File list

Angular JSONP request

I'm trying to get a jsonp response from an api call api.brewerydb.com. However, it's not wrapping the json with a function on its call back. Here is my code:
app.factory('beer', ['$http',function($http){
var url = "http://api.brewerydb.com/v2/beers?key=MYKEY&application/json&name=oberon&callback=JSON_CALLBACK";
$http.jsonp(url)
.success(function(data){
return data;
});
}]);
It is returning json data, however I get a syntax error at a file whose name is the url I passed and it contains the json data.
I discovered that the api does not support jsonp which is why this isn't working out for me
Your url may be incorrect: '../application/json..' is for an optional HTTP_ACCEPT header per their api docs here: breweryDB , so remove it from the var url string if its not needed.
Per their docs, the default return type is JSON, so no need to pass an extra parameter if its not needed.
Try this instead (for the endpoint /Beers) per their endpoint doc :
var url = "http://api.brewerydb.com/v2/beers?key=MYKEY&name=oberon&callback=JSON_CALLBACK";
Go get them beers!
EDIT: code is here: http://jsfiddle.net/r47y3mq3/1/ copy/paste to your local dev environment and use Safari. Using Chrome results in an Access-Control-Allow-Origin header concern as discussed here: access-control
I was having some similar issues. You have name=oberon which is a brewery, but you are searching for beers in your url.
If you tried:
var url = "http://api.brewerydb.com/v2/breweries?key=MYKEY&application/json&name=oberon&callback=JSON_CALLBACK";
...you'd get an array of all the beers in the Oberon brewery.

How to update Google Drive file using byte range

I'm trying to understand how the Google API works server side in order to allow me to implement my own type of resumable upload. I understand that I can use the MediaFileUpload or MediaInMemoryUpload mechanism, but I am looking for something much more raw. For example, I want to deliberately upload 1k from a file, then later on (like days later), append another 1k of the file. Obviously not real figures here, but hopefully you get the idea. Well here is where I am with the code:
headers = {
'range': 'bytes=%d-%d' % (
offset,
offset + len(data)
)
}
body = {
'title': "MyFile.bin",
'description': "",
'modifiedDate': datetime.datetime.now().isoformat(),
'mimeType': 'application/octet-stream',
'parents': [{ 'id': parentId }]
}
res = http.request(
url, method="PUT", body=body, headers=headers
).execute()
So as you can see, it is clear where you specify the parameters for the file (file attributes) and the header specification for the request. But where do you specify the actual data stream to be uploaded in that request? Is it the case that I can just specify a media_body in the request?
You need to implement a multipart HTTP request which is explained on https://developers.google.com/drive/manage-uploads#multipart
I'd recommend you to use our JS client library and use the existing implementation on the API reference right under the JavaScript tab.
It is not possible and is not formally on Google's roadmap to introduce this functionality. The only way to append to a file is to update the entire file again from scratch.