Commit | Line | Data |
b67ffc2e |
1 | package BackPAN::Web; |
2 | |
3 | use Web::Simple __PACKAGE__; |
b67ffc2e |
4 | use Plack::Builder; |
5 | use Plack::Util; |
6 | use HTML::Zoom; |
7 | use HTML::Zoom::FilterBuilder::Template; |
b67ffc2e |
8 | use File::stat; |
9 | use DateTime; |
b67ffc2e |
10 | |
92111caa |
11 | our $VERSION = '1.0'; |
b67ffc2e |
12 | |
13 | sub slurp { |
14 | my ( $self, $filename ) = @_; |
15 | return do { local (@ARGV, $/) = $filename; <> }; |
16 | } |
17 | |
18 | sub template_filename_for { |
19 | my ( $self, $name ) = @_; |
92111caa |
20 | return "root/html/${name}.html"; |
b67ffc2e |
21 | } |
22 | |
23 | sub layout_zoom { |
24 | my $self = shift; |
25 | return $self->{'template_zoom_for_template'}{'layout'} ||= HTML::Zoom->from_file( |
26 | $self->template_filename_for('layout') |
27 | ); |
28 | } |
29 | |
30 | sub template_zoom_for { |
31 | my ( $self, $template_name ) = @_; |
32 | $self->{'template_zoom_for_template'}{$template_name} ||= do { |
33 | my @body; |
34 | HTML::Zoom->from_file( |
35 | $self->template_filename_for($template_name) |
36 | )->select('#content')->collect_content({ into => \@body })->run; |
37 | $self->layout_zoom |
38 | ->select('#content')->replace_content(\@body) |
39 | ->memoize; |
40 | }; |
41 | } |
42 | |
43 | sub error_404 { |
44 | my $self = shift; |
45 | return $self->slurp( $self->template_filename_for('error_404') ); |
46 | } |
47 | |
48 | sub html_response { |
49 | my ( $self, $args ) = @_; |
2a30b3c1 |
50 | my ( $status, $header, $body ) = @$args{qw/status_code header body/}; |
51 | return [ $status || 200, [ |
b67ffc2e |
52 | $header ? ( %$header ) : (), |
53 | 'Content-type' => 'text/html', |
54 | ], ref $body ? $body->to_fh : [ $body ] ]; |
55 | } |
56 | |
b67ffc2e |
57 | sub index_page_content { |
58 | my $self = shift; |
92111caa |
59 | my $index_filename = $self->template_filename_for('index'); |
60 | my $index_st = stat($index_filename) |
61 | or die "No $index_filename: $!"; |
62 | $self->html_response({ |
63 | header => { 'Last-Modified' => $index_st->mtime }, |
64 | body => $self->slurp($index_filename), |
b67ffc2e |
65 | }); |
66 | } |
67 | |
92111caa |
68 | sub dispatch_request { |
69 | my $self = shift; |
70 | ( |
71 | sub (/) { |
72 | $self->index_page_content; |
73 | }, |
74 | |
75 | sub ( /about|/about/ ) { |
76 | my $about_filename = $self->template_filename_for('about'); |
77 | my $about_st = stat($about_filename) |
78 | or die "No $about_filename: $!"; |
79 | $self->html_response({ |
80 | header => { |
81 | 'Last-Modified' => $about_st->mtime, |
82 | }, |
83 | body => $self->slurp($about_filename), |
84 | }); |
85 | }, |
86 | |
87 | sub ( /releases|/releases/ + ?* ) { |
88 | $self->index_page_content; |
89 | }, |
90 | |
91 | sub ( /dists|/dists/ + ?* ) { |
92 | $self->index_page_content; |
93 | }, |
94 | |
95 | sub ( /distribution/*|/distribution/*/ + ?* ) { |
96 | $self->index_page_content; |
97 | }, |
98 | |
99 | sub ( /authors|/authors/ + ?* ) { |
100 | $self->index_page_content; |
101 | }, |
102 | |
103 | sub ( /search|/search/ + ?q=&* ) { |
104 | $self->index_page_content; |
105 | }, |
106 | ); |
b67ffc2e |
107 | }; |
108 | |
92111caa |
109 | around to_psgi_app => sub { |
110 | my ($orig, $self) = (shift, shift); |
111 | my $app = $self->$orig(@_); |
b67ffc2e |
112 | return builder { |
92111caa |
113 | enable_if { $ENV{PLACK_ENV} ne 'deployment' } 'Static', |
114 | path => qr{^/static}, |
115 | root => './root/'; |
b67ffc2e |
116 | enable 'ContentLength'; |
117 | enable 'ConditionalGET'; |
118 | enable 'ErrorDocument', |
119 | 500 => 'root/html/error_500.html', |
92111caa |
120 | 404 => 'root/html/index.html'; |
121 | enable 'HTTPExceptions'; |
b67ffc2e |
122 | enable 'Head'; |
b67ffc2e |
123 | $app; |
124 | }; |
92111caa |
125 | }; |
b67ffc2e |
126 | |
127 | =head1 AUTHOR |
128 | |
129 | Wallace Reis, C<< <wreis at cpan.org> >> |
130 | |
131 | =head1 LICENSE AND COPYRIGHT |
132 | |
cf4e2940 |
133 | © Copyright 2010-2011 Wallace Reis. |
b67ffc2e |
134 | |
135 | =cut |
136 | |
137 | __PACKAGE__->run_if_script; |