CGI::Application::Dispatchを遊んでみる

ただ単にCGI::Application::Dispatchでディスパッチさせるだけでは
おもしろないので、RSSをパースしてみるWebアプリを作ってみました。
ATOMに未対応なのは開発環境のせいです。。本当はXML::Feedつかって
ATOMに対応したかったのですが。。。

LWP::UserAgentつこてるのも理由ありです。

愚痴はいいとして、以下、恥(ソース)さらしw

neko.cgi


#!/usr/local/bin/perl
use strict;
use warnings;
use lib qw(./lib);
use CGI::Application::Dispatch;
CGI::Application::Dispatch->dispatch(
PREFIX => 'Neko',
DEFAULT => 'Index',
);

./lib/Neko.pm


package Neko;
use strict;
use warnings;
use base 'CGI::Application';
sub cgiapp_init {
my $self = shift;
$self->tmpl_path('./template/');
}
sub cgiapp_prerun {
my $self = shift;
$self->header_add(-type => 'text/html; charset=UTF-8');
}
1;

./lib/Neko/Index.pm


package Neko::Index;
use strict;
use warnings;
use base 'Neko';
sub setup {
my $self = shift;
$self->start_mode('index');
$self->run_modes(
'index' => \&do_index,
);
}
sub do_index{
my $self = shift;
my $t = $self->load_tmpl('index.html',die_on_bad_params => 0,);
return $t->output;
}
1;

./lib/Neko/Parse.pm


package Neko::Parse;
use strict;
use warnings;
use base 'Neko';
use LWP::UserAgent;
use XML::RSS;
use CGI::Application::Plugin::FillInForm (qw/fill_form/);
sub setup {
my $self = shift;
$self->start_mode('parse');
$self->run_modes(
'parse' => \&do_parse,
);
}
sub do_parse {
my $self = shift;
if($self->get_xml){
return $self->_error($self->{'error'});
}
my $rss = XML::RSS->new();
eval{$rss->parse($self->{'xml'})} or return $self->_error('Parse Error');
my @entries;
for(@{$rss->{'items'}}){
my %entries;
$entries{title} = $_->{title};
$entries{link} = $_->{link};
$entries{creator} = $_->{dc}->{creator};
$entries{date} = $_->{dc}->{date};
$entries{description} = $_->{description};
$entries{description} =~ s/<p>|<\/p>//g;
push @entries, \%entries;
}
my $t = $self->load_tmpl('parse.html',die_on_bad_params => 0,);
$t->param(parse_info => \@entries);
return $self->fill_form( \$t->output );
}
sub get_xml {
my $self = shift;
my $ua = LWP::UserAgent->new();
my $q = $self->query();
my $req = HTTP::Request->new('GET',$q->param("target_uri"));
if($ua->request($req)->is_success) {
$self->{'xml'} = $ua->request($req)->content;
return 0;
}else{
$self->{'error'} = $ua->request($req)->status_line;
return 1;
}
}
sub _error {
my $self = shift;
my $errmsg = shift;
my $t = $self->load_tmpl('index.html',die_on_bad_params => 0,);
$t->param(error_info => [ {errormsg => $errmsg} ]);
return $self->fill_form( \$t->output );
}
1;

./template/index.html


<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title> Parse RSS Beta </title>
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.css" />
<script language="JavaScript" src="/js/main.js"></script>
</head>
<body>
<form name="fm" action="/neko.cgi/Parse" method="post"><br><br>
<div class="ttl">
<span class="t1">Parse</span>
<span class="t2">RSS</span>
<span class="t4">Beta</span>
</div><br><br>
<!--TMPL_LOOP NAME="error_info"-->
<div class="errormsg"><!--TMPL_VAR NAME="errormsg"--></div>
<!--/TMPL_LOOP-->
<div class="tx"><input type="text" name="target_uri" value="http://" size="60"></div><br><br>
<div class="btn"><input type="button" name="ex" value="Analysis" onClick="p_wait()"></div><br>
<div class="msg" id="msg"></div>
</form><br>
<!--
<div class="ft"> Copyright 2005- nekokak </div>
-->
</body>
</html>

./template/parse.html


<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title> Parse RSS Beta </title>
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="stylesheet" type="text/css" media="screen" href="/css/parse.css" />
<script language="JavaScript" src="/js/parse.js"></script>
</head>
<body>
<form name="fm" action="/neko.cgi/Parse" method="post">
<div class="ttl">
<a href="/cgi-bin/nekoreader/Pj-nekoreader/neko.cgi">
<span class="t1">Parse</span>
<span class="t2">RSS</span>
<span class="t4">Beta</span>
</a>
</div>
<div class="btx">
<input type="text" name="target_uri" value="<!--TMPL_VAR NAME="target_uri"- ->" size="60">
<input type="button" name="ex" value="Analysis" onClick="p_wait()">
<span class="msg" id="msg"></span>
</div>
<hr>
<div class="result">
<!--TMPL_LOOP NAME="parse_info"-->
<div>
<p class="title"><a href="<!--TMPL_VAR NAME="link"-->"><!--TMP_VAR NAME="title"--></a></p>
<p class="creator">Creator:<!--TMPL_VAR NAME="creator"--></p>
<p class="date">Date:<!--TMPL_VAR NAME="date"--></p>
<p class="description"><!--TMPL_VAR NAME="description"--></p>
<p class="link"><!--TMPL_VAR NAME="link"--></p>
</div>
<!--/TMPL_LOOP-->
</div>
</form><br>
<!--
<div class="ft"> Copyright 2005- nekokak </div>
-->
</body>
</html>

./css/main.css


@charset "UTF-8";
/*
* Perse RSS Beta
* Perse RSS Beta STYLESHEET
* http://www.border.jp/nekokak/blog/
*/
div.ttl{
font-style: italic;
text-align : center;
}
div.tx{
text-align : center;
}
div.btn{
text-align : center;
}
div.msg{
text-align : center;
}
div.errormsg{
text-align : center;
color : #FF0033;
}
span.t1{
color : #aaaaaa;
font-size: 36px;
}
span.t2{
color : #bbbbbb;
font-size: 33px;
}
span.t3{
color : #cccccc;
font-size: 33px;
}
span.t4{
color : #888888;
font-size: 15px;
}
div.ft{
text-align : center;
font : 0.8em Arial;
}

./css/parse.css


@charset "UTF-8";
/*
* Perse RSS Beta
* Perse RSS Beta STYLESHEET
* http://www.border.jp/nekokak/blog/
*/
div.ttl{
font-style: italic;
text-align : left;
}
div.ttl a{
text-decoration: none;
}
div.btx{
text-align : left;
}
div.msg{
text-align : center;
}
span.t1{
color : #aaaaaa;
font-size: 36px;
}
span.t2{
color : #bbbbbb;
font-size: 33px;
}
span.t3{
color : #cccccc;
font-size: 33px;
}
span.t4{
color : #888888;
font-size: 15px;
}
div.ft{
text-align : center;
font : 0.8em Arial;
}
p.title{
}
p.link{
color : #008000;
font-size: 12px;
}
p.creator{
font-size: 12px;
}
p.date{
font-size: 12px;
}
p.description{
font-size: 12px;
}

./js/main.js


function p_wait(){
var insertId = 'msg';
var msg='Pleas wait .....';
var targetNode = document.getElementById(insertId);
targetNode.innerHTML = msg;
document.fm.submit();
return true;
}

./js/parse.js


function p_wait(){
var insertId = 'msg';
var msg='Pleas wait .....';
var targetNode = document.getElementById(insertId);
targetNode.innerHTML = msg;
document.fm.submit();
return true;
}

こんなんでいかがでしょうか?

さっくりと開発するにはCGI::Applicationは便利ですね。
CGI::Application::Dispatchもグッドな感じです。

HTMLが見にくくてすみません。^^;