-
-
18 Nov 2017 17:39:04 UTC
- Distribution: Dancer2-Plugin-OpenAPIRoutes
- Module version: 0.03
- Source (raw)
- Browse (raw)
- Changes
- How to Contribute
- Repository
- Issues (1)
- Testers (500 / 0 / 22)
- Kwalitee
Bus factor: 0- 12.50% Coverage
- License: artistic_2
- Perl: v5.10.0
- Activity
24 month- Tools
- Download (8.22KB)
- MetaCPAN Explorer
- Permissions
- Subscribe to distribution
- Permalinks
- This version
- Latest version
- Dependencies
- Dancer2
- Data::Walk
- File::Spec
- JSON
- JSON::Pointer
- Module::Load
- YAML::XS
- and possibly others
- Reverse dependencies
- CPAN Testers List
- Dependency graph
NAME
Dancer2::Plugin::OpenAPIRoutes - automatic routes creation from Swagger specification file.
SYNOPSIS
use Dancer2; use Dancer2::Plugin::OpenAPIRoutes; OpenAPIRoutes(0);
DESCRIPTION
Automatically creates Dancer's routes from Swagger specification file. Extracts request parameters according to given spec. Uploaded files are Dancer2::Core::Request::Upload objects.
Automatically decodes JSON parameters if "Content-Type" is application/json. Automatically encodes answers to application/json if "Accept" header asks for it and returned value is reference.
IFF JSV::Compilator module was loaded before, then it will be used for input data validation. Otherwise it checks whether parameter is required or not but doesn't do real validation.
Catches thrown exceptions and makes JSON error messages if "Accept" is application/json.
Makes very smart mapping from route to Module::handler_function. For example:
/order: post: ... /order/{id} delete: ... patch: ...
will be mapped to Order::create(), Order::remove() and Order::update() accordingly.
CONFIGURATION
Schema details will be taken from your Dancer2 application config file, and should be specified as, for example:
plugins: OpenAPIRoutes: schema: public/swagger.yaml namespace: MyApp default_module: MyApp
- schema
-
Location of the Swagger spec file relative to the project root.
- namespace
-
Starting namespace for generated module name.
- default_module
-
Module name to put root's routes.
You have to call
OpenAPIRoutes([$debug_flag, $custom_map])
in your main application module. Optionally you can pass true value as first argument to see how it maps routes to Modules and functions.SMART MAPPING
This is probably the most crucial feature of this plugin. It automatically makes your application structured according to given spec file. It also makes your application less dependent on Dancer2 framework - you have to think more about application logic and less about framework details. Mapping is complicated but intuitive.
MAPPING RULES
Both the route and its HTTP method are used to compose the mapping.
HTTP METHOD MAPPING
This is starting point of the mapping algorithm. If route has only one method, then route's last part can be used as function name in module which name made of previous route parts.
- POST
-
In RESful terms POST means creation of some resource. That's why usually it maps to
create()
function with one exception: if route ends with /{someId} then it meansupdate()
. - GET
-
This methis is mapped to function
fetch()
. - DELETE
-
This method is mapped to
remove()
. Perl language already hasdelete()
function and it's better not to reuse its name. - PUT
-
In RESful terms PUT means full replacement of some resource. This method is mapped to
replace()
- PATCH
-
In RESful terms PATCH means partial update of some resource. This method is mapped to
update()
- OPTIONS
-
This method is mapped to
choices()
- HEAD
-
This method is mapped to
check()
You don't usually have to define HEAD method because it's done automatically from GET throwing away real answer.
ROUTES MAPPING
Basic idea is very simple: /resource/subresource is mapped to Resource::Subresource module and function name is mapped according HTTP method. Then there're special cases (from OpenAPI example spec):
It would be silly to put these three routes with single method in separate modules
Pet::UploadImage
,Pet::FindByTags
andPet::FindByStatus
. That's why routes with only one method are mapped to theirs "parents" with function name from last route part.NOTICE: It's important to describe path parameters twice: in route and in parameters method's section. Because they are extracted as
regexp captures
and routes with integer parameters should be dispatched first to avoid collision between/pet/{petId}
and/pet/findByTags
type of routes.INTERFACE
ENVIRONMENT VARIABLES
When you need some variable from PSGI's environment, like REMOTE_USER, then it's really inconvenient to get directly from Dancer2 framework. There's a support to get it automatic using OpenAPI extension keyword x-env-{environment-variable} like x-env-remote-user: user. This keyword should be put in HTTP method section. Directive x-env-remote-user: user will put value of PSGI's environment variable
REMOTE_USER
into input hash parameter keyuser
.FUNCTION INTERFACE
Mapped route's function is called like this:
($result, $status, $callback) = ${module_name}::$module_func( \%input, $dsl );
Function receives hash reference with extracted parameters according to Swagger spec and
Dancer2
DSL
object. This object is rarely needed but sometimes you need to have access to application's object, for example:$dsl->app->send_file(...);
Most of the time function can return only one result like this:
sub fetch { my $input = $_[0]; my $pet = schema->get_pet( $input->{petId} ); return $pet; }
Sometimes you want to change response status:
sub remove { my $input = $_[0]; my $error = schema->delete_pet( $input->{petId} ); if ($error) { return ( { error => $error }, 'bad_request' ); } return ( '', 'no_content' ); }
In some odd cases when you use old Dancer2, then you have to call specific functions directly from route handler using callback:
sub downloadFile { my $dsl = $_[1]; # ... return ( undef, undef, sub { $dsl->app->send_file( $filename, filename => $filename, content_type => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ); } ); }
CUSTOM MAPPING
When you need some customization to your routes mapping, you can do it passing hash reference as second parameter to
OpenAPIRoutes([$debug, $castom_map])
. You can change mapping for HTTP method for all paths or only for specific ones like this:OpenAPIRoutes(1, {"get:/store/order/{orderId}" => "remove"});
(Very naughty joke): Instead of calling "fetch" for this specific path it will call "remove". The whole schema:
OpenAPIRoutes(1, {"$method[:$path]" => "[$function]:[$full::module::name]"});
like this:
OpenAPIRoutes(1, { "put" => "update", "post:/store/order" => "create_order", "post:/store/image" => "upload_image", # and so on ... });
AUTHOR
This module was written and is maintained by:
Anton Petrusevich
Module Install Instructions
To install Dancer2::Plugin::OpenAPIRoutes, copy and paste the appropriate command in to your terminal.
cpanm Dancer2::Plugin::OpenAPIRoutes
perl -MCPAN -e shell install Dancer2::Plugin::OpenAPIRoutes
For more information on module installation, please visit the detailed CPAN module installation guide.