我讓 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
try {
$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
try {
$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 將會默默地跳過格式錯誤的資料類型,並產生一個無效的簽章基底字串(不包含 POST 參數,如 RFC 中所定義)。
您應該針對任何您發現接受這種虛假簽章以通過驗證的 REST API 提交一個嚴重錯誤報告。
我正在使用這個與 Woocommerce REST API 溝通,並且在弄清楚 $extra_parameters 應該是什麼樣子(WC REST API 需要的類型,除了 OAUTH_AUTH_TYPE_URI 之外)方面遇到了很多麻煩。
我餵給它的多維陣列導致 PHP 崩潰,所以如果您遇到我的情況,請不要這樣做。
最終解決的方法是我查看了 OAuth 原始碼,並注意到 $extra_parameters 也可以是一個字串,它以 json 編碼 (json_encode) 解決了我所有的問題,因為 WC 接受了它。
如果服務提供商的網路伺服器設定為使用 HTTP 協定 (HTTP 1.1) 的 Keep-Alive 擴充功能,則服務提供商的回應時間可能會大幅延遲。預設情況下,Apache 設定為使用 Keep-Alive 5 秒。這是回應返回給用戶端之前的延遲時間。如果您遇到這種結果延遲的問題,可以在呼叫 $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;
?>
如果您有修改服務提供商程式碼的可能性,例如您自己是服務提供商,或者您可以與開發人員溝通並要求他們針對您的請求發送此標頭,則此方法可以奏效。