The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Mojolicious::Plugin::REST2 - Mojolious::Plugin::REST2

VERSION

version 1.001

SYNOPSIS

    # In Mojolicious Application
    $self->plugin( 'REST' => { prefix => 'api', version => 'v1' } );

    $routes->rest_routes( name => 'account' );

    # Installs following routes:

    # /api/v1/accounts              ....  GET     "list_account()"    ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts              ....  POST    "create_account()"  ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId   ....  DELETE  "delete_account()"  ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId   ....  GET     "read_account()"    ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId   ....  PUT     "update_account()"  ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?
 
 
    $routes->rest_routes( name => 'account')->rest_routes( name => 'feature');

    # Installs following routes:
 
    # /api/v1/accounts                                  ....  GET       "list_account()"                  ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts                                  ....  POST      "create_account()"                ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId                       ....  DELETE    "delete_account()"                ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId                       ....  GET       "read_account()"                  ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId                       ....  PUT       "update_account()"                ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId/features              ....  GET       "list_account_feature()"          ^/api/v1/accounts/([^\/\.]+)/features
    # /api/v1/accounts/:accountId/features              ....  POST      "create_account_feature()"        ^/api/v1/accounts/([^\/\.]+)/features
    # /api/v1/accounts/:accountId/features/:featureId   ....  DELETE    "delete_account_feature()"        ^/api/v1/accounts/([^\/\.]+)/features/([^\/\.]+)
    # /api/v1/accounts/:accountId/features/:featureId   ....  GET       "read_account_feature()"          ^/api/v1/accounts/([^\/\.]+)/features/([^\/\.]+)
    # /api/v1/accounts/:accountId/features/:featureId   ....  PUT       "update_account_feature()"        ^/api/v1/accounts/([^\/\.]+)/features/([^\/\.]+)

    $routes->rest_routes( name => 'account')->rest_routes( name => 'feature')->rest_routes( name => 'other');
    .......
    .......

DESCRIPTION

Mojolicious::Plugin::REST2 adds various helpers for RESTful CRUD operations via HTTP to your mojolicious application.

As much as possible, it tries to follow RESTful API Design principles from Apigee.

"rest_routes" in Mojolicious::Plugin::REST2 shortcut could be used in conjuction with "data" in Mojolicious::Plugin::REST2 and "message" in Mojolicious::Plugin::REST2 helper etc, this module makes building RESTful application a breeze.

This module is inspired from Mojolicious::Plugin::REST. There are two reasons why I writed this module. One is that some function is not available such as 'under' parameter in "rest_routes" in Mojolicious::Plugin::REST due to the update of Mojolicious. Anther is that i want to make this module more convinient to use.

The most different between Mojolicious::Plugin::REST2 and Mojolicious::Plugin::REST is as below: 1. you could build a multilevel related routes more convenient and explicit, see example above. 2. you could use "data" in Mojolicious::Plugin::REST2 and "message" in Mojolicious::Plugin::REST2 etc helper rather than inheriting Mojolicious::Controller::REST. due to other functions are mostly similar, so I named this module Mojolicious::Plugin::REST2

NAME

Mojolious::Plugin::REST2 - Mojolicious Plugin for building RESTful routes

PLUGIN OPTIONS

prefix

If present, this value will be added as prefix to all routes created.

version

If present, this value will be added as prefix to all routes created but after prefix.

htt2crud

If present, given HTTP to CRUD mapping will be used to determine method names in controller. Default mapping:

    {
        collection => {
            get  => 'list',
            post => 'create',
        },
        resource => {
            get    => 'read',
            put    => 'update',
            delete => 'delete'
        }
    }

Routes shortcut

rest_routes

A routes shortcut to easily add RESTful routes and multilevel nested routes.

Following options can be used to control route creation:

methods

This option can be used to control which methods are created for declared rest_route. Each character in the value of this option, determined if corresponding route will be created or ommited(default:crudl). For Example:

    $routes->rest_routes( name => 'account', methods => 'crudl' );

This will install all the rest routes, value 'crudl' signifies:

    c - create
    r - read
    u - update
    d - delete
    l - list.

Only methods whose first character is mentioned in the value for this option will be created. For Example:

    $routes->rest_routes( name => 'account', methods => 'crd' );

This will install only create, read and delete routes as below:

    # /api/v1/accounts             ....  POST    "create_account()"  ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId  ....  DELETE  "delete_account()"  ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?
    # /api/v1/accounts/:accountId  ....  GET     "read_account()"    ^/api/v1/accounts/([^\/\.]+)(?:\.([^/]+)$)?

option value 'crd' signifies, c - create, r - read, d - delete

you could set current route a collection as below:

    # create a collection routes

    $routes->rest_routes( name => 'Account', methods => 'cl' ); # will install routes as below:

    # /api/v1/accounts  ....  GET   "list_account()"    ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts  ....  POST  "create_account()"  ^/api/v1/accounts(?:\.([^/]+)$)?

    # the subroutes below collection will install routes just like below:
    $routes->rest_routes( name => 'accout', method => 'lc')-> (name => 'feature', method => 'rl');
    # /api/v1/accounts                       ....  GET       "list_account()"            ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts                       ....  POST      "create_account()"          ^/api/v1/accounts(?:\.([^/]+)$)?
    # /api/v1/accounts/features              ....  GET       "list_account_feature()"    ^/api/v1/accounts/([^\/\.]+)/features
    # /api/v1/accounts/features/:featureId   ....  GET       "read_account_feature()"    ^/api/v1/accounts/([^\/\.]+)/features/([^\/\.]+)
name

The name of the resource, e.g. 'user'. This name will be used to build the route url as well as the controller name, which is case-insensitive.

controller

By default, resource name will be converted to CamelCase controller name. You can change it by providing controller name.

If customized, this options needs a full namespace of the controller class.

HELPERS

data

Sets the data element in 'data' array in JSON output. Returns controller object so that other method calls can be chained.

  $self->data( hello  => 'world' );
  # renders json response as:
  {
      "data":
      {
          "hello": "world"
      }
  }

  # chained to call message helper;
  $self->data( hello  => 'world' )->message('Something went wrong');
  # renders json response as:
  {
      "data":
      {
          "hello": "world"
      },
      "messages":
      [
          {
              "severity": "info",
              "text": "Something went wrong"
          }
      ]
  }

message

Sets an individual message in 'messages' array in JSON output. Returns controller object so that other method calls can be chained.

if the url you accessed is under '/prefix/version' but not exist, it's will render json = { data : {}, messages : [ {severity: 'error', text: 'route that you accessed is not exist'} ]

A custom severity value can be used by calling message as(default: 'info'):

  $self->message('Something went wrong', 'fatal');

  # renders json response as:
  {
      "messages":
      [
          {
              "text": "Something went wrong",
              "severity": "fatal"
          }
      ]
  }

message_warn

Similar to message, but with severity = 'warn'. Returns controller object so that other method calls can be chained.

AUTHOR

Yan Xueqing <yanxueqing621@163.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by Yan Xueqing.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.