I'm using the latest Google PHP Client library. How can I send the etag with this library?
I've already tried something like this:
$opt_params = array(
'etag' => 'F9iA7pnxqNgrkOutjQAa9F2k8HY/mOihMVEDLCvdSVCzwDmYHpSV');
$response = $youtube->channels->listChannels('snippet', array('id' => $channel_id), $opt_params);
Thanks!
The Google API PHP Client does not have native support for etags. That said, you can still alter the curl request and apply an etag as a header.
Unfortunately
Google_Http_REST
throws an exception when it receives a304 Not Modified
header so you'll need to handle those seperately in acatch
-block.This is the resulting PHP-code (note, this is for version 1 of the Google API PHP Client):
This post is a little long (if not too long). If you just need the code scroll down and skip my discussions. Please proceed as you wish.
Background
I don't know if somebody has figured out a solution for this one. Coded Monkey's answer is a start. The problem is that the solution he presented assumes that the API makes request using only a developer key/api key and not an oauth access key. If you will try his code using an developer key you will get the following:
A developer key is not enough to retrieve a user's youtube data and a developer key does not grant access to any account information. That includes youtube data. To access youtube data, one must use an oauth access key (read here: api keys)
Notice that the developer key becomes part of the query string. On the other hand when you use an oauth key, the key becomes a request header:
However if you try to use an oauth key you will still get the same error as above. This is quite frustrating. And I guess that is why Coded Monkey's answer did not get an upvote. To understand why, one must understand how the google client send requests.
How the Google PHP client works
My explanation on how the google client work behind the scene is not complete and is only based on what I learned from my experience in figuring out how to solve this problem.
The google client, which I'll call
$client
, uses aGoogle_IO_Abstract
class instance, I'll call$io
, to send requests. One can get the current$io
instance and change it using the$client->setIo()
and$client->getIo()
methods.Google_IO_Abstract
is an abstract class. One of its concrete subclass available in the PHP Google API lib isGoogle_IO_Curl
. As its name suggests the class usescurl
.From this point forward I shall assume that
$io
is aGoogle_IO_Curl
instance. The following (from Code Mokey's solution):will add an If-None-Match HTTP header to curl's header option. The actual adding of header happens only when
$io->executeRequest($request)
is called.$request
is the request$client
needs to send.Setting curl's header is done via
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers)
, where$curl
is a curl instance and$headers
is an array of headers.If you will read
executeRequest
implementation. You will see that most parts are for setting curl's options. One important part is the gathering of http headers from$request
into an array called$curlHeaders
as shown below (this is fromGoogle_IO_Curl
source code). TheAuthorization
header is also added here.Notice that after gathering the headers,
curl_setopt()
is called to set curl's header options. Now comes the problem, after these lines of code comes the part where additional options are set. Options that are set using thesetOptions()
method, which means there will be another call forcurl_setopt($curl, CURLOPT_HTTPHEADER, $headers)
but this time $headers only contain the If-None-Match header. This second call will replace all previous headers. Voila! TheAuthorization
header is gone. I am not sure if somebody has reported this yet. I am not sure if this is intentional. But this is really frustrating for beginners like me.Anyway, I came up with a quick solution.
My Solution
I will stop my discussion here and instead give you the code (Google_IO_Curl_Mod.php):
To use this just do the following:
Take note that the pair of double quotes is part of the etag.
If you check the documentation for channels.list you will notice that etag is not one of the optional parameters.
So you cant send etag to list channels via the api its not a limitation of the client library.