web-dev-qa-db-ja.com

認証されたHTTP接続またはcUrlハンドルを再利用する

私たちには、編集投稿ページにメタボックスを追加する、特別注文のWordpressプラグインがあります。プラグインは、セミプライベートHTTP REST AP​​Iからデータにアクセスします。

接続は認証され(DIGEST)、定期的にアクセスされます - 投稿を書いている人は誰でも数回(通常は急激に)対話し、そのような人は100人以上います。そのため、HTTP呼び出しが効率的に機能していることを確認したいと思います。 2つの問題があります。

  • TCPソケットの開閉を常時停止するためにKeep-Aliveが使用されているという証拠はありません。
  • DIGEST認証では、すべての要求が2回行われます。認証されているのは(ユーザーではなく)プラグインなので、これは99%を超える無駄です。 Apacheはこの解決策 を先制認証 と呼びました。

ユーザーがメタボックスを操作すると、メタボックスにレイテンシが表示されるため、これが本当の問題です。

これらの問題のいくつかはcURLハンドルを再利用することで解決できると聞きますが、それをWordPressプラグインに実装することに関するベストプラクティスのアドバイスを見つけることはできません。私たちが抱えている問題の1つは、WordPRessが要求できる限り、リクエストごとにプラグインを効果的に再初期化することです。

4
Simon Gibbs

Web環境(mod_php)におけるPHPの基本的な制限のため、これらの問題のいずれかを解決することは不可能です、少なくとも理にかなっていません。

クラス変数はWebリクエスト間で持続しないため、リクエストの最後にすべてのリソース(つまり、カールハンドル、TCPソケット)が破壊されるため、問題のキープアライブ部分は修正できません。 cUrlハンドルを再利用することは、バッチスクリプトや複数のURLに一度にアクセスする必要があるまれなWebスクリプトに主に関係しているようです。したがって、Java開発者向けの パフォーマンス最適化は標準と見なされる _の種類はPHP開発者には利用できません。

Authorizationヘッダーの値をセッションに固定してダイジェスト認証を実装しようとすることもできますが、それは実装するのが安くなく(開発時間が長い)、多くの企業が時間をかけたいと思うものではありません。これは、たとえば、3年生のニース大学プロジェクトかもしれません。

うまくいけば、いつか誰かがApacheのPHPのアドオン製品をリリースし、どういうわけかHTTPリクエストをプロセスの外部のTCP接続プールに送ることを望んでいます。 PHPからのアップストリームのHTTPリクエストから多くの待ち時間が発生することを考えると、これはおそらく儲かるでしょう。

2
Simon Gibbs

CURLリクエストを調べる

CURLリクエストの検査とデバッグがWordPressに固有のものではない場合でも、それを回避するにはWP HTTP API内部のかなりの部分を知る必要があります。私は自分のためにそれを行うためのプラグインを自分自身で書いています。これは、管理UIとフロントエンド/テーマの両方で、シャットダウンフックにcURLオブジェクトの詳細を出力します。

あなたができることは、まったく同じフックhttp_api_curlを使い、cURLオブジェクトを捕まえることです。それをクラス変数に保存し、それにあなたの次の呼び出しを添付して続けます。私はこれまで自分でこのようなことをしたことはありませんが、実行可能なはずです。

編集する

ここでの編集の数は限られているので、私はこのプラグインのさらなる開発を私の GitHubアカウント に移しました。メモ、コメント、提案がある場合は、そこにコメントを残してください。

以下のプラグインは完全に機能的です。まだもっと高度なバージョンが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 ) 
        );
    }
}
2
kaiser