我在尝试使用 fetch() 发送 POST 请求时遇到了麻烦,远程服务器(在本例中为 Twitter)抱怨我他们的“资源仅支持 POST”。结果发现是 OAuth 1.1 中的一个已知错误,降级到 1.0 就解决了这个问题。
不要像我一样在这上面浪费太多时间 :-)
(PECL OAuth >= 0.99.1)
OAuth::fetch — 获取受 OAuth 保护的资源
$protected_resource_url
,$extra_parameters
= ?,$http_method
= ?,$http_headers
= ?获取资源。
protected_resource_url
受 OAuth 保护的资源的 URL。
extra_parameters
要与资源请求一起发送的其他参数。
http_method
OAUTH_HTTP_METHOD_*
OAUTH 常量之一,包括 GET、POST、PUT、HEAD 或 DELETE。
HEAD (OAUTH_HTTP_METHOD_HEAD
) 可用于在请求之前发现信息(如果 OAuth 凭据位于 Authorization
标头中)。
http_headers
HTTP 客户端标头(如 User-Agent、Accept 等)
版本 | 描述 |
---|---|
PECL oauth 1.0.0 | 以前在失败时返回 null ,而不是 false 。 |
PECL oauth 0.99.5 | 添加了 http_method 参数 |
PECL oauth 0.99.8 | 添加了 http_headers 参数 |
示例 #1 OAuth::fetch() 示例
<?php
尝试 {
$oauth = new OAuth("consumer_key","consumer_secret",OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_AUTHORIZATION);
$oauth->setToken("access_token","access_token_secret");
$oauth->fetch("http://photos.example.net/photo?file=vacation.jpg");
$response_info = $oauth->getLastResponseInfo();
header("Content-Type: {$response_info["content_type"]}");
echo $oauth->getLastResponse();
} catch(OAuthException $E) {
echo "捕获到异常!\n";
echo "响应:". $E->lastResponse . "\n";
}
?>
我在尝试使用 fetch() 发送 POST 请求时遇到了麻烦,远程服务器(在本例中为 Twitter)抱怨我他们的“资源仅支持 POST”。结果发现是 OAuth 1.1 中的一个已知错误,降级到 1.0 就解决了这个问题。
不要像我一样在这上面浪费太多时间 :-)
如果 $extra_parameters 不是数组,则必须指定 Content-Type 标头,否则将收到 HTTP 401 错误。示例
<?php
$oauth->fetch(ENDPOINT, '{"action": "get_user_info"}', OAUTH_HTTP_METHOD_PUT, array('Content-Type' => 'application/json'));
?>
如果返回的 http 状态代码在 4xx 或 5xx 范围内,则 fetch() 方法将抛出 OAuthException
<?php
// 使用错误的登录详细信息查询 Twitter
尝试 {
$oauth->fetch('https://api.twitter.com/1.1/favorites/list.json');
}
catch(Exception $e) {
echo $e->getCode(); // 401
// OAuth 类生成的错误消息
echo $e->getMessage(); // 无效身份验证/错误请求(收到 401,预期 HTTP/1.1 20X 或重定向)
// Twitter 返回的错误消息
echo $e->lastResponse; // {"errors":[{"message":"Could not authenticate you","code":32}]}
}
确保您的 $extra_parameters 是一个数组。
如果不是,则 OAuth 将静默地跳过格式错误的数据类型,并生成一个无效的签名基础字符串(不包含 RFC 中定义的 POST 参数)。
您应该对在野外发现的任何接受这种虚假签名以通过身份验证的 REST API 提交严重错误报告。
因此我正在使用它与 Woocommerce REST API 通信,并且在尝试弄清楚 $extra_parameters 究竟应该是什么样子时遇到了很多麻烦(WC REST API 预期什么,除了类型为 OAUTH_AUTH_TYPE_URI 之外)。
我提供的多维数组导致 PHP 崩溃,因此如果您遇到这种情况,请不要这样做。
最终解决问题的方法是查看 OAuth 源代码,并注意到 $extra_parameters 也可以是字符串,该字符串以 json 编码 (json_encode),解决了我的所有问题,因为 WC 接受了它。
如果提供者的 Web 服务器配置为使用 Keep-Alive 扩展 HTTP 协议(HTTP 1.1),则提供者的响应时间可能会出现较大的延迟。默认情况下,Apache 配置为使用 5 秒的 Keep-Alive。这是响应返回给消费者的延迟时间。如果您遇到此延迟结果问题,可以在调用 $consumer->fetch()
时传入 HTTP 头。
<?php
$consumer = new OAuth("consumer_key", "consumer_secret", OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_FORM);
$consumer->fetch('http://example.com/api/', null, OAUTH_HTTP_METHOD_POST, array('Connection'=>'close'));
?>
然后提供者将在处理完成后立即发送结果,并关闭连接。不幸的是,在调用 $consumer->getRequestToken()
和 $consumer->getAccessToken()
时,没有提供传入 HTTP 头的方法,并且无法避免此延迟(如果存在),或者至少我们找不到避免它的方法。
对我们有效的解决方案是从提供者在将结果返回给消费者时发送此标头。
<?php
$result = 'oauth_callback_accepted=true&oauth_token=' . $this->urlencode($token->oauth_token) .
'&oauth_token_secret='.$this->urlencode($token->oauth_token_secret);
header('HTTP/1.1 200 OK');
header('Content-Length: '.strlen($result));
header('Content-Type: application/x-www-form-urlencoded');
header('Connection:close');
echo $result;
?>
如果您有修改提供者代码的可能性,例如您自己就是提供者,或者您可以与开发人员沟通并要求他们为您请求发送此标头,则此方法有效。