1package Plack::Middleware::AMF;
2
3use warnings;
4use strict;
5
6our $VERSION = '0.02';
7
8use parent "Plack::Middleware";
9
10use Data::AMF::Remoting;
11use Plack::Request;
12use Plack::Util;
13use Plack::Util::Accessor qw/path headers_handler message_handler/;
14use UNIVERSAL::require;
15
16sub prepare_app {
17	my $self = shift;
18
19	unless (defined $self->headers_handler) {
20		$self->headers_handler(\&_default_headers_handler);
21	}
22
23	unless (defined $self->message_handler) {
24		$self->message_handler(\&_default_message_handler);
25	}
26
27	if (ref $self->headers_handler ne 'CODE') {
28		die 'headers_handler should be a code reference';
29	}
30
31	if (ref $self->message_handler ne 'CODE') {
32		die 'message_handler should be a code reference';
33	}
34}
35
36sub call {
37	my $self = shift;
38	my $env  = shift;
39
40	my $res = $self->_handle_amf($env);
41
42	return $res if $res;
43
44	return $self->app->($env);
45}
46
47sub _handle_amf {
48	my ($self, $env) = @_;
49
50	my $path_match = $self->path or return;
51	my $path = $env->{PATH_INFO};
52
53	for ($path) {
54		my $matched = 'CODE' eq ref $path_match ? $path_match->($_) : $_ =~ $path_match;
55		return unless $matched;
56	}
57
58	my $req = Plack::Request->new($env);
59	my $res = $req->new_response(200);
60
61	my $remoting = Data::AMF::Remoting->new(
62		source              => $req->raw_body,
63		headers_did_process => $self->headers_handler,
64		message_did_process => $self->message_handler,
65	);
66	$remoting->run if $remoting->{source};
67
68	$res->content_type('application/x-amf');
69	$res->body($remoting->data);
70
71	return $res->finalize;
72}
73
74sub _default_headers_handler {}
75
76sub _default_message_handler {
77	my $message = shift;
78
79	my ($controller_name, $action_name) = split '\.', $message->target_uri;
80
81	$controller_name->require or die $@;
82
83	my $controller = $controller_name->new;
84	my $action = $controller->can($action_name);
85
86	if (defined $action) {
87		return $controller->$action(@{ $message->value });
88	}
89}
90
911;
92__END__
93
94=head1 NAME
95
96Plack::Middleware::AMF - The great new Plack::Middleware::AMF!
97
98=head1 VERSION
99
100Version 0.01
101
102=head1 SYNOPSIS
103
104    use Plack::Builder;
105
106    builder {
107	    enable "AMF", path => qr/^\/amf\/gateway/;
108	    $app
109    };
110
111=head1 DESCRIPTION
112
113Enable this middleware to allow your Plack-based application to handle Flash Remoting and Flex RPC.
114
115=head1 CONFIGURATIONS
116
117=head2 path
118
119=head2 headers_handler
120
121=head2 message_handler
122
123=head1 METHOD
124
125=head2 prepare_app
126
127=head2 call
128
129=head1 AUTHOR
130
131Takuho Yoshizu, C<< <yoshizu at s2factory.co.jp> >>
132
133=head1 BUGS
134
135Please report any bugs or feature requests to C<bug-plack-middleware-amf at rt.cpan.org>, or through
136the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Plack-Middleware-AMF>.  I will be notified, and then you'll
137automatically be notified of progress on your bug as I make changes.
138
139
140=head1 SUPPORT
141
142You can find documentation for this module with the perldoc command.
143
144    perldoc Plack::Middleware::AMF
145
146
147You can also look for information at:
148
149=over 4
150
151=item * RT: CPAN's request tracker
152
153L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Plack-Middleware-AMF>
154
155=item * AnnoCPAN: Annotated CPAN documentation
156
157L<http://annocpan.org/dist/Plack-Middleware-AMF>
158
159=item * CPAN Ratings
160
161L<http://cpanratings.perl.org/d/Plack-Middleware-AMF>
162
163=item * Search CPAN
164
165L<http://search.cpan.org/dist/Plack-Middleware-AMF/>
166
167=back
168
169
170=head1 ACKNOWLEDGEMENTS
171
172
173=head1 LICENSE AND COPYRIGHT
174
175Copyright 2010 Takuho Yoshizu.
176
177This program is free software; you can redistribute it and/or modify it
178under the terms of either: the GNU General Public License as published
179by the Free Software Foundation; or the Artistic License.
180
181See http://dev.perl.org/licenses/ for more information.
182
183
184=cut
185