HTTP APIを通じて行われたHTTPリクエストURIをフィルタリングしたい。
ユースケース
まだ修正されていない bug 16778 ( more information )があり、HTTPSリクエストは中間者攻撃のリスクを低くするので、更新リクエストは今のところ最も重要なものです。
検索徹底的に 、私はコアコードを勉強しました…しかし2年前にNacinのように終わった:
私はあなたがHTTPリクエストのURLを確実にフィルタリングすることができると考えました、しかし今私はそれを見つけることができません。
私は何を取りこぼしたか?私はしましたか? :)
答えにはなりませんが、私の経験から直接引用したもののリストです。何かを見落としているかもしれません。
Digginがないと更新処理が深くなりすぎますが、WP HTTP APIはWP_HTTP
クラスを使用します。デバッグフックという素晴らしいこともあります。
do_action( 'http_api_debug', $response, 'response', $class, $args, $url );
$response
はWP_Error
オブジェクトになることもできます。
注:簡単なテストでは、このフィルターは(何らかの理由で)実際にリクエストを行っている場所に close のように配置した場合にのみ機能するようです。そのため、以下のいずれかのフィルタでコールバック内から呼び出す必要があります。
WP_HTTP
クラス引数Classesの引数自体はフィルタリング可能ですが、内部のメソッドによってWPが必要と見なしているものにリセットされることがよくあります。
apply_filters( 'http_request_args', $r, $url );
引数の1つはssl_verify
で、これはデフォルトでtrueです(しかし、私にとっては、たとえばGitHubからアップデートすると大きな問題が発生します)。 編集: テストリクエストをデバッグした後、SSLがtrue
に設定されているかどうかを検証するために設定されている別の引数を見つけました。これはsslverify
と呼ばれます(アンダースコアを区切らずに)。それが実際に使われているか放棄されているかどうか、そしてあなたがその価値に影響を与えるチャンスがあるかどうか、これがゲームのどこに入ったのか見当がつかない。 'http_api_debug'
フィルタを使って見つけました。
内部構造全体を「単純に」オーバーライドしてカスタム設定を使用することもできます。そのためのフィルタがあります。
apply_filters( 'pre_http_request', false, $r, $url );
最初の引数はtrueに設定する必要があります。あなたは$r
内の引数とparse_url( $url );
からの結果と対話することができます。
もう1つうまくいく可能性があるのは、カスタムProxyを通してすべてを実行することです。これはあなたのwp-config.php
でいくつかの設定を必要とします。これまで試したことは一度もありませんでしたが、しばらく前に定数を調べて、 should workという例をいくつかまとめて、必要に応じてコメントを含めました。 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' );
WP_HTTP
クラスは通常 base classとして機能します(さまざまなシナリオに対応するように拡張されます)。拡張するWP_HTTP_*
クラスはFsockopen
、Streams
、Curl
、Proxy
、Cookie
、Encoding
です。コールバックを'http_api_debug'
-アクションにフックすると、3番目の引数はどのクラスがあなたのリクエストに使われたかを教えてくれます。
WP_HTTP_curl
クラスの中には、request()
メソッドがあります。このメソッドは、SSLの振る舞いを傍受するための2つのフィルタを提供します。1つはローカル要求'https_local_ssl_verify'
、もう1つはリモート要求'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' );
サイドノート:ほとんどの場合、WP_HTTP_curl
がプロキシの処理に使用されます。
@kaiserの有用な回答に基づいて、うまく機能していると思われるコードをいくつか書きました。それが私が答えとしてマークした理由です。
私の解決策を説明させてください…
APIを介して送信されたリクエストがWP_Http::request()
を介して実行される場合。それが…の方法です
@todoこのコードをリファクタリングします。
…ヘッダーに。私はこれ以上同意できませんでした。
現在、いくつかのフィルターがあります。私は私のニーズのためにpre_http_request
を誤用することにしました:
add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );
ここで3つの引数を取得します:false, $r, $url
。
false
は、apply_filters()
の期待される戻り値です。他に何かを送り返すと、WordPressはすぐに停止し、元のリクエストは送信されません。
$r
は、そのリクエストの引数の配列です。これらも1分で変更する必要があります。
$url
は–驚きです! – URL。
そのため、コールバックt5_update_wp_per_https()
でURLを確認し、それがフィルタリングしたいURLである場合、NOto WordPress bynot“ no”(false
)と言います。
補足:すべての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
をクリックして、新しいファイルをダウンロードします。Win 7で2つのローカルインストール、単一サイトおよびマルチサイトセットアップでテストしました。更新を強制するには、$wp_version
のwp-includes/version.php
を1
に設定し、TwentyElevenのバージョンを1.3
。
私が使用したネットワークトラフィックを監視するために Wireshark :無料で、WindowsとLinuxで実行され、いくつかの印象的なフィルターツールを提供します。
HTTPSを見るのは少し難しいです。暗号化されたデータだけが表示されます。プラグインが何をすべきかを確認するために、まず暗号化されていないトラフィックを監視し、wordpress.orgへの接続に使用されたIPアドレスを書き留めました。それは72.233.56.138
、時には72.233.56.139
でした。
驚くべきことではありませんが、ロードバランサーとおそらく他の多くのツールがあるため、oneIPアドレスに依存することはできません。
次に、フィルターマスクにip.addr == 72.233.56.138
と入力し、プラグインをアクティブにし、wp-admin/update-core.php
に移動して、Wiresharkのトラフィックを監視しました。緑の線はプレーンテキストでのリクエストであり、まさに私たちが望まないものです。赤と黒の線は成功の兆候です。
更新チェックはうまくいきました。「新しい」バージョンが見つかりました。テーマとコアの実際の更新もうまくいきました。まさに私が必要なもの。
それでも…URLに簡単なフィルターがあればもっと簡単になります。
add_filter('http_request_args', 'http_request_args_custom', 10,2);
function http_request_args_custom($request,$url){
if (strpos($url, 'wordpress.org') !== false){
global $replaced_url;
$replaced_url = 'http://wordpress.local';
}
return $request;
}
add_action('http_api_curl', 'http_api_curl_custom');
function http_api_curl_custom(&$handle){
global $replaced_url;
if (!is_null($replaced_url))
curl_setopt( $handle, CURLOPT_URL, $replaced_url);
}
$http = new WP_Http();
$response = $http->request('http://wordpress.org', array());
var_dump($response);