Filter any HTTP request URI?

时间:2012-11-14 作者:fuxia

我想过滤通过HTTP API完成的任何HTTP请求URI。

用例:

WordPress更新检查转到http://api.wordpress.org/core/version-check/1.6/, 但是https://api.wordpress.org/core/version-check/1.6/ 也很管用,我想一直用这个http://wordpress.org/wordpress-3.4.2.zip, 但是https://wordpress.org/wordpress-3.4.2.zip 也很有效更新请求是目前最重要的请求,因为还有未修复的请求bug 16778 (more information), HTTPS请求降低了中间人攻击的风险。

我有searched thoroughly, 我研究过核心代码……但两年前就和Nacin一样:

我确信您可以过滤HTTP请求的URL,但现在我找不到。

我错过了什么?是吗?:)

3 个回复
最合适的回答,由SO网友:kaiser 整理而成

这不是一个答案,但仅仅是我的经验中列出的一系列事情——也许你忽略了什么。

调试请求(&P);它的结果没有深入到更新过程中,但WP HTTP API使用WP_HTTP 班它还提供了一个好东西:调试挂钩。

do_action( \'http_api_debug\', $response, \'response\', $class, $args, $url );
在哪里$response 也可以是WP_Error 可能会告诉你更多的东西。

注意:从一个简短的测试来看,这个过滤器似乎只有(出于某种原因)在您将其置于实际执行请求的位置时才起作用。因此,您可能需要从以下某个过滤器的回调中调用它。

WP_HTTP 类参数本身是可过滤的,但有些类参数会被方法内部重置为WP认为需要的参数。

apply_filters( \'http_request_args\', $r, $url );
其中一个论点是ssl_verify, 这在默认情况下是正确的(但对我来说,从GitHub更新时会导致大量问题)编辑:调试测试请求后,我找到了另一个参数,该参数设置为验证SSL是否设置为true. 它叫sslverify (不分隔下划线)。不知道这是从哪里来的,它是在使用还是被放弃,你是否有机会影响它的价值。我用\'http_api_debug\' 滤器

完全自定义,您还可以“简单地”覆盖整个内部构件并进行自定义设置。有一个过滤器。

apply_filters( \'pre_http_request\', false, $r, $url );
第一个参数需要设置为true。这样你就可以与里面的参数进行交互$r 结果来自parse_url( $url );.

代理

另一个可行的方法是通过自定义代理运行所有内容。这需要在您的wp-config.php. 我以前从未尝试过这一点,但不久前我浏览了这些常量,总结了一些应该有用的示例,并附上了一些注释,以备将来需要。你必须定义WP_PROXY_HOSTWP_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 类通常用作基本类(将针对不同的场景进行扩展)。延伸WP_HTTP_* 课程为Fsockopen, Streams, Curl, Proxy, Cookie, Encoding. 如果将回调挂接到\'http_api_debug\'-操作,则第三个参数将告诉您哪个类用于您的请求。

内部WP_HTTP_curl 同学们,你们会发现request() 方法此方法提供了两个筛选器来拦截SSL行为:一个用于本地请求\'https_local_ssl_verify\' 一个用于远程请求\'https_ssl_verify\'. WP可能会定义locallocalhost 以及你从中得到的回报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 将用于处理代理。

SO网友:fuxia

根据@kaiser的有用答案,我编写了一些代码,似乎效果很好。这就是我把它标记为答案的原因。

让我解释一下我的解决方案…

通过API发送的请求运行时的逻辑WP_Http::request(). 这就是…

@todo重构此代码。

…在其标题中。我完全同意。

现在,有一些过滤器。我决定滥用pre_http_request 根据我的需要:

add_filter( \'pre_http_request\', \'t5_update_wp_per_https\', 10, 3 );
这里有三个参数:false, $r, $url.

  • false 是的预期返回值apply_filters(). 如果我们返回任何其他内容,WordPress将立即停止,原始请求将不会被发送。

  • $r 是该请求的参数数组。我们也必须在一分钟内改变这些。

  • $url 是–惊喜!–URL。

    因此,在我们的回拨中t5_update_wp_per_https() 我们查看URL,如果它是我们要筛选的URL,我们会说NO 对WordPress说“不”(false).

    enter image description here

    旁注:您可以通过以下方式阻止所有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:      Fuxia Scholz
     * Author URI:  https://fuxia.me
     * 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 下载新文件$wp_version 在里面wp-includes/version.php1 以及2011年版1.3.

      查看我使用的网络流量Wireshark: 它是免费的,在Windows和Linux上运行,并提供了一些令人印象深刻的过滤工具。

      观看HTTPS有点困难:你只看到加密的数据……这毕竟是个主意。为了看看我的插件是否做了它应该做的事情,我首先观察了未加密的流量,并记下了用于连接wordpress的IP地址。组织。那是72.233.56.138, 有时72.233.56.139.
      不足为奇,有一个负载平衡器,可能还有许多其他工具,因此我们不能依赖one IP地址。

      然后我打字ip.addr == 72.233.56.138 进入过滤器掩码,激活插件,转到wp-admin/update-core.php 观察Wireshark的交通状况。绿线是纯文本格式的请求,这正是我们不想要的。红线和黑线是成功的标志。

      Wireshark

      更新检查进行得很顺利:它找到了“更新的”版本。主题和核心的实际更新也很顺利。正是我所需要的。

      而且……如果URL有一个简单的过滤器,那就更容易了。

SO网友:Oleg Butuzov
    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);
结束

相关推荐

Allow single quote in URLs

我有一个WordPress网站Go Daddy 运行Apache的服务器。我的经验是在Windows IIS上,所以这可能是一个简单的问题,但我无法理解。我想在我的网站上允许URL,如:http://my.site.com/biz/Jordan\'s\\U place/约旦/问题有两个方面。1) 如果我进入http://my.site.com/biz/Jordan\'s\\U place/约旦/URL很好,但如果我输入:http://my.site.com/biz/Jordan\'s\\U place/约