3. Angelos github.com/dann dann
Presentation Overview
•What is modern web application
framework?
•How to develop the minimal
elements of modern WAF
•How to develop the plugin
architecture of WAF
4. Angelos github.com/dann dann
What is modern WAF?
•Fullstack like Rails
•Pluggable like Plagger
•Server Abstraction like WSGI
•Separete WAF and App
Usability
Extendability
Testability
6. Angelos github.com/dann dann
The basic elements
Component
ManagerDispatcher
Engine
recieve a request and return a
response
(Server Abstraction)
URL to Controller
resolver Load and search component
8. Angelos github.com/dann dann
Engine - Angelos::Engine
sub build_engine {
my $self = shift;
my $request_handler = $self->request_handler;
$request_handler ||= $self->build_request_handler;
return Angelos::PSGI::Engine->new(
interface => {
module => $self->server,
....
},
psgi_handler => $request_handler,
);
} psgi handler which is passed to
the server gateay
the type of server
gateway
9. Angelos github.com/dann dann
Engine - Angelos::PSGI::Engine
use Mouse;
use Angelos::Types qw( ServerGateway );
has 'interface' => (
is => 'ro',
isa => ServerGateway,
coerce => 1,
);
has 'psgi_handler' => ( is => 'rw', );
sub run {
my $self = shift;
$self->interface->run( $self->psgi_handler );
}
pass psgi handler to server
gateway
Create Server Gateway
10. Angelos github.com/dann dann
Create Server Gateway
package Angelos::PSGI::ServerGatewayBuilder;
use strict;
use warnings;
use Plack::Loader;
sub build {
my ( $class, $module, $args ) = @_;
my $server_gateway = Plack::Loader->load( $module,
%{$args} );
$server_gateway;
}
Create server gateway with
Plack::Loader
11. Angelos github.com/dann dann
psgi handler s code
...
sub {
my $env = shift;
my $req = Angelos::Request->new($env);
my $res = $self->handle_request($req);
my $psgi_res = $self->finalize_response($res);
return $psgi_res;
}
... return PSGI response
recieve PSGI env
and convert it to WAF Request
12. Angelos github.com/dann dann
Request Handler - Angelos::Engine::Base
sub handle_request {
my ( $self, $req ) = @_;
eval { $self->DISPATCH($req); };
if ( my $e = Exception::Class->caught() ) {
$self->HANDLE_EXCEPTION($e);
}
# return response
return $self->context->res;
}
②dispatch request to
Dispatcher
①recive a request
13. Angelos github.com/dann dann
Dispatching
sub DISPATCH {
my ( $self, $req ) = @_;
my $dispatch = $self->dispatcher->dispatch($req);
...
$dispatch->run;
# return response
$c->res;
}
② Dispatch a request do
dispatcher
14. Angelos github.com/dann dann
Angelos::Dispatcher
sub dispatch {
my ( $self, $request ) = @_;
my $match = $self->router->match($request);
my $dispatch = $self->dispatch_class->new( match =>
$match );
return $dispatch;
}
③ <URL to Controller>
search controller name
based on the request path
with HTTP::Router
④ Create dispatch
instance
15. Angelos github.com/dann dann
Angelos::Dispatcher::Dispatch
my $controller = $match->params->{controller};
my $controller_instance = $self-
>find_controller_instance(
{ context => $c,
controller => $controller,
}
);
...
$controller_instance->_dispatch_action( $action,
$params );
⑤ search a controller
instance from Component
Manager
⑥ execute Controller’s
action and return response.
17. Angelos github.com/dann dann
Routing Table
.----------------------------------------------+------------+------------+--------------.
| path | method | controller | action |
+---------------------------------------------+------------+------------+------------+
| / | | Root | index |
| /book.{format} | POST | Books | create |
| /book | POST | Books | create |
| /book.{format} | GET | Books | index |
| /book | GET | Books | index |
| /book/new.{format} | GET | Books | post |
| /book/new | GET | Books | post |
| /book/{book_id}.{format} | GET | Books | show |
| /book.{format} | POST | Books | create |
| /book | POST | Books | create |
| /book.{format} | GET | Books | index |
| /book.{bookk_id}.{format} | DELETE | Books | destroy |
| /book/{book_id} | DELETE | Books | destroy |
| /book/{book_id}.{format} | PUT | Books | update |
| /book/{book_id} | PUT | Books | update |
'-----------------------------------------------+------------+------------+-------------
18. Angelos github.com/dann dann
Finished developing basic
elements of WAF
•It’s really easy to develop basic
elements of WAF
•You can develop simple WAF
like Sinatra in 4 or 5 hours
20. Angelos github.com/dann dann
How to development the plugin
architecture of WAF
• What the plugin architecture of WAF
SHOULD be
• The type of Plugins
• How to develop plugin architecture of
WAF
• Example: the plugin of Angelos
21. Angelos github.com/dann dann
What the plugin architecture of WAF SHOULD
• the core elements of WAF should be as
small as possible and the all parts of WAF
should be extendable and pluggable
• The scope of plugin should be limeted
• Controller,View, Middleware, Request,
Response
• Extension point must be declaretive
23. Angelos github.com/dann dann
Plugin Implementation
• Hook WAF’s lifecycle
• Mouse’s Role + method modifier
• Class::Trigger
• MouseX::Object::Pluggable
• Add methods to WAF’s classes
• Mouse’s Role
• Exporter
• Multiple inheritance
24. Angelos github.com/dann dann
How to develop plugin in Angelos
• Make Plugin as Role
• User consume plugins in the WAF Component
• Hook WAF’s lifecycle with method modifier
• hook Component’s hook point
• Declare hook point method with CAPITAL
character
25. Angelos github.com/dann dann
Hook point example
sub _dispatch_action {
my ( $self, $action, $params ) = @_;
...
eval { $self->ACTION( $self->context, $action, $params ); };
...
}
Declare hook point with
Capital character
26. Angelos github.com/dann dann
the code of Plugin
before 'ACTION' => sub {
my ( $self, $c, $action, $params ) = @_;
$self->__action_start_time( time() );
};
after 'ACTION' => sub {
my ( $self, $c, $action, $params ) = @_;
$self->__action_end_time( time() );
my $elapsed = $self->__action_end_time - $self-
>__action_start_time;
my $message
= "action processing time:naction: $action ntime : $elapsed
secsn";
$self->log->info($message);
};
27. Angelos github.com/dann dann
What The WAF developer should do
• WAF developer should make default plugin sets
which user should use
• if there aren’t default plugins sets...
• How can I use Unicode in WAF?
• ... UseXXX,YYY...
• How can I inflate datetime? ...
28. Angelos github.com/dann dann
Conclusion
• The basic elements of WAF
• Engine, Dispatcher, Component Loader
• WAF’s plugin
• Hook WAF Lifecycle or add a Method to the
Component of WAF
• Plugin Scope must be limited
• the plugin and plugins default sets should be
provided by WAF developer
29. Angelos github.com/dann dann
Fin.
• It’s really easy to implement WAF now
• Let’s develop modern WAF with us ;)
• Repository
• http://github.com/dann/angelos/tree/master