I've been working with the Google Drive API in my Java application. The goal is to have a framework for our internal AppEngine project to fill out various templates in our organization's Team Drives.
I have setup a Service Account with domain-wide permissions and have gone through the "Executing Functions using the Apps Script API" documents. I can use the Java v3 library to update a sheet to get some number information, copy the template to a new file in the Team Drive. I've written a simple AppScript function to take in the Docs File Id and a JSON string representing the token/value pairs to substitute.
Everything goes great until it's time to execute the script when I get:
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Request contains an invalid argument.",
"reason" : "badRequest"
} ],
"message" : "Request contains an invalid argument.",
"status" : "INVALID_ARGUMENT"
}
Not sure how to debug or change this error, as I don't really get any additional info. I do see the request being made in the AppScript API and project console, but don't know how to get more information.
My code to execute is as follows:
List<Object> params = Lists.newArrayList();
params.add( fileId );
params.add( json );
ExecutionRequest request = new ExecutionRequest().setFunction( "main2" )
.setParameters( params );
script().scripts().run( TEMPLATE_FILLER_SCRIPT_ID, request ).execute();
After enabling the logging to I was able to pull the entire web request. It all looks ~fine but maybe there's more here:
CONFIG: {"function":"main2","parameters":["15gXG9frqV0VrF57BjDqOe0pCHPWxVJ1ucV0Fl3zR0J4","{\"num\":\"035\",\"digital_key\":\"https://docs.google.com/document/d/15gXG9frqV0VrF57BjDqOe0pCHPWxVJ1ucV0Fl3zR0J4\",\"Title\":\"Build Control for Image Enhancement\",\"Author\":\"Evan Ruff\",\"Date\":\"05/11/18\"}"]}
May 11, 2018 4:59:41 PM com.google.api.client.http.HttpRequest execute
CONFIG: -------------- REQUEST --------------
POST https://script.googleapis.com/v1/scripts/1T7HAaK2yJ2qUf3sOAz3ZGSPRql73-DGCe79-dLgCyqbnh_LbIn5KgQ4r:run
Accept-Encoding: gzip
Authorization: Bearer *******MY TOKEN *********
User-Agent: Memo Builder/1.0 Google-API-Java-Client Google-HTTP-Java-Client/1.23.0 (gzip)
Content-Type: application/json; charset=UTF-8
Content-Encoding: gzip
Content-Length: 230
May 11, 2018 4:59:41 PM com.google.api.client.http.HttpRequest execute
CONFIG: curl -v --compressed -X POST -H 'Accept-Encoding: gzip' -H 'Authorization: Bearer ya29.c.EmW4BdRkBR2JFBoDaAw_FG8DFbNCHYoe4E3jBs9HyowMAPqM2SnNky4ffRdh0zxG2nc4ylcIlr9yUHJ-ibOJuXdJhakgTmEyC7R4xn8cdKEif7mSeaeRGV9XwYI4W3AkoRAz-sCWmw' -H 'User-Agent: Micro C-Memo Builder/1.0 Google-API-Java-Client Google-HTTP-Java-Client/1.23.0 (gzip)' -H 'Content-Type: application/json; charset=UTF-8' -H 'Content-Encoding: gzip' -d '#-' -- 'https://script.googleapis.com/v1/scripts/1T7HAaK2yJ2qUf3sOAz3ZGSPRql73-DGCe79-dLgCyqbnh_LbIn5KgQ4r:run' << $$$
May 11, 2018 4:59:41 PM com.google.api.client.util.LoggingByteArrayOutputStream close
CONFIG: Total: 299 bytes
May 11, 2018 4:59:41 PM com.google.api.client.util.LoggingByteArrayOutputStream close
CONFIG: {"function":"main2","parameters":["15gXG9frqV0VrF57BjDqOe0pCHPWxVJ1ucV0Fl3zR0J4","{\"num\":\"035\",\"digital_key\":\"https://docs.google.com/document/d/15gXG9frqV0VrF57BjDqOe0pCHPWxVJ1ucV0Fl3zR0J4\",\"Title\":\"Build Control for Image Enhancement\",\"Author\":\"Evan Ruff\",\"Date\":\"05/11/18\"}"]}
May 11, 2018 4:59:41 PM com.google.api.client.http.HttpResponse <init>
CONFIG: -------------- RESPONSE --------------
HTTP/1.1 400 Bad Request
Transfer-Encoding: chunked
X-Frame-Options: SAMEORIGIN
Alt-Svc: hq=":443"; ma=2592000; quic=51303433; quic=51303432; quic=51303431; quic=51303339; quic=51303335,quic=":443"; ma=2592000; v="43,42,41,39,35"
Cache-Control: private
Server: ESF
X-Content-Type-Options: nosniff
Content-Encoding: gzip
Vary: Referer
Vary: X-Origin
Vary: Origin
X-XSS-Protection: 1; mode=block
Date: Fri, 11 May 2018 20:59:41 GMT
Content-Type: application/json; charset=UTF-8
This seems simple enough but I'm really struggling. Any tips would be appreciated!
In case someone comes across this, Google released a Java Docs API soon after I actually got this working. The Docs API is a much nicer solution.
Related
I tried the following code for creating a repository. But it gives JSON parsing problem. What causes this?. I took this code from https://docs.github.com/en/rest/reference/repos tried in python code using requests.post method. But that too gave the same error Problem Parsing JSON. Is this bad request or the parsing problem is inside Github API.
curl -i -H "Authorization: token MYACCESSTOKENHERE" \
-d '{ \
"name": "simp", \
"auto_init": true, \
"private": true, \
"gitignore_template": "nanoc" \
}' \
https://api.github.com/user/repos
Output:
HTTP/1.1 400 Bad Request
Date: Sun, 09 Aug 2020 05:14:23 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 159
Server: GitHub.com
Status: 400 Bad Request
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4956
X-RateLimit-Reset: 1596950918
X-OAuth-Scopes: admin:gpg_key, admin:org, admin:org_hook, admin:repo_hook, gist, notifications, read:packages, repo, user, workflow, write:discussion, write:packages
X-Accepted-OAuth-Scopes: public_repo, repo
X-GitHub-Media-Type: github.v3; format=json
Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
Vary: Accept-Encoding, Accept, X-Requested-With
X-GitHub-Request-Id: B649:25C9:CDEF3A:117E0EE:5F2F862F
{
"message": "Problems parsing JSON",
"documentation_url": "https://docs.github.com/rest/reference/repos#create-a-repository-for-the-authenticated-user"
}
Could you please validate your token is authorized.
Please refer Authorizing OAuth Apps
curl -H "Authorization: token OAUTH-TOKEN" <https://<your_repo_endpoint> -I
Update using JSON formatter
"-d""{ \\
\"name\": \"simp\", \\
\"auto_init\": true, \\
\"private\": true, \\
\"gitignore_template\": \"nanoc\" \\
}""\\
The problem is with the JSON format. After I removed unwanted lines and spaces from the curl command, it worked.
curl -i -H "Authorization: token 1f003ae8eab2feea72630d6f3150b921a522a868" -d '{ "name": "simp1", "private": true}' https://api.github.com/user/repos
quite new to testing, but currently Im testing rest services...
Really like SoapUI (did some soap testing in the past), but I have problem with testing one service - it is service for creating an event - have tried it in postman(working) and in soapui(not working).
When I try to run it in SoapUI Im getting error:
Object reference not set to an instance of an object.
Here is code from postman request (getting status: 200 OK):
POST /Event.Api/v1/events HTTP/1.1
Host: 172.26.2.66
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJCT0hVU0xBViIsImZhbWlseV9uYW1lIjoiRE9LT1VQSUwiLCJQT0lEIjoiOGYyMTdiZWItZmQ3My00OThjLWFhZjktOWY0ZTk0YmRhMjIzIiwiZXhwIjoxNTE1MTUzNTg0fQ.2uB_pPXyl3wSAqonaDb5pLAwDb-BujMIU6Rdeg_73Jw
Cache-Control: no-cache
Postman-Token: 1d92a58e-c4de-f790-caca-fd983392a17e
{
"name": "Michalova událost",
"place": "AC",
"start": "2018-01-05T15:00:39.164Z",
"end": "2018-01-05T16:00:39.164Z",
"wholeDay": true,
"repeating": "NEOPAKUJE_SE",
"description": "Popis michalovy události"
}
edit: screen of soapUI request added
and here is request code from soapUI, dont undestand why, but there is not the json content I added in the post window
POST http://172.26.2.66/Event.Api/v1/events HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJCT0hVU0xBViIsImZhbWlseV9uYW1lIjoiRE9LT1VQSUwiLCJQT0lEIjoiZWJhMWVmNjMtNWUzNS00YTU3LTljNWMtNDY3ZmJhZmI5YTIyIiwiZXhwIjoxNTE1MTU4MTI3fQ.s5dNZxV6NME1G8rbYrsuv8sb1nMiB8z1GSVGHe3auVA
Content-Length: 220
Host: 172.26.2.66
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
and here is raw response from soapUI:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Server: Kestrel
X-Powered-By: ASP.NET
Date: Fri, 05 Jan 2018 11:17:25 GMT
{
"errors": [
{
"code": "COMMON_ERROR",
"description": "Object reference not set to an instance of an object."
}
]
}
Anyone can help? Thanks for your replys.
P.S:think it is something with that json content, cause when Im testing get methods, everything is fine and Im getting expected results even in the soapUI
MJ
I'm getting 403 watchDenied errors when I try to make File Watch requests in a Batch Request. Sending them normally is fine. I'm presuming that batching of File Watch requests is permitted?
Additional info: If I set an incorrect Address, I get the usually unpermitted webhook address error, and if I set a dummy file ID I get a 404, so it doesn't feel like the request I'm making is incorrect.
Example code (using the C# client library):
var request = new BatchRequest(service);
request.Queue<Channel>(service.Files.Watch(
new Channel
{
Id = [Guid being used],
Type = "web_hook",
Address = [notification endpoint],
Token = [token being used],
Expiration = DateTime.Now.AddHours(1).ToUnixTimeMilliseconds()
}, fileId)
, (content, error, i, message) =>
{
}
);
await request.ExecuteAsync();
API Request
Headers:
POST: https://www.googleapis.com/batch
User-Agent: OverDRIVE google-api-dotnet-client/1.16.0.0 (gzip)
Authorization: Bearer [token]
Content-Type: multipart/mixed; boundary="8d7a0653-4d9b-4c09-b701-9794341f882d"
Host: www.googleapis.com
Content-Length: 988
Accept-Encoding: gzip, deflate
Body:
--8d7a0653-4d9b-4c09-b701-9794341f882d
Content-Type: application/http
POST https://www.googleapis.com/drive/v2/files/[fileId]/watch
Content-Type: application/json; charset=utf-8
Content-Length: 241
{"address":"[notification endpoint]","expiration":1474036096103,"id":"938bd983-b071-4e63-8535-f20d7f39e248","token":"[token being used]","type":"web_hook"}
--8d7a0653-4d9b-4c09-b701-9794341f882d
Content-Type: application/http
POST https://www.googleapis.com/drive/v2/files/[fileId]/watch
Content-Type: application/json; charset=utf-8
Content-Length: 241
{"address":"[notification endpoint]","expiration":1474036096105,"id":"79303874-5f6c-49aa-a601-93950895ac0f","token":"[token being used]","type":"web_hook"}
--8d7a0653-4d9b-4c09-b701-9794341f882d--
Error example
{
"error": {
"errors": [
{
"domain": "push",
"reason": "watchDenied",
"message": "Watch request denied by backend"
}
],
"code": 403,
"message": "Watch request denied by backend"
}
}
Had an update from the developer support team for a ticket I submitted to them.
Unfortunately watch requests are known to largely incompatible with
Drive batch requests. Our Drive team recommended to make watch
requests separate from other requests.
I have an image saved on my AWS S3 bucket. This is my CORS configuration:
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Also, the bucket has this policy:
{
"Version": "2012-10-17",
"Id": "Policy1468082822770",
"Statement": [
{
"Sid": "Stmt1468082812651",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::criptolibertad/*"
}
]
}
This is the image: https://criptolibertad.s3.amazonaws.com/Django/0_startproject.jpeg , as you can see, it is public. I use a library called Croppie that tries to load the image into a canvas. But the canvas doesn't show the image I don't know why. The js looks like this:
croppie_div.croppie('bind', {
url: "{{ carta_magicpy.imagen_base.url }}",
points: [10,10,300,600]
});
That url attribute is just a variable rendered by Django. It looks like this when it is rendered:
<img style="opacity: 0;" src="https://criptolibertad.s3.amazonaws.com/Django/0_startproject.jpeg" crossorigin="anonymous" class="cr-image">
Notice the crossorigin attribute. I went into Croppie's source and removed that attribute. But then I get the error:
Image from origin ... has been blocked from loading by Cross-Origin Resource Sharing policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource
How can I solve this?
Seems the CORS headers are still not set correctly. This related Croppie issue #119 mentions you can check that by looking at the response headers.
It's pretty easy to inspect the headers with curl, for the image stored in your bucket:
curl -I -H "Origin: https://stackoverflow.com/questions/38365182" -H "Access-Control-Request-Method: GET" https://criptolibertad.s3.amazonaws.com/Django/0_startproject.jpeg
HTTP/1.1 200 OK
x-amz-id-2: 9AaMwS9s2Im+OV6YlzVKrDW8RnbQqFt4Ygc+pRa3XM4iDmnJqlO8DQ7EjvpT4W4GnhGc0IvoQeI=
x-amz-request-id: CD4E7C50B5186192
Date: Fri, 15 Jul 2016 07:54:52 GMT
Last-Modified: Sat, 09 Jul 2016 05:13:33 GMT
ETag: "5733f7cd0187eb3a840bbe83e2c66a9b"
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 33402
Server: AmazonS3
As opposed to the properly set up CORS headers on e.g imgur:
curl -I -H "Origin: https://stackoverflow.com/questions/38365182" -H "Access-Control-Request-Method: GET" http://i.imgur.com/HMf7XWD.jpg
HTTP/1.1 200 OK
Last-Modified: Wed, 06 Jul 2016 15:07:13 GMT
ETag: "7b01be4b9235542038f6d9793cc2c620"
Content-Type: image/jpeg
Fastly-Debug-Digest: f94b623450bb8143aff369600bf855d6332bb44c12070f02b0fc95648eac6ef3
cache-control: public, max-age=31536000
Content-Length: 2457350
Accept-Ranges: bytes
Date: Fri, 15 Jul 2016 07:55:15 GMT
Age: 277937
Connection: keep-alive
X-Served-By: cache-iad2131-IAD, cache-fra1232-FRA
X-Cache: HIT, HIT
X-Cache-Hits: 1, 1
X-Timer: S1468569315.725739,VS0,VE2
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Origin: *
Server: cat factory 1.0
As you can see the main difference is that imgur returns the headers Access-Control-Allow-Methods and Access-Control-Allow-Origin, while your S3 bucket does not.
I have followed the official Amazon documentation on the subject and applied the modified CORS configuration to my own bucket, the difference from your configuration is the AllowedHeader element, which defines the headers to allowed in response. I set my bucket to:
<AllowedHeader>*</AllowedHeader>
Here are the resulting headers on the image stored in my bucket:
curl -I -H "Origin: https://stackoverflow.com/questions/38365182" -H "Access-Control-Request-Method: GET" https://so38134984.s3.amazonaws.com/rainbow_dash.png
HTTP/1.1 200 OK
x-amz-id-2: ANxPKoL3JDsLDGerTf8gdcyRU7U4Ozg4eMYJ9ADlX/2qcBmx0dsmAbZxv2h/tFfQIXbkAs+x5iA=
x-amz-request-id: 737E30AE2F8634FC
Date: Fri, 15 Jul 2016 07:53:55 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Mon, 04 Jul 2016 20:09:19 GMT
ETag: "3ad1bb64b913c2eadab216b96034b990"
Accept-Ranges: bytes
Content-Type: image/png
Content-Length: 148647
Server: AmazonS3
I assume my image will now work properly in your Croppie script.
I have been trying to use the Google Drive API to make a Fusiontable publicly readable, and have not been able to get it to work. I am able to use the OAuth 2.0 Playground to insert public share permissions for other Google Drive documents, but for Fusiontables I get an HTTP 500 error, "Internal Error". Note that I have tried including every scope available under "Drive API v2" and "Fusion Tables API v1".
I'm aware that Google is no longer developing and supporting Fusiontables, but I'm wondering if anyone has found a workaround that allows them to get around this problem? I haven't tried legacy/deprecated versions of the API either.
Here's are the actual API request format and responses from OAuth Playground for a Fusiontable permissions insert (HTTP 500), then a Doc permissions insert (HTTP 200). The only difference between requests is the fusiontable_id or document_id in the Request URI:
Request:
POST /drive/v2/files/<fusiontable_id or document_id>/permissions HTTP/1.1
Host: www.googleapis.com
Content-length: 33
Content-type: application/json
Authorization: Bearer <access_token>
{"role":"reader","type":"anyone"}
Fusiontable Response:
HTTP/1.1 500 Internal Server Error
Content-length: 180
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
Expires: Tue, 04 Nov 2014 23:51:58 GMT
Vary: Origin,Referer,X-Origin
Server: GSE
Cache-control: private, max-age=0
Date: Tue, 04 Nov 2014 23:51:58 GMT
X-frame-options: SAMEORIGIN
Content-type: application/json; charset=UTF-8
{
"error": {
"code": 500,
"message": "Internal Error",
"errors": [
{
"domain": "global",
"message": "Internal Error",
"reason": "internalError"
}
]
}
}
Doc response:
HTTP/1.1 200 OK
Content-length: 281
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Vary: Origin,Referer,X-Origin
Server: GSE
Etag: "M4l5RvCt2StP2jOGfgyJPGdTZTc/dgFZz37LrQjIXplUkmnh3VtemzQ"
Pragma: no-cache
Cache-control: no-cache, no-store, max-age=0, must-revalidate
Date: Wed, 05 Nov 2014 15:35:56 GMT
X-frame-options: SAMEORIGIN
Content-type: application/json; charset=UTF-8
{
"kind": "drive#permission",
"etag": "\"M4l5RvCt2StP2jOGfgyJPGdTZTc/dgFZz37LrQjIXplUkmnh3VtemzQ\"",
"role": "reader",
"type": "anyone",
"id": "anyone",
"selfLink": "https://www.googleapis.com/drive/v2/files/<document_id>/permissions/anyone"
}
This appears to be due to a bug in the Drive API. I've located the internal error and have raised the issue with the engineering team. At this time there are no known workarounds.
I have a good news!
I've received an email from googletables-feedback. They says that it should be working now.
My code on Google Client JS API works fine
var setAccess = function setAccessF() {
gapi.client.request({
path : '/drive/v2/files/{fileID}/permissions',
method : 'post',
body : {
'value' : 'anyone',
'type' : 'anyone',
'role' : 'reader'
}
}).then(opt_onFulfilled, opt_onRejected);
}
function opt_onRejected(e) {
console.log(e)
}
function opt_onFulfilled(e) {
console.log(e)
}
If you'd be OK with a temporary workaround, inserting Fusion Table public share permission still works with older XML-based GData API. You can check it out here, though beware of the red banner at the top of the page saying 'The deprecation period for Version 3 of the Google Documents List API is nearly at an end. On April 20, 2015, we will discontinue service for this API.'
So if you need to workaround the problem now, that would keep you going till April and then let's hope the Drive API bug gets fixed before that...
Personally, the document I was attempting to add the permissions to had become invalid. This might also be an issue for someone else.