Re use conexão HTTP autenticada ou identificador cUrl

4

Temos um plugin Wordpress personalizado, que adiciona uma meta box à página de edição de postagens. O plug-in acessa dados de uma API REST HTTP semi-privada.

A conexão é autenticada (DIGEST) e acessada regularmente - cada pessoa que escrever um post irá interagir com ela várias vezes (geralmente em rajadas apertadas) e há > 100 dessas pessoas. Então, gostaríamos de garantir que as chamadas HTTP estejam funcionando de maneira eficiente. Nós vemos dois problemas:

  • Nenhuma evidência de Keep-Alive sendo usada para interromper a abertura do soquete TCP e fechando constantemente.
  • Cada solicitação é feita duas vezes para a autenticação DIGEST. Como é o plugin autenticado (não o usuário), isso é > 99% de resíduos. O Apache chamou sua solução para essa autenticação preventiva .

Podemos ver a latência na caixa meta enquanto os usuários interagem com ela, portanto, isso é um problema real.

Eu ouço alguns desses problemas que podem ser resolvidos reutilizando o identificador cURL, mas não consigo encontrar nenhum conselho sobre práticas recomendadas para implementá-lo especificamente em um plug-in do WordPress. Um problema que temos com isso é que o WordPRess efetivamente reinicia o plug-in em uma base por solicitação, até onde podemos dizer.

    
por Simon Gibbs 16.01.2013 / 11:16

2 respostas

2

Não é possível, pelo menos não dentro da razão, resolver qualquer um desses problemas devido a limitações fundamentais do PHP em um ambiente web (mod_php).

As variáveis de classe não persistem entre solicitações da web, portanto, a parte do problema Keep-Alive do problema não pode ser corrigida porque todos os recursos (ou seja, curl handle, tcp socket) serão destruídos no final da solicitação. Reutilizar o identificador cURL parece ser mais relevante para scripts em lote ou para o raro script da Web que precisa acessar várias URLs de uma só vez. O tipo de otimizações de desempenho consideradas padrão para desenvolvedores Java, portanto, não está disponível para desenvolvedores PHP.

Pode-se tentar implementar a autenticação digest colocando os valores do cabeçalho Authorization na sessão, mas isso não é barato para implementar (tempo dev alto) e não é algo que muitas empresas querem dedicar tempo. Este pode ser um bom projeto universitário do 3º ano, por exemplo.

Esperançosamente, em algum momento, alguém lançará um produto complementar para PHP no Apache que, de alguma forma, canaliza solicitações HTTP para um conjunto de conexões TCP externo ao processo. Isso provavelmente geraria dinheiro, uma vez que derrubará muito a latência de solicitações HTTP do PHP.

    
por Simon Gibbs 23.01.2013 / 12:47
2

Inspecionando o pedido cURL

Mesmo que a inspeção e a depuração de uma solicitação cURL não seja algo exclusivo do WordPress, você precisa conhecer uma boa parte dos recursos internos da API de HTTP do WP para contorná-la. Eu mesmo escrevi um plugin para fazer isso para mim, que eu modifiquei / limpei e coloquei para você usar. Ele mostrará os detalhes do objeto cURL no gancho de desligamento, tanto na interface do usuário do administrador quanto no front-end / tema.

O que você pode fazer é usar exatamente o mesmo gancho http_api_curl e capturar o objeto cURL. Em seguida, salve-o em uma variável de classe, anexe suas próximas chamadas a ele e continue. Eu não fiz nada assim antes, mas deve ser factível.

Editar

  

Como o número de edições aqui é limitado, mudei o desenvolvimento deste plugin para a minha conta do GitHub . Se você tiver notas, comentários ou sugestões, deixe um comentário lá.

O plugin abaixo é totalmente funcional. Ainda há uma versão muito mais avançada no GitHub.

<?php
/** 
 * Plugin Name: (#81791) Dump cURL Request & Response 
 * Author:      Franz Josef Kaiser
 */
add_action( 'plugins_loaded', array( 'WPSE81791_cURL', 'init' ) );
class WPSE81791_cURL
{
    protected static $instance;

    public static $dump;

    public static function init()
    {
        null === self :: $instance AND self :: $instance = new self;
        return self :: $instance;
    }

    public function __construct()
    {
        add_action( 'http_api_curl', array( $this, 'dump_curl' ) );
        add_action( 'shutdown', array( $this, 'do_dump' ) );
    }

    /**
     * Debug the response in the middle.
     * Catches the cURL object during the request.
     * @param  cURL $handle
     * @return void
     */
    public function dump_curl( &$handle )
    {
        curl_setopt( $handle, CURLINFO_HEADER_OUT, 1 );
        curl_setopt( $handle, CURLOPT_HEADER, 0 );
        curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'dump_curl_buffer_cb' ) );
        curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'dump_curl_buffer_cb' ) );
        curl_exec( $handle );
        $this->add_dump(
             curl_getinfo( $handle, CURLINFO_HEADER_OUT )
            .$this->dump_curl_buffer_cb( null )
            .'<br />Nr. of Errors: '.curl_errno( $handle )
            .'<br />Errors: '.curl_error( $handle )
        );
    }

    /**
     * Callback for cURL dump method
     * @param  object $curl
     * @param  null   $data
     * @return int
     */
    public function dump_curl_buffer_cb( $curl, $data = null )
    {
        static $buffer = '';
        if ( is_null( $curl ) )
        {
            $r = $buffer;
            $buffer = '';
            return $r;
        }
        $buffer .= $data;
        return strlen( $data );
    }

    /**
     * Adds data to the static data stack
     * @param  
     * @return void
     */
    public function add_dump( $data )
    {
        self :: $dump[] = $data;
    }

    /**
     * Dumps the data stack for debug
     * @param  
     * @return void
     */
    public function do_dump()
    {
        printf(
             '<pre>%s</pre>'
            ,var_export( implode( "<br />", self :: $dump ), true ) 
        );
    }
}
    
por kaiser 22.01.2013 / 21:43