我正在使用最新的Google PHP Client library。如何将etag与此库一起发送?
我已经尝试过这样的事情:
$opt_params = array(
'etag' => 'F9iA7pnxqNgrkOutjQAa9F2k8HY/mOihMVEDLCvdSVCzwDmYHpSV');
$response = $youtube->channels->listChannels('snippet', array('id' => $channel_id), $opt_params);
谢谢!
答案 0 :(得分:1)
Google API PHP客户端没有etags的原生支持。也就是说,您仍然可以更改curl请求并将etag应用为标题。
不幸的是,Google_Http_REST
在收到304 Not Modified
标题时会引发异常,因此您需要在catch
- 块中单独处理这些异常。
这是生成的PHP代码(注意,这是针对Google API PHP客户端的第1版):
class EmptyResponse { }
$DEVELOPER_KEY = '';
$client = new Google_Client();
$client->setDeveloperKey($DEVELOPER_KEY);
$youtube = new Google_Service_YouTube($client);
// Do some logic, catch some resources
// ..
// Set the "If-None-Match" header for the etag
// This assumes the Google API is using CURL
$client->getIo()->setOptions(array(
CURLOPT_HTTPHEADER => array('If-None-Match: "4FSIjSQU83ZJMYAO0IqRYMvZX98/OPaxOhv3eeKc9owSnDQugGfL8ss"'),
));
try {
$response = $youtube->playlists->listPlaylists('snippet', array(
'id' => 'PLOIvOnfHWjIkiz6fd5KYUXJY6ZpHRqPfW',
));
}
catch (Google_Service_Exception $e) {
if (304 == $e->getCode()) {
// If the error code is 304 (Not Modified) return an empty response
$response = new EmptyResponse;
}
else {
// The request was unsuccesful
$response = null;
}
}
// After the request set the headers back to default
$client->getIo()->setOptions(array(
CURLOPT_HTTPHEADER => array(),
));
var_dump($response);
// Catch some more resources
// ...
答案 1 :(得分:1)
这篇文章有点长(如果不是太长)。如果您只需要向下滚动代码并跳过我的讨论。请按照您的意愿继续。
我不知道是否有人为此找到了解决方案。编码猴子的答案是一个开始。问题是他提出的解决方案假设API只使用开发人员密钥 / api密钥而不是 oauth访问密钥来发出请求。如果您将使用开发人员密钥尝试他的代码,您将获得以下内容:
调用GET时出错 https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id%2Csnippet%2Cstatus&mine=true&maxResults=50&key= {developer key here} : (401)需要登录
开发人员密钥不足以检索用户的YouTube数据,而开发人员密钥不授予对任何帐户信息的访问权。这包括youtube数据。要访问youtube数据,必须使用oauth访问密钥(请在此处阅读:api keys)
请注意,开发人员密钥成为查询字符串的一部分。另一方面,当您使用oauth密钥时,密钥将成为请求标头:
授权:持票人 {oauth key here}
但是,如果您尝试使用oauth键,您仍会得到与上述相同的错误。 这非常令人沮丧。而且我猜这就是为什么Coded Monkey的答案没有获得赞成。要了解原因,必须了解Google客户端如何发送请求。
我对谷歌客户端如何在幕后工作的解释并不完整,只是基于我从如何解决这个问题的经验中学到的东西。
我称之为$client
的Google客户端使用Google_IO_Abstract
类实例,我将调用$io
来发送请求。可以使用$io
和$client->setIo()
方法获取当前$client->getIo()
实例并进行更改。 Google_IO_Abstract
是一个抽象类。 PHP Google API库中提供的一个具体子类是Google_IO_Curl
。顾名思义,该课程使用curl
。
从这一点开始,我将假设$io
是Google_IO_Curl
个实例。以下(来自Code Mokey'解决方案):
$client->getIo()->setOptions(array(
CURLOPT_HTTPHEADER => array('If-None-Match: "4FSIjSQU83ZJMYAO0IqRYMvZX98/OPaxOhv3eeKc9owSnDQugGfL8ss"'),
));
会将 If-None-Match HTTP标头添加到curl的标头选项中。只有在调用$io->executeRequest($request)
时才会实际添加标头。 $request
是$client
需要发送的请求。
设置curl的标头是通过curl_setopt($curl, CURLOPT_HTTPHEADER, $headers)
完成的,其中$curl
是curl实例,$headers
是标头数组。
如果您将阅读executeRequest
实施。您将看到大多数部件都用于设置卷曲选项。一个重要的部分是将$request
中的http标头收集到名为$curlHeaders
的数组中,如下所示(这来自Google_IO_Curl
源代码)。此处还添加了Authorization
标题。
$requestHeaders = $request->getRequestHeaders();
if ($requestHeaders && is_array($requestHeaders)) {
$curlHeaders = array();
foreach ($requestHeaders as $k => $v) {
$curlHeaders[] = "$k: $v";
}
curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeaders);
}
请注意,收集标题后,会调用curl_setopt()
来设置curl的标题选项。现在出现问题,在这些代码行出现后,设置了其他选项的部分。使用setOptions()
方法设置的选项,这意味着将会有另一个curl_setopt($curl, CURLOPT_HTTPHEADER, $headers)
调用,但这次$ headers只包含If-None-Match标头。 第二次调用将替换所有以前的标题。瞧! Authorization
标题已消失。我不确定是否有人报告了此事。我不确定这是否是故意的。 但对于像我这样的初学者来说,这真是令人沮丧。
无论如何,我提出了一个快速的解决方案。
我将在此停止讨论,而是为您提供代码( Google_IO_Curl_Mod.php ):
<?php
/**
* Wrapper class for Google_IO_Curl.
*
* This class fixes issues involving request headers added using setOptions()
*
* @author Russel Villacarlos<cvsurussel_AT_gmail.com>
*/
if (!class_exists('Google_Client')) {
require_once 'Google/autoload.php';
}
class Google_IO_Curl_Mod extends Google_IO_Curl
{
//Google_IO_Curl instance
private $io;
//Array for additional headers added using setOptions()
private $headers;
public function __construct(Google_IO_Curl $io)
{
$this->io = $io;
$this->headers=[];
}
/**
* Execute an HTTP Request
*
* @param Google_Http_Request $request the http request to be executed
* @return array containing response headers, body, and http code
* @throws Google_IO_Exception on curl or IO error
*/
public function executeRequest(Google_Http_Request $request)
{
foreach ($this->headers as $value) {
if(is_string($value) && strpos($value,":")!==false){
$header = split(":\s*",$value);
$request->setRequestHeaders(array($header[0]=>$header[1]));
}
}
$result = $this->io->executeRequest($request);
return $result;
}
/**
* Set options that update the transport implementation's behavior.
* @param $options
*/
public function setOptions($options)
{
if($options){
if(array_key_exists(CURLOPT_HTTPHEADER, $options)){
$this->headers= array_merge($this->headers, $options[CURLOPT_HTTPHEADER]);
unset($options[CURLOPT_HTTPHEADER]);
}
$this->io->setOptions($options);
}
}
/**
* Set the maximum request time in seconds.
* @param $timeout in seconds
*/
public function setTimeout($timeout)
{
$this->io->setTimeout($timeout);
}
/**
* Get the maximum request time in seconds.
* @return timeout in seconds
*/
public function getTimeout()
{
return $this->io->getTimeout();
}
/**
* Test for the presence of a cURL header processing bug
*
* {@inheritDoc}
*
* @return boolean
*/
protected function needsQuirk()
{
return $this->io->needsQuirk();
}
}
要使用此功能,请执行以下操作:
$client = new Google_Client();
//codes for setting the oauth credential appears here
$io = new Google_IO_Curl_Mod(new Google_IO_Curl($client));
$client->setIo($io);
$client->getIo()->setOptions(array(
CURLOPT_HTTPHEADER =>
array('If-None-Match: "NO6QTeg0-3ShswIeqLchQ_mzWJs/wtg8du-olFPZ73k6UW7Jk5JcwpQ"'),
));
//codes for calling youtube api or any google api goes here
请注意,这对双引号是etag的一部分。
答案 2 :(得分:0)
如果您查看channels.list的文档,您会注意到etag不是可选参数之一。
所以你不能通过api将etag发送到列表频道,而不是客户端库的限制。