問題描述
我想透過 HTTP API 過濾任何 HTTP 請求 URI 。
用例:
-
WordPress 更新檢查到 http://api.wordpress.org/core/version-check/1.6/,但 https://api.wordpress.org/core/version-check/1.6/也工作,我想永遠使用這個。
-
新的 WordPress 檔案來自 http://wordpress.org/wordpress-3.4.2.zip,但 https://wordpress.org/wordpress-3.4.2.zip 也可以使用。
-
有時我想除錯請求並將這些臨時重定向到本地伺服器上的自定義域。
-
一些外掛向其他伺服器發出請求,當外部伺服器關閉時,我想要替換這些請求。
更新請求是現在最重要的,因為仍然存在未固定的 bug 16778(more information),並且 HTTPS 請求降低了 Man-in-the 中間攻擊的風險。
我有 searched thoroughly,我已經研究了核心程式碼… 但最終像 Nacin 兩年前一樣:
I thought for sure you could filter the URL of an HTTP request, but now I can’t find one.
我錯過了什麼?我有:)
最佳解決方案
不到一個答案,但只是從我的經驗直接列出的事情 – 也許你忽略了一些東西。
除錯請求& 其結果
沒有 diggin’ 更深入到更新過程,但 WP HTTP API 使用 WP_HTTP
類。它還提供了一個好東西:除錯鉤。
do_action( 'http_api_debug', $response, 'response', $class, $args, $url );
哪裡 $response
也可以是一個 WP_Error
物件,可能會告訴你更多。
注意:從一個簡短的測試,這個過濾器似乎只是 (由於某種原因) 工作,如果你把它放在你實際執行請求的地方。所以也許你需要從一個下面的過濾器的回撥中呼叫它。
WP_HTTP
類引數
Classes 引數本身是可過濾的,但是 afa 有些可以透過方法內部的方式重新設定為 WP 假定需要的。
apply_filters( 'http_request_args', $r, $url );
其中一個引數是 ssl_verify
,預設情況下為 true(但是對於我來說,當從 – 例如 GitHub 更新時會導致大量問題) 。編輯:除錯測試請求後,我發現另一個引數設定為驗證 SSL 是否設定為 true
。它被稱為 sslverify
(不分離下劃線) 。不知道這是進入遊戲,如果它實際上在使用或放棄,如果你有機會影響其價值。我發現它使用'http_api_debug'
過濾器。
完全定製
您也可以”simply” 覆蓋整個內部部件,並使用自定義設定。有一個過濾器。
apply_filters( 'pre_http_request', false, $r, $url );
第一個 arg 需要設定為 true 。比起 $r
中的引數和 parse_url( $url );
的結果進行互動。
Proxy
另一件可能工作的事情可能是透過自定義代理執行所有內容。這需要您的 wp-config.php
中的一些設定。我從來沒有嘗試過,但是我經常碰到這些常數,並總結了一些應該工作的例子,並且包括一些意見,以防我有一天需要它。您必須將 WP_PROXY_HOST
和 WP_PROXY_PORT
定義為最小值。設定。否則沒有任何工作,它只會繞過您的代理。
# HTTP Proxies
# Used for e.g. in Intranets
# Fixes Feeds as well
# Defines the proxy adresse.
define( 'WP_PROXY_HOST', '127.0.84.1' );
# Defines the proxy port.
define( 'WP_PROXY_PORT', '8080' );
# Defines the proxy username.
define( 'WP_PROXY_USERNAME', 'my_user_name' );
# Defines the proxy password.
define( 'WP_PROXY_PASSWORD', 'my_password' );
# Allows you to define some adresses which
# shouldn't be passed through a proxy.
define( 'WP_PROXY_BYPASS_HOSTS', 'localhost, www.example.com' );
EDIT
WP_HTTP
類通常作為基類 (將針對不同的場景進行擴充套件) 。擴充套件的 WP_HTTP_*
類是 Fsockopen
,Streams
,Curl
,Proxy
,Cookie
,Encoding
。如果您將回撥掛接到'http_api_debug'
-action,則第三個引數將告訴您哪個類用於您的請求。
在 WP_HTTP_curl
類中,可以找到 request()
方法。此方法提供兩個過濾器來攔截 SSL 行為:一個用於本地請求'https_local_ssl_verify'
,一個用於遠端請求'https_ssl_verify'
。 WP 可能將 local
定義為 localhost
,並從 get_option( 'siteurl' );
返回。
所以我會做的是在你執行該請求之前嘗試以下的許可權 (或者從一個掛鉤到最接近請求的回撥中)
add_filter( 'https_ssl_verify', '__return_true' );
# Local requests should be checked with something like
# 'localhost' === $_SERVER['HTTP_HOST'] or similar
# add_filter( 'https_local_ssl_verify', '__return_true' );
Sidenote:在大多數情況下,WP_HTTP_curl
將用於處理代理。
次佳解決方案
基於 @ kaiser 的有用答案,我寫了一些似乎工作得很好的程式碼。這就是為什麼我把它標記為 「答案」 的原因。
讓我解釋一下我的解決方案
邏輯
當透過 API 傳送的請求透過 WP_Http::request()
執行。這是… 的方法
@todo Refactor this code.
… 在其標題我不能同意。
現在有一些過濾器。我決定濫用 pre_http_request
作為我的需要:
add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );
我們在這裡得到三個引數:false, $r, $url
。
-
false
是apply_filters()
的預期回報值。如果我們發回任何東西,WordPress 立即停止,原始請求將不會被髮送。 -
$r
是該請求的一組引數。我們必須在一分鐘內改變這些。 -
$url
是 – 驚喜! – 網址。
所以在我們的回撥 t5_update_wp_per_https()
中,我們看看 URL,如果是我們想要過濾的 URL,我們不用說 「no」(false
) 對 WordPress 說 NO 。
旁註:遵循以下可以透過以下方式阻止所有 HTTP 請求:add_filter( 'pre_http_request', '__return_true' );
我們用更好的 URL 和稍微調整的引數 ($r
,更名為 $args
可讀性) 來觸發我們自己的請求。
程式碼
請閱讀線上評論,他們很重要。
<?php
/**
* Plugin Name: T5 Update WP per HTTPS
* Description: Forces update checks and downloads for WP to use HTTPS.
* Plugin URI: http://wordpress.stackexchange.com/questions/72529/filter-any-http-request-uri
* Version: 2012.11.14
* Author: Thomas Scholz
* Author URI: http://toscho.de
* Licence: MIT
* License URI: http://opensource.org/licenses/MIT
*/
add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );
/**
* Force HTTPS requests for update checks and new WP version downloads.
*
* @wp-hook pre_http_request
* @param bool $false
* @param array $args
* @param string $url
* @return FALSE|array|object FALSE if everything is okay, an array of request
* results or an WP_Error instance.
*/
function t5_update_wp_per_https( $false, $args, $url )
{
// Split the URL into useful parts.
$url_data = parse_url( $url );
// It is already HTTPS.
if ( 'https' === strtolower( $url_data['scheme'] ) )
return FALSE;
// Not our host.
if ( FALSE === stripos( $url_data['host'], 'wordpress.org' ) )
return FALSE;
// Make that an HTTPS request.
$new_url = substr_replace( $url, 'https', 0, 4 );
// WP_Http cannot verify the wordpress.org certificate.
$args['sslverify'] = FALSE;
// It is slow. We wait at least 30 seconds.
30 > $args['timeout'] and $args['timeout'] = 30;
// Get an instance of WP_Http.
$http = _wp_http_get_object();
// Get the result.
$result = $http->request( $new_url, $args );
/* prepend this line with a '#' to debug like a boss.
print '<pre>'
. htmlspecialchars( print_r( $result, TRUE ), ENT_QUOTES, 'utf-8', FALSE )
. '</pre>';
die();
/**/
return $result;
}
測試
沒有這個外掛 WordPress 使用:
-
http://api.wordpress.org/core/version-check/1.6/
進行更新檢查, -
http://wordpress.org/wordpress-3.4.2.zip
下載新檔案。
我測試了兩個本地安裝,單個站點和 multi-site 設定在 Win 7. 要強制更新,我將 wp-includes/version.php
中的 $wp_version
設定為 1
和 TwentyEleven 版本到 1.3
。
要觀看網路流量,我使用 Wireshark:它是免費的,它執行在 Windows 和 Linux 上,它提供了一些令人印象深刻的過濾工具。
看 HTTPS 是有點困難:你看到加密的資料… 這畢竟是一個想法。要檢視我的外掛是否應該做什麼,我先看看未加密的流量,並注意用於連線到 wordpress.org 的 IP 地址。那是 72.233.56.138
,有時是 72.233.56.139
。不奇怪,有一個負載平衡器,可能還有很多其他工具,所以我們不能依賴一個 IP 地址。
然後我將 ip.addr == 72.233.56.138
鍵入過濾器掩碼,啟用外掛,進入 wp-admin/update-core.php
並觀看 Wireshark 的流量。綠線是純文字的要求 – 正是我們不想要的。紅線和黑線是成功的標誌。
更新檢查很好:它找到了 「newer」 版本。主題和核心的實際更新也很好。正是我需要的
而且,如果有一個簡單的過濾器,URL 可能會更容易。
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。