work.log

元エンジニアの備忘録的ブログ

PerlのXML::XPathを使ってPingサーバを建てる

投稿:2014-07-09 17:02  更新:

下記記事で書いた更新通知用の Ping サーバのメモ。

前回は Perl の XMLRPC::Transport::HTTP モジュールを使って簡単なサーバを書いてみたけど、実際に稼働させたいサーバを覗いたらこのモジュールが無かった。別途インストールすれば良いんだろうけど Ping を受けるだけなら何でも良いんじゃなかという事で書き直し。

XML::XPath が使えるのでこれに置き換えてみた。

#!/usr/bin/perl

use strict;
use warnings;
use XML::XPath;

    my $method = 'weblogUpdates';
    my $query = '';
    my $xpath = '';
    my $nodeset = '';
    my $msg = {};

    $msg = {
        0 => 'Thanks for the ping',
        1 => 'Bad Request',
    };

    ## POST かつ XML 以外のリクエストはエラーを出力し終了
    if ($ENV{'REQUEST_METHOD'} !~ /^POST$/i ||
        $ENV{'CONTENT_TYPE'} !~ /^(text|application)\/xml$/) { &print_xml(1); }

    read (STDIN, $query, $ENV{'CONTENT_LENGTH'});

    ## 受けたリクエスト内容をデバッグ用のログに記録
    open(OUT, "> debug.log");
    print OUT "----- req -----\n";
    print OUT "$query\n";
    print OUT "----- req -----\n";
    close(OUT);

    ## メソッド名を取得
    $xpath = XML::XPath->new(xml => $query); 
    $nodeset = $xpath->find('//methodName/text()');

    ## 未知のメソッド名であればエラーを出力し終了
    if ($nodeset !~ /^$method/) { &print_xml(1); }

    ## テキストノードの抜き出してデバッグ用のログに記録
    $nodeset = $xpath->find('//params/param/value/string');

    open(OUT, ">> debug.log");
    foreach ($nodeset->get_nodelist) {
        print OUT $xpath->getNodeText($_), "\n";
    }
    close(OUT);

    ## レスポンスを返して終了
    &print_xml(0);

sub print_xml {

    my $flag = shift;

    print "Content-type: text/xml\n";
    print "\n";
    print "<?xml version='1.0'?>\n";
    print "<methodResponse><params>\n";
    print "<param><value><struct>\n";
    print "<member>\n";
    print "<name>flerror</name><value><boolean>$flag</boolean></value>\n";
    print "</member>\n";
    print "<member>\n";
    print "<name>message</name><value><string>$msg->{$flag}</string></value>\n";
    print "</member>\n";
    print "</struct></value></param>\n";
    print "</params></methodResponse>\n";

    exit;

}
 
exit;

これを適当な名前で htdocs に配置して、WordPress の Ping 通知先にセットしてみる。

適当な記事を更新するとこんなリクエストが飛ぶ。

<?xml version="1.0"?>
<methodCall>
<methodName>weblogUpdates.extendedPing</methodName>
<params>
<param><value><string>work.log</string></value></param>
<param><value><string>https://worklog.be/</string></value></param>
<param><value><string>https://worklog.be/feed</string></value></param>
</params></methodCall>

取得したデバッグ用のログはこんな感じ。

# cat debug.log
----- req -----
<?xml version="1.0"?>
<methodCall>
<methodName>weblogUpdates.extendedPing</methodName>
<params>
<param><value><string>work.log</string></value></param>
<param><value><string>https://worklog.be/</string></value></param>
<param><value><string>https://worklog.be/feed</string></value></param>
</params></methodCall>
----- req -----
work.log
https://worklog.be/
https://worklog.be/feed

適当に書いちゃってるけど Ping 受けるだけならこんな感じで OK でしょ多分。

ちょっと気になったのは前回書いた時はメソッド名が「weblogUpdates.ping」だったけど、今回やったら「weblogUpdates.extendedPing」になってた。

weblogUpdates.ping の拡張版らしく下記を含めた PIng らしい。

  • サイトの名前
  • サイトの URL
  • 変更したページの URL
  • フィードの URL

どう見ても「変更したページの URL」が入ってないけどどういう事だろ。

とりあえず今日はここまで!

参考にしたページ
oogle ブログ検索の更新通知 API について
weblogUpdates.extendedPing/Blog Ping自動送信ソフト開発 第3稿