NAME
Dancer2::Plugin::WebService - RESTful Web Services with login, sessions, persistent data, multiple input/output formats, and IP access
VERSION
version 4.1.5
SYNOPSIS
The replies through this module have the extra key error . At success error is 0 , while at fail is the error description
Built in routes
GET WebService
GET WebService/client
GET WebService/about
GET WebService/version
Your routes
POST AllKeys?to=yamk posted data {"k1":"v1"}
POST SomeKeys?to=xml posted data {"k1":"v1"}
POST login posted data {"username":"joe", "password":"souvlaki"}
POST LoginNeeded_store posted data {"token":"2d85b82b158e", "k1":"v1", "k2":"v2"}
POST LoginNeeded_delete posted data {"token":"2d85b82b158e"}
POST LoginNeeded_read posted data {"token":"2d85b82b158e"}
POST logout posted data {"token":"2d85b82b158e"}
Code example
package MyService;
use Dancer2;
use Dancer2::Plugin::WebService;
post '/AllKeys' => sub { reply posted_data };
post '/SomeKeys' => sub { reply posted_data('k1','k2') };
get '/data1' => sub { reply 'k1'=>'v1', 'k2'=>'v2' };
get '/data2' => sub { reply {'k1'=>'v1', 'k2'=>'v2'} };
any '/data3' => sub { my %H = posted_data('k1', 'k2');
reply 'foo'=> $H{k1}, 'boo'=>$H{k2}
};
get '/error' => sub { reply 'k1', 'v1', 'error', 'oups' };
any '/LoginNeeded_store' => sub { reply session_set('s1'=>'sv1', 's2'=>'v1') };
post '/LoginNeeded_delete'=> sub { reply session_del('s1', 's2') };
any '/LoginNeeded_read' => sub { reply session_get('s1', 's2') };
dance;
NAME
Dancer2::Plugin::WebService - Web Services with login, sessions, persistent data, multiple input/output formats, and IP access
VERSION
version 4.1.5
POLYMORPHISM
Define input/output format using the url parameters "to" and "from" . You can mix input/output formats independently. Supported formats are
json
xml
yaml
perl
human
If missing the default is the config.yml property
plugins :
WebService :
Default format : json
Examples
GET SomeRoute?to=human
GET SomeRoute?to=perl
POST SomeRoute?to=xml' posted data {"k1":"v1"}
POST SomeRoute?to=yaml' posted data {"k1":"v1"}
POST SomeRoute?to=perl' posted data {"k1":"v1"}
POST SomeRoute?from=json;to=human' posted data {"k1":"v1"}
POST SomeRoute?from=xml;to=human' posted data <Data><k1>v1</k1></Data>
POST SomeRoute?from=xml;to=yaml' posted data <Data><k1>v1</k1></Data>
ROUTES
Your routes can be either public or protected
public are the routes that anyone can use without login , Τhey do not support sessions / persistent data, but you can post and access data using the method posted_data
protected are the routes that you must provide a token, returned by the login route. At protected routes you can read, write, delete persistent data using the methods session_get , session_set , session_del
Persistent session data are auto deleted when you logout or if your session expired.
You can define a route as protected at the config.yml
plugins:
WebService:
Routes:
SomeRoute: protected
or at your application code
setting('plugins')->{'WebService'}->{'Routes'}->{'SomeRoute'} = 'protected';
BUILT-IN ROUTES
public informational routes
You can use "to" format modifiers if you want
GET WebService The available routes
GET WebService/about About
GET WebService/version Perl, Dancer2, WebService, apllication version
GET WebService/client Your client information
LOGIN
public route
Login to get a token for using protected routes and storing persistent data
POST login posted data {"username":"SomeUser","password":"SomePass"} e.g.
curl -X POST 0/login -d '{"username":"jonathan","password":"__1453__"}'
LOGOUT
protected route
If you logout your session and all your persistent data are deleted
POST logout posted data {"token":"SomeToken"} e.g
curl -X POST 0/logout --data '{"token":"a105076d9"}'
IP ACCESS
You can control which clients IP addresses are allowed to login by editing the file config.yml
The rules are checked from up to bottom until there is a match. If no rule match then the client can not login. At rules your can use the wildcard characters * ?
plugins:
WebService:
Allowed hosts:
- 127.*
- 10.*
- 192.168.1.23
- 172.20.*
- 32.??.34.4?
- 4.?.?.??
- ????:????:????:6d00:20c:29ff:*:ffa3
- "*"
SESSIONS
Upon successful login, client is in session until logout or get expired due to inactivity. In session you can use the session methods by providing the token you received.
Session persistent storage
You can change persistent data storage directory at the config.yml
plugins:
WebService:
Session directory : /var/lib/WebService
or at your main script
setting('plugins')->{'WebService'}->{'Session directory'} = '/var/lib/WebService';
Be careful this directory must be writable from the user that is running the service
Session expiration
Sessions expired after some seconds of inactivity. You can change the amount of seconds either at the config.yml
plugins:
WebService:
Session idle timeout : 3600
or at your main script
setting('plugins')->{'WebService'}->{'Session idle timeout'} = 3600;
METHODS
WebService methods for your main Dancer2 code
reply
public method
Send the reply to the client; it applies any necessary format convertions. This should be the last route's statement
reply only the error
reply k1 => 'v1', ... anything you want
reply( { k1 => 'v1', ... } ) anything you want
reply 'k1' The specific key and its value of the posted data
posted_data
public method
Get the data posted by the user
posted_data hash of all the posted data
posted_data('k1', 'k2'); hash of the selected posted keys and their values
session_get
session method
Read session persistent data
my %data = session_get; returns a hash of all keys
my %data = session_get( 'k1', 'k2', ... ); returns a hash of the selected keys
my %data = session_get(['k1', 'k2', ... ]); returns a hash of the selected keys
session_set session method
Store non volatile session persistent data;
You must pass your data as key / value pairs
session_set( 'rec1' => 'v1', 'rec2' => 'v2', ... );
session_set( { 'rec1' => 'v1', 'rec2' => 'v2', ... } );
It returns a document of the stored keys, your can use the url to=... modifier e.g.
{
"error" : 0,
"stored keys" : [ "rec1", "rec2" ]
}
session_del
session method
Deletes session persistent data
session_del; delete all keys
session_del( 'rec1', 'rec2', ... ); delete selected keys
session_del( [ 'rec1', 'rec2', ... ] ); delete selected keys
It returns a document of the deleted keys, your can use the url to=... modifier e.g.
{
"error" : 0,
"deleted keys" : [ "rec1", "rec2" ]
}
AUTHENTICATION
For using protected routes, you must provide a valid token received from the login route. The login route is using the the first active authentication method of the config.yml Authentication method can be INTERNAL or external executable Command.
At INTERNAL you define the usernames / passwords directly at the config.yml . The <any> means any username or password, so if you want to allow all users to login no matter the username or the password use
<any> : <any>
This make sense if you just want to give anyone the ability for persistent data
At production enviroments, for native Linux authentication mechanism, use the Command
MODULE_INSTALL_DIR/AuthScripts/LinuxNative.pl
If the user do not belong to any of the defined groups then the login will fail, even if the username and password are correct.
It is easy to write your own scripts for Active Directory, LDAP, facebook integration or whatever.
If the Command needs sudo, you must add the user running the WebService to sudoers
Please read the AUTHENTICATION_SCRIPTS for the details
A sample config.yml is the following.
version : 2.0.0
environment : development
plugins :
WebService :
Default format : json
Session directory : /var/lib/WebService
Session idle timeout: 86400
Routes :
INeedLogin_store : protected
INeedLogin_read : protected
route1 : public
route2 : public
mirror : public
Allowed hosts:
- 127.*
- 10.*
- 172.16.?.*
- 192.168.1.23
- "????:????:????:6d00:20c:29ff:*:ffa3"
- "*"
Authentication methods:
- Name : INTERNAL
Active : true
Accounts :
user1 : pass1
user2 : <any>
<any> : Secret4All
- Name : Linux native users
Active : false
Command : MODULE_INSTALL_DIR/AuthScripts/LinuxNative.pl
Arguments : [ ]
Groups : [root, glusterfs, ceph]
Use sudo : true
- Name : Basic Apache auth for simple users
Active : false
Command : MODULE_INSTALL_DIR/AuthScripts/HttpBasic.sh
Arguments : [ "/etc/htpasswd" ]
Groups : [ ]
Use sudo : false
INSTALLATION
You should run your service a non privileged user e.g. dancer
Create your application ( TestService ) e.g. at /opt/TestService/
dancer2 gen --application TestService --directory TestService --path /opt --overwrite
chown -R dancer:dancer /opt/TestService
Write your code at the file /opt/TestService/lib/TestService.pm
Configure your environment file
/opt/TestService/environments/development.yml
# logger : file, console
# log level : core, debug, info, warning, error
startup_info : 1
show_errors : 1
warnings : 1
no_server_tokens : 0
log : 'core'
logger : 'console'
engines:
logger:
file:
log_format : '{"ts":"%{%Y-%m-%d %H:%M:%S}t","host":"%h","level":"%L","message":"%m"}'
log_dir : '/var/log/WebService'
file_name : 'TestService.log'
console:
log_format : '{"ts":"%{%Y-%m-%d %H:%M:%S}t","host":"%h","level":"%L","message":"%m"}'
Start the service as user dancer
production
plackup --host 0.0.0.0 --port 3000 --server Starman --workers=5 --env production -a /opt/TestService/bin/app.psgi
development
plackup --host 0.0.0.0 --port 3000 --server HTTP::Server::PSGI --env development --Reload /opt/TestService/lib/TestService.pm,/opt/TestService/config.yml -a /opt/TestService/bin/app.psgi
plackup --host 0.0.0.0 --port 3000 -a /opt/TestService/bin/app.psgi
without Plack
perl /opt/TestService/bin/app.psgi
view the INSTALL document for details
SEE ALSO
Plack::Middleware::REST Route PSGI requests for RESTful web applications
Dancer2::Plugin::REST A plugin for writing RESTful apps with Dancer2
RPC::pServer Perl extension for writing pRPC servers
RPC::Any A simple, unified interface to XML-RPC and JSON-RPC
XML::RPC Pure Perl implementation for an XML-RPC client and server.
JSON::RPC JSON RPC 2.0 Server Implementation
COPYRIGHT AND LICENSE
This software is copyright (c) 2018 by George Bouras
It is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
AUTHOR
George Bouras <george.mpouras@yandex.com>
AUTHOR
George Bouras <george.mpouras@yandex.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2019 by George Bouras.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.