I just set up Google Drive API Change Notifications, specifying the folderId
of a certain shared folder that I have on My Drives. It sends notifications if I change the folder name, but doesn't send notifications if I add files.
I set up the channel successfully, as upon issuing these PHP commands
$client = new Google_Client();
$client->setApplicationName('Some Name');
$client->setAuthConfig( __DIR__ . '/service_account.json');
$client->setScopes(Google_Service_Drive::DRIVE);
$client->fetchAccessTokenWithAssertion();
$token = $client->getAccessToken();
$service = new Google\Service\Drive($client);
$httpclient = new \GuzzleHttp\Client();
$folderid = $someid;
$body = [
'kind' => "api#channel",
'id' => uniqid(),
'type' => 'web_hook',
'resourceId' => $folderid,
'resourceUri' => 'https://www.googleapis.com/drive/v3/files/'.$folderid,
'address' => 'myendpoint'
];
$apiendpoint = 'https://www.googleapis.com/drive/v3/files/' . $folderid . '/watch';
$result = $httpclient->post($apiendpoint, [
'headers' => ['Content-Type' => 'application/json', 'Authorization' => "Bearer {$token['access_token']}"],
'body' => json_encode($body),
"http_errors" => false]);
I see a successful return, and my channel immediately sends a sync
message to my endpoint, where I have this
function myendpoint (WP_REST_Request $request) {
$headers= getallheaders();
write_log('in google drive webhook with headers '.print_r($headers, true));
$body = $request->get_body();
write_log('in google drive webhook with body '.print_r($body, true));
global $wpdb;
return http_response_code(200);
}
Via my logging, I see
[07-Nov-2021 12:52:35 UTC] in google drive webhook with headers Array
(
[Host] => courses-test.com
[User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
[Content-Length] => 0
[Accept] => */*
[Accept-Encoding] => gzip, deflate, br
[X-Forwarded-For] => 66.102.8.121
[X-Forwarded-Proto] => https
[X-Goog-Channel-Expiration] => Sun, 07 Nov 2021 13:51:26 GMT
[X-Goog-Channel-Id] => 6187cbc82a08e
[X-Goog-Message-Number] => 1
[X-Goog-Resource-Id] => resid
[X-Goog-Resource-State] => sync
[X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json
[X-Original-Host] => mydomain
)
I read here
https://developers.google.com/drive/api/v3/push
where it says
"To indicate success, you can return any of the following status codes: 200, 201, 202, 204, or 102."
and hence I am returning return http_response_code(200);
and also read here
https://developers.google.com/drive/api/v3/reference/files/watch
and I don't see anything obvious going on here.
Here
there is this remark
"Avoid unnecessary retry requests by ensuring that your application is well-designed and responds promptly to notification messages (within seconds)."
Now, when I first set up the channel, my endpoint returns right away, so that would seem to negate the above point.
Also, after I get channel set up, I also run these lines
$optParams = array(
'pageSize' => 10,
'fields' => 'nextPageToken, files(id, name)'
);
$results = $service->files->listFiles($optParams);
and indeed see a listing of files.
So I truly at a loss. When I go into the folder, whose folderId
I specified to set up the watch channel, and add a file, or edit a file, I don't receive any notifications. The folder in question is shared, but as I understand, sharing only becomes an issue when dealing with shared drives, which is not my case.
And I read here,
https://developers.google.com/drive/api/v3/push#understanding-drive-api-notification-events
that watching for files being added should indeed work on a file watch, when the file is a folder, since add
is one of the events for a resource, and it applies to Files
.
**Update:
Ok, I seem to have things working, but not based on an add
event. The only thing I changed, is that instead of using Guzzle to make the POST, as I show above, I use this
$channel->setId(uniqid());
$channel->setAddress($body['address']);
$channel->setType('web_hook');
$test = $service->files->watch($folderid, $channel);
Maybe adding some of those extra params in the $body
like kind
, resourceId
, was messing things up when I was using POST via Guzzle. Or now that I know resourceId
is not same as folderid
, maybe that threw a flag on google's end so that a limited number of notifications were being sent. In any case, just using id
', address
and type
seems to be the way to go, which I think is in the Google Drive Push docs. Just that in those docs, also mention of adding those other params in the request, like 'resourceId'. I suspect if I redo using Guzzle, but specify correct resourceId
, or just leave it out and use id
', address
and type
, that it would work.
So now, I get this sort of header in my endpoint when I add a file:
(
[Host] => courses-test.com
[User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
[Content-Length] => 0
[Accept] => */*
[Accept-Encoding] => gzip, deflate, br
[X-Forwarded-For] => someip
[X-Forwarded-Proto] => https
[X-Goog-Changed] => children
[X-Goog-Channel-Expiration] => Mon, 08 Nov 2021 09:46:10 GMT
[X-Goog-Channel-Id] => chanid
[X-Goog-Message-Number] => num
[X-Goog-Resource-Id] => someid
[X-Goog-Resource-State] => update
[X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json
[X-Original-Host] => mydomain
)
So I can detect [X-Goog-Changed]
as being children
and just keep track of my current uploaded files and see what the new file is. Or maybe using the fields
query string somehow I can directly get the new file id?
Still seems odd that getting info about a new file is such a pain. Maybe it is easier in Google Cloud API and Google wants more people signing up for Cloud. In fact that add
event only seems to apply to Cloud buckets
.