NAME
OX - the hardest working two letters in Perl
VERSION
version 0.01
SYNOPSIS
package MyApp;
use OX;
has template_root => (
is => 'ro',
isa => 'Str',
value => 'root',
);
has model => (
is => 'ro',
isa => 'MyApp::Model',
lifecycle => 'Singleton',
);
has tt => (
is => 'ro',
isa => 'Template',
dependencies => {
INCLUDE_PATH => 'template_root'
},
);
has root => (
is => 'ro',
isa => 'MyApp::Controller',
infer => 1,
);
router as {
route '/' => 'root.index';
route '/inc' => 'root.inc';
route '/dec' => 'root.dec';
route '/reset' => 'root.reset';
route '/set/:number' => 'root.set' => (
number => { isa => 'Int' },
);
};
DESCRIPTION
OX is a web framework based around PSGI and Bread::Board, and with easy access to routing via Path::Router. It provides all of the application building blocks as services in a Bread::Board container, so that all of your application objects can easily refer to each other. Your application is turned into a simple PSGI coderef, which can be used directly by any PSGI-supporting web server.
The philosophy behind OX is that it shouldn't require any explicit plugin system or glue layer to build your application. An OX application is just a normal Bread::Board container, and the default router implementation routes incoming paths to method calls on normal Moose classes. All configuration can be done through applying roles to your application class (to affect application initialization) or providing your own request class (to provide more features at runtime).
Although you can build your application manually (see the OX::Application docs for how to do that), OX comes with an easy to use sugar layer based on Bread::Board::Declare. This allows you to write your application class in a way that is very similar to writing a normal Moose class, with full use of Moose features like attributes and roles. See Bread::Board::Declare for an explanation of its syntax; all of it is valid in OX applications. In addition, applications defined with the OX sugar automatically get OX::Application::Role::Router::Path::Router and OX::Application::Role::RouteBuilder as well.
FUNCTIONS
as
router as {
...
};
Sugar function for declaring coderefs.
router
router as {
...
};
This function declares the router for your application. By default, it creates a router based on Path::Router. Within the router
body, you can declare routes, middleware, and mounted applications using the route
, wrap
, and mount
keywords described below.
router ['My::Custom::RouteBuilder'] => as {
...
};
By default, actions specified with route
will be parsed by either OX::RouteBuilder::ControllerAction, OX::RouteBuilder::HTTPMethod, or OX::RouteBuilder::Code, whichever one matches the route. If you want to be able to specify routes in other ways, you can specify a list of OX::RouteBuilder classes as the first argument to router
, which will be used in place of the previously mentioned list.
router 'My::Custom::Router' => (
foo => 'some_service',
);
router My::Custom::Router->new(%router_args);
If you have declared a router manually elsewhere, you can pass in either the class name or the built router object to router
instead of a block. It will be used directly in that case. If you pass a class name, it can take an optional hash of dependencies, which will be resolved and passed into the class's constructor as arguments.
route $path, $action_spec, %params
The route
keyword adds a route to the current router. It is only valid in a router
block. The first parameter to route
is the path for the route to match, the second is an action_spec
to be parsed by an OX::RouteBuilder class, and the remaining parameters are a hash of parameters containing either defaults or validations for the router to use when matching.
route '/' => 'controller.index';
This declares a simple route using the OX::RouteBuilder::ControllerAction route builder. When the application receives a request for /
, the application will resolve the controller
service, and call the index
method on it, passing in an OX::Request instance for the request. The index
method should return either a string, a PSGI response arrayref, or an object that responds to finalize
(probably a Web::Response object).
route '/view/:id' => 'posts.view', (
id => { isa => 'Int' },
name => 'view',
);
This declares a route with parameters. This will resolve the posts
service and call the view
method on it, passing in a request object and the value of id
. If id
was provided but was not an Int
, this route will not match at all. Inside the view
method, the mapping
method will return a hash of (controller => 'posts', action => 'view', id => $id, name => 'view')
.
Also, other parts of the application can call uri_for
with any unique subset of those parameters (such as (name => 'view', id => 1)
) to get the absolute URL path for this route (for instance, "/myapp/view/1"
if this app is mounted at /myapp
).
route '/method' => 'method_controller';
Since this action spec doesn't contain a .
, this will be handled by the OX::RouteBuilder::HTTPMethod route builder. If a user sends a GET
request to /method
, it will resolve the method_controller
service, and call the get
method on it, passing in the request object. Variable path components and defaults and validations work identically to the description above.
route '/get_path' => sub { my $r = shift; return $r->path };
This route will just call the given coderef directly, passing in the request object. Variable path components and defaults and validations work identically to the description above.
route '/custom' => $my_custom_thing;
In addition, if you specified any custom route builders in the router
description, you can pass anything that they can handle into the second argument here as well.
mount
The mount
keyword declares an entirely separate application to be mounted under a given path in your application's namespace. This is different from route
, because the targets are full applications, which handle the entire path namespace under the place they are mounted - they aren't just handlers for one specific path.
mount '/other_app' => 'My::Other::App', (
template_root => 'template_root',
);
If you specify a class name for the target, it will create an app by creating an instance of the class (resolving the parameters as dependencies and passing them into the constructor) and calling to_app
on that instance.
mount '/other_app' => My::Other::App->new;
If you specify an object as the target, it will create the app by calling to_app
on that object.
mount '/other_app' => sub {
my $env = shift;
return [ 200, [], [$env->{PATH_INFO}] ];
};
You can also specify a coderef directly. Note that in this case, unlike specifying a coderef as the route spec for the route
keyword, the coderef is a plain PSGI application, which receives an env hashref and returns a full PSGI response arrayref.
wrap
The wrap
keyword declares a middleware to apply to the application. The wrap
statements will be applied in order such that the first wrap
statement corresponds to the outermost middleware (just like Plack::Builder).
wrap 'Plack::Middleware::Static' => (
path => dep(value => sub { s{^/static/}{} }),
root => 'static_root',
);
If you specify a class name as the middleware to apply, it will create an instance of the class (resolving the parameters as dependencies and passing them into the constructor) and call wrap
on that instance, passing in the application coderef so far and using the result as the new application (this is the API provided by Plack::Middleware).
wrap Plack::Middleware::StackTrace->new(force => 1);
If you specify an object as the middleware, it will call wrap
on that object, passing in the application coderef so far and use the result as the new application.
wrap sub {
my $app = shift;
return sub {
my $env = shift;
return [302, [Location => '/'], []]
if $env->{PATH_INFO} eq '/';
return $app->($env);
};
};
If you specify a coderef as the middleware, it will call that coderef, passing in the application coderef so far, and use the result as the new application.
BUGS
No known bugs.
Please report any bugs through RT: email bug-ox at rt.cpan.org
, or browse to http://rt.cpan.org/NoAuth/ReportBug.html?Queue=OX.
SEE ALSO
SUPPORT
The IRC channel for this project is #ox
on irc.perl.org
.
You can find this documentation for this module with the perldoc command.
perldoc OX
You can also look for information at:
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
RT: CPAN's request tracker
Search CPAN
AUTHORS
Stevan Little <stevan.little at iinteractive.com>
Jesse Luehrs <doy at cpan dot org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Infinity Interactive.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.