¿Filtra cualquier URI de solicitud HTTP?

9

Quiero filtrar cualquier URI de solicitud HTTP realizada a través de la API HTTP.

Casos de uso:

  1. La comprobación de actualización de WordPress va a enlace , pero enlace también funciona, y quiero usar esto siempre.
  2. El nuevo archivo de WordPress se toma de enlace , pero enlace también funciona.
  3. A veces quiero depurar las solicitudes y redireccionarlas temporalmente a un dominio personalizado en mi servidor local.
  4. Algunos complementos realizan solicitudes a otros servidores, y quiero reemplazar estas solicitudes cuando el servidor externo falla.

Las solicitudes de actualización son las más importantes por ahora, porque todavía hay un bug 16778 ( Más información ), y las solicitudes de HTTPS reducen el riesgo de un ataque Man in the middle.

Tengo buscado a fondo , he estudiado el código central ... pero terminé como Nacin hace dos años:

  

Pensé que podría filtrar la URL de una solicitud HTTP, pero ahora no puedo encontrar una.

¿Qué me perdí? ¿Hice? :)

    
pregunta fuxia 14.11.2012 - 08:08

3 respuestas

8

Menos que una respuesta, pero solo una lista de cosas directamente de mi experiencia con él, tal vez haya pasado por alto algo.

Depurando la solicitud & sus resultados

Sin excavar demasiado en el proceso de actualización, pero la API HTTP de WP usa la clase WP_HTTP . También ofrece una buena cosa: un gancho de depuración.

do_action( 'http_api_debug', $response, 'response', $class, $args, $url );

Donde $response también puede ser un objeto WP_Error que quizás te diga más.

Nota: de una breve prueba, este filtro parece funcionar solo (por algún motivo) si lo coloca como cerca en el lugar donde está realizando la solicitud. Es posible que necesite llamarlo desde una devolución de llamada en uno de los siguientes filtros.

WP_HTTP Argumentos de la clase

Los argumentos de las Clases en sí son filtrables, pero algunos métodos internos se restablecen a lo que WP supone que es necesario.

apply_filters( 'http_request_args', $r, $url );

Uno de los argumentos es ssl_verify , que es verdadero de forma predeterminada (pero para mí causa problemas masivos al actualizar desde, por ejemplo, GitHub). Editar: Después de depurar una solicitud de prueba, encontré otro argumento que está configurado para verificar si SSL está configurado como true . Se llama sslverify (sin separar el guión bajo). No tengo idea de dónde entró esto en el juego, si está realmente en uso o abandonado y si tienes la oportunidad de influir en su valor. Lo encontré usando el filtro 'http_api_debug' .

Completamente personalizado

También puede "simplemente" anular todas las partes internas e ir con una configuración personalizada. Hay un filtro para eso.

apply_filters( 'pre_http_request', false, $r, $url );

El primer argumento debe establecerse en verdadero. Entonces puedes interactuar con los argumentos dentro de $r y el resultado de parse_url( $url ); .

Proxy

Otra cosa que podría funcionar podría ser ejecutar todo a través de un Proxy personalizado. Esto necesita algunos ajustes en su wp-config.php . Nunca había intentado esto antes, pero hace un tiempo repasé las constantes y resumí algunos ejemplos en los que debería funcionar e incluí algunos comentarios en caso de que lo necesite algún día. Debe definir WP_PROXY_HOST y WP_PROXY_PORT como un mínimo. ajuste. De lo contrario, nada funcionará y simplemente pasará por alto tu proxy.

# 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' );

EDITAR

La clase WP_HTTP normalmente actúa como clase base (se ampliará para diferentes escenarios). Las clases WP_HTTP_* extendidas son Fsockopen , Streams , Curl , Proxy , Cookie , Encoding . Si enlaza una devolución de llamada a la acción 'http_api_debug' , entonces el tercer argumento le dirá qué clase se utilizó para su solicitud.

Dentro de la clase WP_HTTP_curl , encontrarás el método request() . Este método ofrece dos filtros para interceptar el comportamiento SSL: uno para solicitudes locales 'https_local_ssl_verify' y otro para solicitudes remotas 'https_ssl_verify' . Es probable que WP defina local como localhost y lo que obtenga a cambio de get_option( 'siteurl' ); .

Entonces, lo que haría es intentar lo siguiente justo antes de que hagas esa solicitud (o de una devolución de llamada que esté conectada a la solicitud más cercana:

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: En la mayoría de los casos, WP_HTTP_curl se usará para manejar Proxies.

    
respondido por el kaiser 14.11.2012 - 11:42
8

Basado en la útil respuesta de @ kaiser, he escrito un código que parece funcionar bien. Esa es la razón por la que lo marqué como La Respuesta.

Déjame explicarte mi solución ...

La lógica

Cuando una solicitud enviada a través de la API se ejecuta a través de WP_Http::request() . Ese es el método con ...

  

@todo Refactoriza este código.

... en su encabezado. No podría estar más de acuerdo.

Ahora, hay algunos filtros. Decidí hacer un mal uso de pre_http_request para mis necesidades:

add_filter( 'pre_http_request', 't5_update_wp_per_https', 10, 3 );

Aquí obtenemos tres argumentos: false, $r, $url .

  • false es el valor de retorno esperado para apply_filters() . Si devolvemos algo más, WordPress se detiene de inmediato, y la solicitud original no se enviará.

  • $r es una matriz de argumentos para esa solicitud. Tenemos que cambiar esto también en un minuto.

  • $url is - ¡sorpresa! - la URL.

Entonces, en nuestra devolución de llamada t5_update_wp_per_https() miramos la URL, y si es una URL que queremos filtrar, le decimos NO a WordPress y no dice " no ”( false ).

Notaalmargen:Acontinuación,puedeevitartodaslassolicitudesHTTPcon:
add_filter('pre_http_request','__return_true');

Envezdeeso,lanzamosnuestrapropiasolicitudconunamejorURLyargumentosligeramenteajustados($r,renombradoa$argsparafacilitarlalectura).

Elcódigo

Porfavor,lealoscomentariosenlínea,sonimportantes.

<?php/***PluginName:T5UpdateWPperHTTPS*Description:ForcesupdatechecksanddownloadsforWPtouseHTTPS.*PluginURI:http://wordpress.stackexchange.com/questions/72529/filter-any-http-request-uri*Version:2012.11.14*Author:ThomasScholz*AuthorURI:http://toscho.de*Licence:MIT*LicenseURI:http://opensource.org/licenses/MIT*/add_filter('pre_http_request','t5_update_wp_per_https',10,3);/***ForceHTTPSrequestsforupdatechecksandnewWPversiondownloads.**@wp-hookpre_http_request*@parambool$false*@paramarray$args*@paramstring$url*@returnFALSE|array|objectFALSEifeverythingisokay,anarrayofrequest*resultsoranWP_Errorinstance.*/functiont5_update_wp_per_https($false,$args,$url){//SplittheURLintousefulparts.$url_data=parse_url($url);//ItisalreadyHTTPS.if('https'===strtolower($url_data['scheme']))returnFALSE;//Notourhost.if(FALSE===stripos($url_data['host'],'wordpress.org'))returnFALSE;//MakethatanHTTPSrequest.$new_url=substr_replace($url,'https',0,4);//WP_Httpcannotverifythewordpress.orgcertificate.$args['sslverify']=FALSE;//Itisslow.Wewaitatleast30seconds.30>$args['timeout']and$args['timeout']=30;//GetaninstanceofWP_Http.$http=_wp_http_get_object();//Gettheresult.$result=$http->request($new_url,$args);/*prependthislinewitha'#'todebuglikeaboss.print'<pre>'.htmlspecialchars(print_r($result,TRUE),ENT_QUOTES,'utf-8',FALSE).'</pre>';die();/**/return$result;}

Laspruebas

SineseplugindeWordPressutilizado:

  • http://api.wordpress.org/core/version-check/1.6/paraverificacionesdeactualización,y
  • http://wordpress.org/wordpress-3.4.2.zipparadescargarlosnuevosarchivos.

Loprobécondosinstalacioneslocales,unsolositioyunaconfiguracióndevariossitiosenWin7.Paraforzarunaactualizaciónconfiguré$wp_versionenwp-includes/version.phpa1ylaversióndeVeinteañoshasta1.3.

Paravereltráficodelaredusé Wireshark : es gratuito, funciona en Windows y Linux, y ofrece un filtro impresionante herramientas.

Ver HTTPS es un poco difícil: solo ves datos encriptados ... esa es la idea después de todo. Para ver si mi complemento hizo lo que debía hacer, primero observé el tráfico no cifrado y anoté la dirección IP utilizada para conectar a wordpress.org. Eso fue 72.233.56.138 , a veces 72.233.56.139 .
No es sorprendente, hay un equilibrador de carga y probablemente muchas otras herramientas, por lo que no podemos confiar en una una dirección IP.

Luego escribí ip.addr == 72.233.56.138 en la máscara del filtro, activé el complemento, fui a wp-admin/update-core.php y observé el tráfico en Wireshark. Las líneas verdes son solicitudes en texto sin formato, exactamente lo que no queremos. Las líneas rojas y negras son un signo de éxito.

Laverificacióndeactualizaciónsalióbien:encontrólasversiones"más nuevas". Las actualizaciones reales para el tema y el núcleo también funcionaron bien. Exactamente lo que necesitaba.

Y aún así ... eso podría ser más fácil si hubiera un filtro simple para la URL.

    
respondido por el fuxia 15.11.2012 - 02:03
1
    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);
    
respondido por el Butuzov 14.11.2012 - 08:23

Lea otras preguntas en las etiquetas