Web-MREST-0.290 000755 001750 000144 0 14257045157 13455 5 ustar 00smithfarm users 000000 000000 Web-MREST-0.290/Build.PL 000444 001750 000144 5244 14257045157 15113 0 ustar 00smithfarm users 000000 000000 use 5.012000;
use strict;
use warnings;
use Module::Build;
my $builder = Module::Build->new(
module_name => 'Web::MREST',
license => 'bsd',
dist_author => q{Nathan Cutler },
dist_version_from => 'lib/Web/MREST.pm',
create_license => 0,
create_readme => 0,
release_status => 'stable',
share_dir => {
dist => [ 'config' ],
},
meta_merge => {
no_index => {
directory => [
"config"
]
}
},
script_files => [
'bin/mrest',
'bin/mrest-standalone',
],
configure_requires => {
'Module::Build' => 0,
},
build_requires => {
'App::CELL' => 0.209,
'Cwd' => 0,
'Encode' => 0,
'File::Basename' => 0,
'File::ShareDir' => 0,
'File::Spec' => 0,
'HTTP::Request' => 0,
'HTTP::Request::Common' => 0,
'JSON' => 0,
'LWP::UserAgent' => 6.05,
'LWP::Protocol::https' => 6.04,
'Module::Runtime' => 0,
'Params::Validate' => 0,
'Path::Router' => 0.12,
'Plack' => 1.0031,
'Plack::Test' => 0,
'Pod::Simple::HTML' => 0,
'Pod::Simple::Text' => 0,
'Test::Deep' => 0,
'Test::Fatal' => 0,
'Test::JSON' => 0,
'Test::More' => 0,
'Test::Warnings' => 0,
'Try::Tiny' => 0,
'URI::Escape' => 0,
'Web::Machine' => 0.15,
},
requires => {
'perl' => 5.012,
'App::CELL' => 0.209,
'Getopt::Long' => 2.32,
'Encode' => 0,
'File::ShareDir' => 0,
'File::Spec' => 0,
'HTTP::Request' => 0,
'HTTP::Request::Common' => 0,
'JSON' => 0,
'LWP::UserAgent' => 6.05,
'LWP::Protocol::https' => 6.04,
'Module::Runtime' => 0,
'Params::Validate' => 1.06,
'Path::Router' => 0.12,
'Plack::Middleware::LogErrors' => 0,
'Plack::Middleware::Session' => 0,
'Plack::Middleware::StackTrace' => 0,
'Plack::Runner' => 0,
'Pod::Simple::HTML' => 0,
'Pod::Simple::Text' => 0,
'Pod::Usage' => 0,
'Term::ReadLine' => 0,
'Test::Deep::NoTest' => 0,
'Try::Tiny' => 0,
'URI::Escape' => 0,
'Web::Machine' => 0.15,
'Web::MREST::CLI' => 0.276,
},
add_to_cleanup => [ 'Web-MREST-*' ],
# create_makefile_pl => 'traditional',
recursive_test_files => 1,
);
$builder->create_build_script();
Web-MREST-0.290/Changes 000444 001750 000144 50106 14257045157 15127 0 ustar 00smithfarm users 000000 000000 Revision history for Web::MREST
0.01 2014-12-19 21:01 CET
- basic module setup with code (mainly Resource.pm) taken from
App::Dochazka::REST version 0.356
- MREST.pm: write POD
0.02 2014-12-22 09:52 CET
- remove auto-generated build files that I committed accidentally
- MREST.pm: work on POD
- Resource.pm: get rid of is_authorized and associated routines
0.03 2014-12-22 16:03 CET
- start development
0.04 2014-12-23 11:42 CET
- rename from App::MREST to Web::MREST
- get t/503-Service-Unavailable.t to work as desired
0.05 2014-12-23 16:50 CET
- no longer dying in allowed_methods
0.06 2014-12-23 21:34 CET
- Build.PL: add Module::Runtime dependency
- MREST_Config.pm: add MREST_APPLICATION_MODULE
- dispatch_MetaConfig.pm: document format of resource definitions; re-structure
the resources to illustrate how individual resources can have subresources
for a tree structure; add MREST_ROOT_RESOURCE
- Resource.pm: fix bugs in resource initialization routines
- t/405-Method-Not-Allowed.t: now that allowed_methods is doing something, add
some tests
0.07 2014-12-29 15:39 CET
- bin/mrest: now takes app distro as parameter
- config/dispatch_MetaConfig.pm: minor fixes; add root resource definition
- MREST.pm: work on POD, make init take a PARAMHASH so application can
get its own meta and site parameters loaded
- Resource.pm: remove Clone dependency; adapt to flat structure of resource
definitions
- t/405-Method-Not-Allowed.t: fix tests
- t/method_not_allowed_override.t: demonstrate how a unit can define its own
resources and generate HTTP requests against them
0.08 2014-12-30 15:30 CET
- config/HTTP_Status_Message_en.conf: add HTTP status codes
- MREST.pm: work on POD
- Resource.pm: implement 'mrest_declare_error' method; use it in
allowed_methods; change all instances of $self->response->body to
$self->response->content; add error-handling code to 'finish_request' method;
start declaring HTTP errors using the new method
- Test.pm: in 'status_from_json' we call 'from_json' which might die - handle
this situation more gracefully
0.09 2014-12-30 18:35 CET
- implement malformed_request, is_authorized, forbidden
- rename "mrest_declare_error" to "mrest_declare_status" so we
can "declare" a successful status, too
- try to figure out why CLI parser dies when we return a "declared" 500 status
(something strange is afoot)
0.10 2014-12-31 09:54 CET
- add dispatch-specific config files and module
- bin/mrest: disable StackTrace middleware as it was making it difficult
to return sensible 500 error entities
- Resource.pm: turn warnings into errors; add 'mrest_resource_exists' method;
"GET bugreport" works
0.11 2014-12-31 16:11 CET
- bin/mrest: turn on Web::Machine tracing
- HTTP_Status_Message_en.conf: add 501
- MREST_Config.pm: support OPTIONS method
- get rid of bogus dispatch_Config.pm innards
- MREST.pm: work on POD
- Resource.pm: too much work to describe here
0.12 2014-12-31 23:24 CET
- Resource.pm: expand 'status_declared' method; work on 'malformed_request' method;
call handler in a try block
- config/MREST_Config.pm: expand supported options - break tests
- t/request_body_read.t: write what seem to be some sensible tests that pass
- t/: address some of the brokenness
0.13 2015-01-02 14:33 CET
- Util.pm: for pod_to_html
- Dispatch/Docu.pm: handlers for docu resources
- t/: new units t/resources/docu.t and t/4xx/415-Unsupported-Media-Type.t
- get HTML responses to work
- get docu resources to work
- MREST.pm: POD checked up to B5
- Dispatch.pm: add 'noop' handler
- Resource.pm: basic handling/checking of 'Content-Length' and 'Content-Type'
headers
0.14 2015-01-02 15:19 CET
- in valid_content_headers, actually check the headers against the valid
set (taken from RFC2616)
0.15 2015-01-03 22:15 CET
- handle and test 406 Not Acceptable
- work on POD
- take "content types provided" from configuration
0.16 2015-01-05 16:01 CET
- dispatch_MetaConfig.pm, Dispatch.pm: add 'test/post_is_create/:bool' resource
- MREST.pm: work on POD
- Resource.pm: implement 'post_is_create' and 'create_path' methods
- t/2xx/201.t: basic unit tests for 'post_is_create'
0.17 2015-01-06 08:28 CET
- resource handlers are now method names
- bin/mrest: take distro name and name of module to bless the application object into
- dispatch_MetaConfig.pm: work on documentation; remove module name from handler property;
generalize 'test' resource
- MREST.pm: work on POD
- Dispatch.pm: inherit from Web::MREST::Resource; work on 'echo' handler; generalize
'test' handler so it works for GET, POST, PUT and DELETE
- Resource.pm: execute handler via method call instead of function call
- Test.pm, t/: start adapting tests to current state
0.18 2015-01-06 13:44 CET
- add 'forbidden' resource and test for 403 Forbidden
- add site params to control "cache disablement" headers
- call handlers 'handler_foo' to distinguish them from resource names
- get rid of 'help' resource; rename 'not_implemented' to 'noop'
0.19 2015-01-07 16:38 CET
- work on POD
- change how resource handlers are called
- start adapting the resource handlers (WIP)
- debug Resources.pm (WIP)
0.20 2015-01-07 21:43 CET
- Resource.pm: call resource targets twice (once to determine resource
existence and a second time - as part of response generation - to get the
status)
- Dispatch.pm: adapt 'bugreport' and 'docu/..' resources to the latest change
in how resource targets are called
0.21 2015-01-08 09:49 CET
- add t/2xx/200-OK.t
- Dispatch.pm, Resource.pm: fix post_is_create, create_path
- Test.pm, t/: add low-level 'llreq' routine; make req use it
0.211 2015-01-10 08:28 CET
- standardize terminology ("request entity" instead of "request body")
- remove 'forbidden' resource definition and handler: they are not
necessary to test 403 Forbidden response
- add new modules that override 'forbidden' and 'is_authorized' methods
and associated unit tests
- work on POD
- clarify how resource_exists is supposed to work and adapt 'handler_test'
- Resource.pm: remove bogus forbidden handling code, clean up
'known_content_type', push content type onto context; add
'web_machine_metadata' accessor; work on process_post method
0.212 2015-01-12 09:01 CET
- Resource.pm: add 'documentation' to hard-coded list of not-to-be-expanded
properties
- Test.pm: make 'llreq' handle headers argument properly, including assigning
default headers if no arguments are provided
- t/: adapt tests in 2xx, 4xx, and 5xx to current code state
0.213 2015-01-12 16:00 CET
- config/: define resources in a site, rather than meta, config file
- MANIFEST: fix omissions
- Dispatch.pm: fix 'handler_echo'
- t/method_not_allowed_override.t: broken unit - skip it for now
0.214 2015-01-12 19:37 CET
- Resource.pm: split off init_router stuff into a separate module
- Test.pm: make req really use llreq; fix a warning
0.215 2015-01-13 08:53 CET
- Test.pm, t/: make initialize_unit take a PARAMHASH and prepare it to take a
sitedir option
0.216 2015-01-13 10:05 CET
- Resource.pm: split off "Web Services introduction" into a separate module
- MREST.pm: work on POD
0.217 2015-01-13 12:03 CET
- find and fix some lingering instances of 'request_body' (renamed to 'request_entity')
- t/dispatch/docu.t: 'documentation_format' property renamed to 'format'
- test suite running cleanly
0.218 2015-01-13 15:05 CET
- InitRouter.pm: take list of non-expandable properties from a config param
- MREST.pm: make 'init' take 'sitedir' property instead of inappropriately
named 'path'
- t/method_not_allowed_override.t: revive the unit
0.219 2015-01-14 06:20 CET
- dispatch_Config.pm: add 'docu/text' resource
- Dispatch.pm: resource handlers now called with ordinal number of pass - adapt
and clean up; make 'handler_param_get' handle second pass properly; in
'handler_docu', return 400 if request entity missing, improve error explanations;
adapt 'handler_echo' to current state
- Util.pm: fix a glaring oversight
0.220 2015-01-14 16:43 CET
- Build.PL, bin/mrest: use Plack::Middleware::LogErrors to redirect psgix.error
to our logger object
- Resource.pm: use the new 'get_acceptable_content_type_handler' method from
https://github.com/stevan/webmachine-perl/pull/32
0.221 2015-01-15 09:14 CET
- Dispatch.pm: have only one handler for all 'param/...' requests
- Resource.pm: add accessor for declared status code; add methods for running
request handler and response generator; make request handler call the
response generator; properly handle empty requests in request handler;
process_post just calls the _run_request_handler method; remove deprecated
web_machine_metadata method
0.222 2015-01-15 16:14 CET
- Resource.pm: clarify possible return values from request handler and response
generator; rearrange various routines so the order in which they appear in the
source file matches more closely the order in which requests propagate through
the FSM
0.223 2015-01-16 08:09 CET
- split off Entity.pm from Resource.pm
- MREST.pm: work on POD
- Resource.pm: provide a means to muffle debug-level log messages;
start organizing methods according to which "part" of the FSM they
belong to; move _make_json to Util.pm
0.224 2015-01-16 09:36 CET
- Entity.pm: add boilerplate
- Resource.pm: make 'context' initialize the context property, if needed, even
when called as an accessor; do not decode_utf8 the path_info for now
- Util.pm: use and export $JSON singleton; comment out 'make_json' routine as
it might not be needed
0.225 2015-01-16 11:28 CET
- dispatch_Config.pm, Dispatch.pm: allow DELETE method on 'param/...' resource
- Entity.pm: implement get_acceptable_content_type_handler method for which
patch is pending upstream; rationalize PUT/POST request processing
- Resource.pm: streamline process_post
0.226 2015-01-16 14:26 CET
- MREST_Config.pm: remove MREST_CONTENT_TYPES_PROVIDED
- Entity.pm: rename _render_response_html -> mrest_generate_response_html;
rename _render_response_json -> mrest_generate_response_json; add
generic mrest_generate_response method
0.227 2015-01-16 14:35 CET
- Resource.pm: include entity in responses to DELETE requests
0.228 2015-01-16 14:58 CET
t/dispatch/param.t: add test cases for 'param/...' resource
0.229 2015-01-16 15:33 CET
- Resource.pm: make declared status be an App::CELL::Status object
from the very beginning - this simplifies finish_request
- t/: adapt tests
0.230 2015-01-16 15:46 CET
- Resource.pm: make mrest_declare_status optionally take a ready-made
App::CELL::Status object
0.231 2015-01-16 16:02 CET
- t/dispatch/noop.t: add test cases for 'noop' resource
- dispatch_Config.pm: cleanup
- Dispatch.pm: fix up the 'handler_noop' method
0.232 2015-01-16 22:00 CET
- Dispatch.pm, t/dispatch/version.t: add handler and test cases for the
'version' resource
- MREST.pm: add a 'version' method to provide access to $VERSION package variable
0.233 2015-01-18 16:19 CET
- bring in CLI from App::Dochazka::CLI (0.076)
0.234 2015-01-18 23:09 CET
- dispatch_Config.pm: fix 'param/..' resource definition; make root handler
be 'handle_noop'
- InitRouter.pm: work on POD; find some kind of weird race condition - needs
a closer look
0.235 2015-01-20 07:22 CET
- Build.PL: add Web::MREST::CLI::Parser module directory and move
CLI configuration files to it
- bin/mrest-cli: re-enable logging, add some print statements for
better orientation, change prompt to Web::MREST::CLI::Parser
- config_cli/: log to mrest-cli.log in home directory
- CLI/UserAgent.pm: add some comments
- InitRouter.pm: add debug log messages
0.236 2015-01-20 17:53 CET
- Resource.pm, InitRouter.pm: get root resource to work
- t/dispatch/root_resource.t: tests for the root resource
0.237 2015-01-26 15:51 CET
- Test.pm: do not add content-length in llreq
- MREST.pm: work on POD
- bin/mrest-cli: load config parameters only once
0.238 2015-01-28 18:04 CET
- Build.PL, config/: consolidate server and CLI configuration files
- implement new 'configinfo' resource for displaying contents of
CELL_META_SITEDIR_LIST
0.239 2015-01-29 09:57 CET
- define root resource in (almost) the same way as all the other resources,
- the name of the root resource is '/'
- definitions of top-level resources must include parent => '/'
0.240 2015-01-29 14:42 CET
- Dispatch.pm: bring in resource definitions from dispatch_Config.pm,
and init_router function from InitRouter.pm
- eliminate all references to $meta->RESOURCES - this data is now stored in the
$resources package variable in InitRouter.pm
- remove obsoleted dispatch_Config.pm (integrate documentation into MREST.pm)
- t/: remove two units broken by this round of modifications
0.241 2015-01-29 17:43 CET
- 503.pm: add file needed for test
- Resource.pm: call init_router earlier
0.242 2015-01-30 07:50 CET
- CLI/UserAgent.pm: handle exceptions more gracefully
0.243 2015-02-02 10:11 CET
- bin/mrest: disable StackTrace by default since we are catching exceptions now
- bin/mrest-cli: tweak how responses are displayed
- InitRouter.pm: fix to handle case when a resource property is set to undef
- Resource.pm: when Web::Machine catches an exception, trigger a 500 and provide
a response entity with the text of the exception
0.244 2015-02-02 16:46 CET
- report HTTP method in declared statuses
- improve documentation of docu resource
0.245 2015-02-02 21:24 CET
- Resource.pm: add explicit 'create_path_after_handler' method
0.246 2015-02-03 07:24 CET
- Entity.pm: declare status when response generator is not OK
- InitRouter.pm: tweak log messages
0.247 2015-02-04 17:55 CET
- Resource.pm: be careful that create_path always returns a string
0.248 2015-02-11 10:18 CET
- Resource.pm: add 'nullify_declared_status' method
0.249 2015-02-11 14:04 CET
- Entity.pm: insert Location header only if resource does not exist
- Test.pm: put Location header in return value (App::CELL::Status object) so we
can test for it
- t/dispatch/param.t: test for correct response code (201 or 200) and Location
header in PUT requests that create/modify a resource; add more test cases
0.250 2015-02-12 07:32 CET
- InitRouter.pm: make debug message more useful
0.251 2015-02-12 09:19 CET
- CLI/UserAgent.pm: use URI::Escape to escape % characters
- Resource.pm: make 'mrest_declare_status' take optional 'args' property
so we can specify explanation as a message code
0.252 2015-02-16 21:45 CET
- InitRouter.pm: expand list of non-expandable properties
0.253 2015-02-17 18:25 CET
- MREST.pm: prep POD for release (WIP)
- CLI/Parser.pm: enable root resource
- MREST/Dispatch.pm: eliminate setting of 'resource_exists' in the response
generator as I am not sure if this is useful (needs more investigation)
0.254 2015-02-18 07:06 CET
- MREST.pm: mention 'curl' in SYNOPSIS
- Entity.pm: handle possible \415 from get_acceptable_content_type_handler
- Resource.pm: do not return scalar refs from 'process_post'
0.255 2015-02-18 07:25 CET
- MREST.pm: work on POD; fix syntax error
0.256 2015-02-18 08:44 CET
- implement normalize_filespec (in Util.pm) and use it to convert relative
paths to absolute
- eliminate all references to %ENV (for portability)
0.257 2015-02-18 16:46 CET
- work on POD
0.258 2015-02-21 08:09 CET
- CLI/UserAgent.pm: add 'http_code' property to return status object
0.259 2015-02-21 18:59 CET
- Resource.pm: make 'known_content_type' tolerate undefined/empty content type
0.260 2015-04-06 13:42 CEST
- Resource.pm: mrest_declare_status method could nominally take an
App::CELL::Status object, but this functionality was not tested and, of
course, didn't work properly -> fix
0.261 2015-04-06 14:59 CEST
- Resource.pm: refactor 'mrest_declared_status_code' accessor, add
'mrest_declared_status_explanation' and 'declared_status' accessors
- t/mrest_declared_status.t: add unit tests
0.262 2015-04-13 09:35 CEST
- tweak dependencies in an attempt to fix 'Can't locate object method "create"
via package "Plack::Test"' error in certain smoke tests
0.263 2015-04-13 10:06 CEST
- stop generating massive README, replace it with link to metacpan.org
0.264 2015-07-04 19:03 CEST
- bin/mrest: take local sitedir as a third argument
0.265 2015-07-04 19:59 CEST
- bin/mrest: really load the local site configuration directory
0.266 2015-07-04 20:17 CEST
- MREST.pm: make init() honor all parameters, instead of just one
0.267 2015-07-13 09:42 CEST
- Test.pm: make initialize_unit() more verbose
0.268 2015-07-13 09:45 CEST
- tweak release scripts
0.269 2015-07-16 11:45 CEST
- bin/mrest-cli: fix version number
0.270 2015-07-16 11:48 CEST
- Test.pm: make is_deeply check handle case when the value is undef?
0.271 2015-07-21 19:36 CEST
- Update copyright statement to 2015
- set $VERSION in top-level module only
- new release script
0.272 2015-07-22 14:42 CEST
- Make MREST_CLI_URI_BASE a meta param
- bin/mrest: take $VERSION from top-level module
0.273 2015-07-23 17:45 CEST
- Build.PL: require recent versions of LWP::UserAgent and LWP::Protocol::https
- No longer generate Makefile.PL
- UserAgent.pm: enable SSL connections
0.274 2015-07-25 11:49 CEST
- bin/mrest: use options instead of positional parameters
- release scripting modifications
- Build.PL: make LWP::Protocol::https a BuildRequires as well as a Requires
0.275 2015-07-26 21:21 CEST
- Add missing "use Pod::Usage" to bin/mrest
- Entity.pm: declare error statuses properly in mrest_generate_response_json()
(fixes Github issue #6)
- CLI/UserAgent.pm: in send_req(), be more careful when modifying the response
- Build.PL: add Cwd and File::Basename to BuildRequires
- bin/mrest-standalone: add wrapper for starting server in standalone mode
- update documentation of standalone mode in MREST.pm
0.276 2015-07-27
- Include descriptive text with DISPATCH_VERSION and MREST_CLI_SERVER_ERROR message codes
- Build.PL, MANIFEST.SKIP: release scripting modifications
- Test.pm: change diag() to note() in initialize_unit()
0.277 2015-07-28 17:09 CEST
- finish splitting off Web::MREST::CLI into a separate distro
- bin/mrest: import normalize_filespec() from Web::MREST::CLI::UserAgent
- Util.pm: drop normalize_filespec(); has been moved to Web::MREST::CLI
- lib/Web/MREST/: drop entire CLI/ subtree (just two files, actually)
- config/: drop all CLI-related files and keep server-related ones
- Build.PL: require Web::MREST::CLI >= 0.276
0.278 2015-07-30 14:29 CEST
- Early debugging feature
- MREST.pm: do not call $CELL->load() with debug_mode param
- bin/mrest: import normalize_filespec() from Web::MREST::CLI
0.279 2015-07-30 14:36 CEST
- bin/mrest: fix a silly typo
0.280 2015-08-05 15:35 CEST
- MREST.pm->init(): be more careful about early debugging filespec provided
by user
0.281 2015-07-11 12:07 CET
- config/: rename messages that might clash with application
- global: do not convert warnings into errors
- tests: use Test::Warnings to check for unexpected warnings
- update release and prerelease scripts
0.282 2016-01-02 01:17 CET
- bin/mrest: call app's init() function if it exists
0.283 2016-08-24 10:08 CET
- Display application module in HTML header, not Web::MREST
- add POD caveat: request entity not available until 2nd handler pass
- release.sh: automate attachment of version number to OBS commit
0.284 2016-07-31 20:07 CET
- Dispatch.pm: fix POD on _first_pass_always_exists
- bin/mrest: drop deprecated comments
- bin/mrest: document how to pass arguments to Plack::Runner
0.285 2016-09-05 09:02 CEST
- bin/mrest: comment out a useless message
- Travis CI
- Merge README files into single README.rst
- Add helper files for release automation scripting
0.286 2016-09-24 14:35 CEST
- Drop deprecated local release scripts
- cleanup: drop unused _get_sharedir() argument in bin/mrest
- cleanup: fix copyright header in bin/mrest
- Add get_session() function to Util.pm
0.287 2017-02-25 09:38 CET
- Refrain from munging Plack::Session object
- script: store sessions in a dedicated directory in /tmp
0.288 2017-10-16 22:17 CEST
- build/ops: require latest App::CELL
- Report MREST_DEBUG_MODE setting at startup
0.289 2022-06-29 14:46 CEST
- cleanup: tweak whitespace in copyright notices
- bootstrap: add (hopefully self-explanatory) bootstrap scripts
- doc: Web/MREST.pm: fix error in POD
- lib: update copyright year range in source files
- doc: MREST.pm: point readers to CLI documentation
0.290 2022-06-29 14:49 CEST
- MANIFEST.SKIP: do not include bootstrap scripts in Perl distro
Web-MREST-0.290/LICENSE 000444 001750 000144 3067 14257045157 14625 0 ustar 00smithfarm users 000000 000000 Copyright (c) 2014-2015, SUSE LLC
All rights reserved.
This is free software, licensed under:
The (three-clause) BSD License
The BSD License
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of SUSE LLC nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Web-MREST-0.290/MANIFEST 000444 001750 000144 2065 14257045157 14746 0 ustar 00smithfarm users 000000 000000 bin/mrest
bin/mrest-standalone
Build.PL
Changes
config/dispatch_Message_en.conf
config/favicon.ico
config/HTTP_Status_Message_en.conf
config/MREST_Config.pm
config/MREST_Message_en.conf
lib/Web/MREST.pm
lib/Web/MREST/Dispatch.pm
lib/Web/MREST/Entity.pm
lib/Web/MREST/InitRouter.pm
lib/Web/MREST/Resource.pm
lib/Web/MREST/Test.pm
lib/Web/MREST/Test/503.pm
lib/Web/MREST/Test/Forbidden.pm
lib/Web/MREST/Test/Unauthorized.pm
lib/Web/MREST/Util.pm
lib/Web/MREST/WebServicesIntro.pm
LICENSE
MANIFEST This list of files
META.json
META.yml
README.rst
t/2xx/200-OK.t
t/2xx/201-Created.t
t/4xx/400-Bad-Request.t
t/4xx/401-Unauthorized.t
t/4xx/403-Forbidden.t
t/4xx/405-Method-Not-Allowed.t
t/4xx/406-Not-Acceptable.t
t/4xx/413-Request-Entity-Too-Large.t
t/4xx/414-Request-URI-Too-Long.t
t/4xx/415-Unsupported-Media-Type.t
t/5xx/501-Not-Implemented.t
t/5xx/503-Service-Unavailable.t
t/config.t
t/dispatch/bugreport.t
t/dispatch/docu.t
t/dispatch/echo.t
t/dispatch/noop.t
t/dispatch/param.t
t/dispatch/root_resource.t
t/dispatch/version.t
t/mrest_declare_status.t
t/request_body_read.t
Web-MREST-0.290/META.json 000444 001750 000144 7421 14257045157 15237 0 ustar 00smithfarm users 000000 000000 {
"abstract" : "Minimalistic REST server",
"author" : [
"Nathan Cutler "
],
"dynamic_config" : 1,
"generated_by" : "Module::Build version 0.4224",
"license" : [
"bsd"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : "2"
},
"name" : "Web-MREST",
"no_index" : {
"directory" : [
"config"
]
},
"prereqs" : {
"build" : {
"requires" : {
"App::CELL" : "0.209",
"Cwd" : "0",
"Encode" : "0",
"File::Basename" : "0",
"File::ShareDir" : "0",
"File::Spec" : "0",
"HTTP::Request" : "0",
"HTTP::Request::Common" : "0",
"JSON" : "0",
"LWP::Protocol::https" : "6.04",
"LWP::UserAgent" : "6.05",
"Module::Runtime" : "0",
"Params::Validate" : "0",
"Path::Router" : "0.12",
"Plack" : "1.0031",
"Plack::Test" : "0",
"Pod::Simple::HTML" : "0",
"Pod::Simple::Text" : "0",
"Test::Deep" : "0",
"Test::Fatal" : "0",
"Test::JSON" : "0",
"Test::More" : "0",
"Test::Warnings" : "0",
"Try::Tiny" : "0",
"URI::Escape" : "0",
"Web::Machine" : "0.15"
}
},
"configure" : {
"requires" : {
"Module::Build" : "0"
}
},
"runtime" : {
"requires" : {
"App::CELL" : "0.209",
"Encode" : "0",
"File::ShareDir" : "1.00",
"File::Spec" : "0",
"Getopt::Long" : "2.32",
"HTTP::Request" : "0",
"HTTP::Request::Common" : "0",
"JSON" : "0",
"LWP::Protocol::https" : "6.04",
"LWP::UserAgent" : "6.05",
"Module::Runtime" : "0",
"Params::Validate" : "1.06",
"Path::Router" : "0.12",
"Plack::Middleware::LogErrors" : "0",
"Plack::Middleware::Session" : "0",
"Plack::Middleware::StackTrace" : "0",
"Plack::Runner" : "0",
"Pod::Simple::HTML" : "0",
"Pod::Simple::Text" : "0",
"Pod::Usage" : "0",
"Term::ReadLine" : "0",
"Test::Deep::NoTest" : "0",
"Try::Tiny" : "0",
"URI::Escape" : "0",
"Web::MREST::CLI" : "0.276",
"Web::Machine" : "0.15",
"perl" : "5.012"
}
}
},
"provides" : {
"Web::MREST" : {
"file" : "lib/Web/MREST.pm",
"version" : "0.290"
},
"Web::MREST::Dispatch" : {
"file" : "lib/Web/MREST/Dispatch.pm"
},
"Web::MREST::Entity" : {
"file" : "lib/Web/MREST/Entity.pm"
},
"Web::MREST::InitRouter" : {
"file" : "lib/Web/MREST/InitRouter.pm"
},
"Web::MREST::Resource" : {
"file" : "lib/Web/MREST/Resource.pm"
},
"Web::MREST::Test" : {
"file" : "lib/Web/MREST/Test.pm"
},
"Web::MREST::Test::503" : {
"file" : "lib/Web/MREST/Test/503.pm"
},
"Web::MREST::Test::Forbidden" : {
"file" : "lib/Web/MREST/Test/Forbidden.pm"
},
"Web::MREST::Test::Unauthorized" : {
"file" : "lib/Web/MREST/Test/Unauthorized.pm"
},
"Web::MREST::Util" : {
"file" : "lib/Web/MREST/Util.pm"
},
"Web::MREST::WebServicesIntro" : {
"file" : "lib/Web/MREST/WebServicesIntro.pm"
}
},
"release_status" : "stable",
"resources" : {
"license" : [
"http://opensource.org/licenses/bsd-license.php"
]
},
"version" : "0.290",
"x_serialization_backend" : "JSON::PP version 2.27400_02"
}
Web-MREST-0.290/META.yml 000444 001750 000144 4605 14257045157 15070 0 ustar 00smithfarm users 000000 000000 ---
abstract: 'Minimalistic REST server'
author:
- 'Nathan Cutler '
build_requires:
App::CELL: '0.209'
Cwd: '0'
Encode: '0'
File::Basename: '0'
File::ShareDir: '0'
File::Spec: '0'
HTTP::Request: '0'
HTTP::Request::Common: '0'
JSON: '0'
LWP::Protocol::https: '6.04'
LWP::UserAgent: '6.05'
Module::Runtime: '0'
Params::Validate: '0'
Path::Router: '0.12'
Plack: '1.0031'
Plack::Test: '0'
Pod::Simple::HTML: '0'
Pod::Simple::Text: '0'
Test::Deep: '0'
Test::Fatal: '0'
Test::JSON: '0'
Test::More: '0'
Test::Warnings: '0'
Try::Tiny: '0'
URI::Escape: '0'
Web::Machine: '0.15'
configure_requires:
Module::Build: '0'
dynamic_config: 1
generated_by: 'Module::Build version 0.4224, CPAN::Meta::Converter version 2.150010'
license: bsd
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: '1.4'
name: Web-MREST
no_index:
directory:
- config
provides:
Web::MREST:
file: lib/Web/MREST.pm
version: '0.290'
Web::MREST::Dispatch:
file: lib/Web/MREST/Dispatch.pm
Web::MREST::Entity:
file: lib/Web/MREST/Entity.pm
Web::MREST::InitRouter:
file: lib/Web/MREST/InitRouter.pm
Web::MREST::Resource:
file: lib/Web/MREST/Resource.pm
Web::MREST::Test:
file: lib/Web/MREST/Test.pm
Web::MREST::Test::503:
file: lib/Web/MREST/Test/503.pm
Web::MREST::Test::Forbidden:
file: lib/Web/MREST/Test/Forbidden.pm
Web::MREST::Test::Unauthorized:
file: lib/Web/MREST/Test/Unauthorized.pm
Web::MREST::Util:
file: lib/Web/MREST/Util.pm
Web::MREST::WebServicesIntro:
file: lib/Web/MREST/WebServicesIntro.pm
requires:
App::CELL: '0.209'
Encode: '0'
File::ShareDir: '1.00'
File::Spec: '0'
Getopt::Long: '2.32'
HTTP::Request: '0'
HTTP::Request::Common: '0'
JSON: '0'
LWP::Protocol::https: '6.04'
LWP::UserAgent: '6.05'
Module::Runtime: '0'
Params::Validate: '1.06'
Path::Router: '0.12'
Plack::Middleware::LogErrors: '0'
Plack::Middleware::Session: '0'
Plack::Middleware::StackTrace: '0'
Plack::Runner: '0'
Pod::Simple::HTML: '0'
Pod::Simple::Text: '0'
Pod::Usage: '0'
Term::ReadLine: '0'
Test::Deep::NoTest: '0'
Try::Tiny: '0'
URI::Escape: '0'
Web::MREST::CLI: '0.276'
Web::Machine: '0.15'
perl: '5.012'
resources:
license: http://opensource.org/licenses/bsd-license.php
version: '0.290'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
Web-MREST-0.290/README.rst 000444 001750 000144 2117 14257045157 15302 0 ustar 00smithfarm users 000000 000000 ==========
App::MREST
==========
.. image:: https://travis-ci.org/smithfarm/mrest.svg?branch=master
:target: https://travis-ci.org/smithfarm/mrest
.. image:: https://badge.fury.io/pl/App-MREST.svg
:target: https://badge.fury.io/pl/App-MREST
MREST stands for "minimalistic" or "mechanical" REST server. (Mechanical
because it relies on Web::Machine.)
Web::MREST provides a fully functional REST server that can be
started with a simple command. Without modification, the server provides a
set of generalized resources that can be used to demonstrate how the REST
server works, or for testing.
Developers can use Web::MREST as a platform for implementing
their own REST servers, as described below. App::Dochazka::REST
is one example of such a server.
For an introduction to REST and Web Services, see Web::MREST::WebServicesIntro.
Bootstrapping
=============
The process of "bootstrapping" MREST (successfully running it for the first time
from source) is documented in the bootstrap scripts included in the git repo.
Documentation
=============
See https://metacpan.org/pod/Web::MREST
Web-MREST-0.290/bin 000755 001750 000144 0 14257045157 14225 5 ustar 00smithfarm users 000000 000000 Web-MREST-0.290/bin/mrest 000444 001750 000144 17146 14257045157 15470 0 ustar 00smithfarm users 000000 000000 #!/usr/bin/perl
# *************************************************************************
# Copyright (c) 2014-2017, SUSE LLC
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
#
# Web::MREST server executable
#
# -------------------------------------------------------------------------
use 5.014;
use strict;
use warnings;
use App::CELL qw( $log $site );
use Web::MREST;
use Data::Dumper;
use File::Path qw( remove_tree );
use Getopt::Long;
use Log::Any::Adapter;
use Module::Runtime qw( is_module_name require_module );
use Plack::Builder;
use Plack::Runner;
use Plack::Session::Store::File;
use Pod::Usage;
use Try::Tiny;
use Web::Machine;
use Web::MREST::CLI qw( normalize_filespec );
=head1 NAME
mrest - Web::MREST server startup script
=head1 SYNOPSIS
Possible invocations (any options after C<--> are parsed by
L: basically, they can be anything accepted by C:
$ mrest --distro My-Distro --module My::Module
$ mrest -d My::Distro -m My::Module
$ mrest --distro My-Distro --module My::Module --sitedir /etc/my-module
$ mrest -d My::Distro -m My::Module -s /etc/my-module
$ mrest -- --server Starman
$ mrest --help
=head1 DESCRIPTION
Run this script from the bash prompt to start the server.
=head1 PASSING OPTIONS TO PLACK
This script starts the server by instantiates a L object and
calling its C method. Before doing that, it calls the C
method with C<@ARGV> as its argument. However, the script does so B
parsing its own options. Options intended to be parsed by L
should be placed at the end of the command line, preceded by C<-->.
=head1 DEBUGGING OPTIONS
You can include an C<--early-debug> option on the command line, with
the name of a file in which L will capture "early" log
messages -- i.e. all log messages generated before the "official" MREST
log file (i.e. the one defined in the site parameters) is known.
=head1 FUNCTIONS
=cut
sub _welcome_message {
my $message = "Starting Web::MREST ver. $Web::MREST::VERSION";
print "$message\n";
$log->notice( $message );
}
sub _get_sharedir {
my ( $distro, $module ) = @_;
# for distro, we allow both formats My::Distro and My-Distro
# distro might be just Foo, or Foo::Bar, or Foo-Bar
my @tmp_c;
if ( $distro =~ m/\:/ ) {
@tmp_c = split( '::', $distro );
} elsif ( $distro =~ m/\-/ ) {
@tmp_c = split( '-', $distro );
} else {
@tmp_c = ( $distro );
}
my $app_distro = join( '-', @tmp_c );
my $app_module = $module;
die "$app_module is not a module name" unless is_module_name( $app_module );
print "App distro is $app_distro\n";
print "App module is $app_module\n";
my $distro_sharedir;
my $status;
try {
$distro_sharedir = File::ShareDir::dist_dir( $app_distro );
print "Distro sharedir is $distro_sharedir\n";
} catch {
$status = "Could not find a sharedir for distro $app_distro: $_";
};
if ( $status ) {
die $status;
}
return ( $app_distro, $app_module, $distro_sharedir );
}
sub _load_config_params {
my ( $app_distro, $sitedir, $early_debug ) = @_;
print "Loading configuration parameters from $sitedir\n";
my $status = Web::MREST::init( distro => $app_distro, sitedir => $sitedir, early_debug => $early_debug );
die $status->text unless $status->ok;
}
sub _set_up_logging {
#print "Setting up logging\n";
my $log_file = normalize_filespec( $site->MREST_LOG_FILE );
my $should_reset = $site->MREST_LOG_FILE_RESET;
unlink $log_file if $should_reset;
Log::Any::Adapter->set( 'File', $log_file );
my $message = "Logging to $log_file";
print "$message\n";
print "MREST_DEBUG_MODE is set to " . ( $site->MREST_DEBUG_MODE || 0 ) . "\n";
$log->info( $message );
if ( ! $site->MREST_APPNAME ) {
die "Site parameter MREST_APPNAME is undefined - please investigate!";
}
$log->init(
ident => $site->MREST_APPNAME,
debug_mode => ( $site->MREST_DEBUG_MODE || 0 ),
);
}
sub function_exists {
no strict 'refs';
my $funcname = shift;
return \&{$funcname} if defined &{$funcname};
return;
}
sub _call_init {
my $app_module = shift;
require_module( $app_module );
if ( my $subref = function_exists( $app_module . "::init" ) ) {
print "Calling $app_module" . "::init()\n";
&$subref();
}
}
sub _init_webmachine {
my $app_module = shift;
print "Starting server\n";
return Web::Machine->new(
resource => $app_module,
tracing => 1,
)->to_app;
}
=head1 MAIN
=cut
_welcome_message();
# process command-line options
my $help = 0;
my $distro = '';
my $module = '';
my $sitedir = '';
my $early_debug = '';
GetOptions(
'distro|d=s' => \$distro,
'early-debug|e=s' => \$early_debug,
'help|?' => \$help,
'module|m=s' => \$module,
'sitedir|s=s' => \$sitedir,
);
pod2usage(1) if $help;
print "Early debug mode activated\n" if $early_debug;
# distro and module are required
die "You must specify at least --distro and --module (with values). Bailing out"
unless $distro and $module;
my ( $app_distro, $app_module, $distro_sharedir ) = _get_sharedir( $distro, $module );
print "Local site configuration directory is $sitedir\n" if $sitedir;
_load_config_params( $app_distro, $sitedir, $early_debug ); # initializes $site
_set_up_logging(); # needs $site
_call_init( $app_module );
my $app = _init_webmachine( $app_module );
my $runner = Plack::Runner->new;
$runner->parse_options(@ARGV);
remove_tree('/tmp/mrest-sessions');
mkdir '/tmp/mrest-sessions';
$runner->run(
builder {
enable "LogErrors", logger => sub {
my $args = shift;
my $level = $args->{'level'};
my $message = $args->{'message'};
$log->$level( $message );
};
# enable "StackTrace", force => 1;
# enable "Session", store => 'File';
enable "Session", store => Plack::Session::Store::File->new(
dir => '/tmp/mrest-sessions'
);
enable "Static", path => qr{/favicon}, root => $distro_sharedir;
$app;
}
);
Web-MREST-0.290/bin/mrest-standalone 000444 001750 000144 3527 14257045157 17574 0 ustar 00smithfarm users 000000 000000 #!/bin/sh
# *************************************************************************
# Copyright (c) 2014-2015-2015, SUSE LLC
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
#
# Web::MREST standalone server executable
#
# -------------------------------------------------------------------------
mrest --distro Web::MREST --module Web::MREST::Dispatch
Web-MREST-0.290/config 000755 001750 000144 0 14257045157 14722 5 ustar 00smithfarm users 000000 000000 Web-MREST-0.290/config/HTTP_Status_Message_en.conf 000444 001750 000144 4227 14257045157 22203 0 ustar 00smithfarm users 000000 000000 # *************************************************************************
# Copyright (c) 2014-2015-2015, SUSE LLC
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
# -------------------------------------------
# Web::MREST
# -------------------------------------------
#
# HTTP_Status_Message_en.conf
#
# Status codes for the various HTTP errors
# -------------------------------------------
200
OK
400
Bad Request
401
Unauthorized
403
Forbidden
404
Not Found
405
Method Not Allowed
406
Not Acceptable
413
Request Entity Too Large
414
Request-URI Too Long
415
Unsupported Media Type
500
Internal Server Error
501
Not Implemented
503
Service Unavailable
Web-MREST-0.290/config/MREST_Config.pm 000444 001750 000144 11113 14257045157 17611 0 ustar 00smithfarm users 000000 000000 # *************************************************************************
# Copyright (c) 2014-2017, SUSE LLC
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
# -------------------------------------------
# Web::MREST
# -------------------------------------------
#
# MREST_Config.pm
#
# WARNING: THIS FILE MAY CONTAIN PASSWORDS
# (restrictive permissions may be warranted)
# -------------------------------------------
# MREST_HOST
# the hostname (vhost) where REST server will listen on a part
set( 'MREST_HOST', 'localhost' );
# MREST_PORT
# the port where the REST server will listen
set( 'MREST_PORT', 5000 );
# MREST_LOG_FILE
# full path of log file to log to (in the user's home directory)
# If you don't want it in the user's home directory, specify an absolute
# path.
set( 'MREST_LOG_FILE', "mrest.log" );
# MREST_LOG_FILE_RESET
# should the logfile be deleted/wiped/unlinked/reset before each use
set( 'MREST_LOG_FILE_RESET', 1 );
# MREST_DOCUMENTATION_URI
# used in the "help"/"default" resources
set( 'MREST_DOCUMENTATION_URI', 'https://metacpan.org/pod/Web::MREST' );
# MREST_REPORT_BUGS_TO
# this should be an ordinary string like "bugs@dochazka.com" or
# "http://bugs.dochazka.com"
set( 'MREST_REPORT_BUGS_TO', 'bug-App-MREST@rt.cpan.org' );
# MREST_MAX_LENGTH_URI
# maximum length of a URI in bytes -- see Resource.pm->uri_too_long
set( 'MREST_MAX_LENGTH_URI', 1000 );
# MREST_MAX_LENGTH_REQUEST_ENTITY
# maximum length of request entity in bytes -- see Resource.pm->malformed
set( 'MREST_MAX_LENGTH_REQUEST_ENTITY', 10000 );
# MREST_APPNAME
# name of application (for logging) -- this can be set to any string, with
# the proviso that it should not contain ':' characters
set( 'MREST_APPNAME', 'Web-MREST' );
# MFILE_APPLICATION_MODULE
# the 'version' method of this module is called to get the version
# number returned by the 'version' resource
set( 'MREST_APPLICATION_MODULE', 'Web::MREST' );
# MREST_DEBUG_MODE
# determines whether or not debug- and trace-level messages are logged
set( 'MREST_DEBUG_MODE', 1 );
# MREST_SUPPORTED_HTTP_METHODS
# list of supported HTTP methods returned by the 'known_methods' method
# "HEAD" is omitted on purpose - see t/501-Not-Implemented.t
set( 'MREST_SUPPORTED_HTTP_METHODS', [ qw( GET PUT POST DELETE TRACE CONNECT OPTIONS ) ] );
# MREST_VALID_CONTENT_HEADERS
# list of valid content headers as per RFC2616
set( 'MREST_VALID_CONTENT_HEADERS', [ qw(
Encoding Language Length Location MD5 Range Type
) ] );
# MREST_SUPPORTED_CONTENT_TYPES
# list of supported content types (major portions only!)
set( 'MREST_SUPPORTED_CONTENT_TYPES', [
'application/json',
] );
# MREST_CACHE_ENABLED
# set to 0 to include response headers telling clients not to cache
set( 'MREST_CACHE_ENABLED', 0 );
# MREST_CACHE_CONTROL_HEADER
# value of 'Cache-Control' header used to disable caching
set( 'MREST_CACHE_CONTROL_HEADER', 'no-cache, no-store, must-revalidate, private' );
# -----------------------------------
# DO NOT EDIT ANYTHING BELOW THIS LINE
# -----------------------------------
use strict;
use warnings;
1;
Web-MREST-0.290/config/MREST_Message_en.conf 000444 001750 000144 5735 14257045157 20760 0 ustar 00smithfarm users 000000 000000 # *************************************************************************
# Copyright (c) 2014-2015-2015, SUSE LLC
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
# -------------------------------------------
# Web::MREST
# -------------------------------------------
#
# MREST_Message_en.conf
#
# status message codes and their respective texts
# -------------------------------------------
# MREST_RESPONSE_HTML
# what we display when we detect GET request from browser
# takes two arguments: $version_number and $response_entity
MREST_RESPONSE_HTML
%s
%s
Documentation:
https://metacpan.org/pod/App::Dochazka::REST
Report bugs to: bug-Web-MREST@rt.cpan.org
Copyright (C) 2014-2015, SUSE LLC
All rights reserved.
TEST_NON_EXISTENT_RESOURCE
The requested resource does not exist (%s)
Web-MREST-0.290/config/dispatch_Message_en.conf 000444 001750 000144 4425 14257045157 21660 0 ustar 00smithfarm users 000000 000000 # *************************************************************************
# Copyright (c) 2014-2015-2015, SUSE LLC
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
# -------------------------------------------
# Web::MREST
# -------------------------------------------
#
# dispatch_Message_en.conf - Status messages returned by handlers.
#
# -------------------------------------------
MREST_DISPATCH_BUGREPORT
See payload for bug reporting instructions
MREST_DISPATCH_CONFIGINFO
See payload for list of directories that App::CELL::Load scanned for configuration files
MREST_DISPATCH_ONLINE_DOCUMENTATION
See payload for the documentation you requested
MREST_DISPATCH_VERSION
See payload for the application and version currently running on the server
MREST_DISPATCH_NOOP
MREST_DISPATCH_NOOP
Web-MREST-0.290/config/favicon.ico 000444 001750 000144 2176 14257045157 17206 0 ustar 00smithfarm users 000000 000000 h ( ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ÿ ÿ ÿ1 ÿ1 ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ¯ ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ¯ ÿ1 ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ¯ ¯ ÿ1 ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿ ÿ1 ÿ1 ÿ1 ÿ ÿ ÿ1 ÿ1 ÿ1 ÿ ÿi ÿÿ ÿÿ ÿi ÿ ÿ1 ÿ1 ÿ1 ÿ ÿ ÿ1 ÿ1 ÿ1 ÿ ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ¯ ¯ ÿ1 ÿ1 ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ¯ ¯ ÿ1 ÿ1 ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿ1 ÿ1 ÿ1 ÿ1 ÿ ÿ ÿ1 ÿ1 ÿ1 ÿ1 ÿi ÿÿ ÿÿ ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿi ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ € ¿ý ¾} ¿Ý ¿½ ¿= ®u ®u ¾} ¾} ¿ý ¾} ¿ý € ÿÿ Web-MREST-0.290/lib 000755 001750 000144 0 14257045157 14223 5 ustar 00smithfarm users 000000 000000 Web-MREST-0.290/lib/Web 000755 001750 000144 0 14257045157 14740 5 ustar 00smithfarm users 000000 000000 Web-MREST-0.290/lib/Web/MREST.pm 000444 001750 000144 145027 14257045157 16376 0 ustar 00smithfarm users 000000 000000 # *************************************************************************
# Copyright (c) 2014-2022, SUSE LLC
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of SUSE LLC nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
package Web::MREST;
use 5.012;
use strict;
use warnings;
use App::CELL qw( $CELL $log $meta $core $site );
use App::CELL::Test qw( _touch );
use Data::Dumper;
use File::ShareDir;
use Log::Any::Adapter;
use Params::Validate qw( :all );
#use Try::Tiny;
use Web::Machine;
=head1 NAME
Web::MREST - Minimalistic REST server
=head1 VERSION
Version 0.290
=cut
our $VERSION = '0.290';
=head2 Development status
L is currently in "Alpha - feature freeze". There are almost
certainly bugs lurking in the code, but all features have been implemented.
=head1 SYNOPSIS
To take this module for a spin, execute this command:
$ mrest-standalone
Leave this running, and from another console start the command-line client:
$ mrest-cli
In the CLI client, type e.g.
Web::MREST::CLI::Parser> get /
A 'GET' request will be sent for the root resource and the CLI client
will display a representation of the response.
A similar result can be obtained using C:
curl -v http://localhost:5000/ -X GET -H "Content-Type: application/json"
For more information on using the CLI client, see L.
=head1 DESCRIPTION
MREST stands for "minimalistic" or "mechanical" REST server. (Mechanical because
it relies on L.)
L provides a fully functional REST server that can be started
with a simple command. Without modification, the server provides a set of
generalized resources that can be used to demonstrate how the REST server
works, or for testing.
Developers can use L as a platform for implementing their own
REST servers, as described below. L is a "real-world"
example of such a server.
For an introduction to REST and Web Services, see
L.
=head1 RFC2616 AS A STATE MACHINE
RFC2616 is, of course, the HTTP 1.1 standard - not a state machine. But
the authors of "Web Machine" (which was originally implemented in Erlang) had a
neat idea to represent it as a state machine and use this to implement a server
for providing web services.
L is, of course, the Perl port of Web Machine.
L relies on L to implement RFC2616. L
can be thought of as an additional abstraction layer over L.
By itself, L is not a server. It does not listen on a port, for
example. Instead, it is designed to work (via L) with a
L-compliant web server.
The web server hands incoming requests over to L, which runs the
requests through its state machine. (The L authors refer to the
state machine as "the FSM.") The best way to grasp the state machine is to
envision it as a flow-chart. At each "decision node" of the flow-chart - where
flow can go in one of two directions - L calls the method
corresponding to that node. Each node is designated by a letter and a number:
e.g. F7, O18, etc.
The flow-chart implemented by the FSM can be found L - you are
encouraged to have that open for reference while reading this documentation
and implementing your REST server.
=head1 SERVER STARTUP AND INHERITANCE SCHEME
=head2 Standalone mode
As stated above, L is capable of operating independently. To try
it out, start up the server like this:
$ mrest-standalone
And then point your browser to
http://localhost:5000
If you look inside the C script, you will see that it is
just a wrapper for the C script, which takes two mandatory options. The
first, C<--distro>, is the name of the distribution in whose sharedir it should
look for configuration files. The second, C<--module>, is the name of the
application's resource module, i.e. the ultimate module in the chain of
inheritance.
In standalone mode, the actual command that is run is:
mrest --distro=Web::MREST --module=Web::MREST::Dispatch
which causes the chain of inheritance to be built up as follows:
=over
=item C
calls C<< Web::Machine->new >>; the L object is blessed into L
=item L
inherits from L
=item L
inherits from L
=item L
inherits from L
=back
When you browse to C in standalone mode, you get a list of the
sample REST resources that are available. For more information on these, see
C.
=head2 With your application
Starting the server with your application is the same as described in
L<"Standalone mode">, above, except that you replace C with the name
of your distribution and C with the name of your ultimate
resource module.
$ mrest YourApp-MREST YourApp::MREST::Dispatch
For example, here we are starting the server with the distribution
C, which is presumed to implement a chain of inheritance
similar to L's, i.e.:
Web::MREST -> YourApp::MREST::Resource -> YourApp::MREST::Dispatch
Thanks to this arrangement, the application developer can customize
L - i.e., not only providing her own resources and handlers,
but even altering how the state machine operates, if necessary - by providing
her own chain of inheritance and overriding various methods within it.
=head3 Recapitulation
Since the above is quite important, let's go over it again:
The L documentation will always refer to your application either
as the "application" or as C. The application should take the form
of a Perl distribution, which should have:
=over
=item * a distribution sharedir
=item * a resource module, C.
=item * a dispatch module, C
=back
For now, just think of these three components as "black boxes". We will
cover their contents later.
The server (i.e. your application), is started by executing the C
executable with the name of your application's distribution and the name of its
dispatch module, which should be the ultimate module in the chain of
inheritance.
$ mrest --distro YourApp --module YourApp::Dispatch
Under the hood the startup script, which can be reviewed at C,
does essentially this:
use Web::Machine;
Web::Machine->new(
resource => 'YourApp::Dispatch',
)->to_app;
There are two key points concerning the L object constructed by
call to C<< Web::Machine->new >>:
=over
=item 1. the object is blessed into C
=item 2. the object is a L application
=back
=head1 INHERITANCE SCHEME
As seen in the previous section, C inherits from
L via a chain of inheritance. Here is the chain implemented by L:
-> Web::MREST::Dispatch
-> Web::MREST::Entity
-> Web::MREST::Resource
-> Web::Machine::Resource
-> Plack::Component
Assuming L has its authentication and authorization routines
in L and its resource definitions and handlers in
L, the chain for L would look like this:
-> YourApp::Dispatch
-> YourApp::Resource
-> Web::MREST::Entity
-> Web::MREST::Resource
-> Web::Machine::Resource
-> Plack::Component
(In other words, L and L replace
L, which is just a demo.)
When L reaches a given node in the FSM, it calls the
corresponding method on that L object. Since the object is
blessed into C, that module is where Perl will
start to look for the method.
If the method is not found at the lowest level, Perl follows the chain of
inheritance "upward". The highest level, L, is shown only for
completeness - L and L implement
all the methods that your resource module might (or should) want to override.
Readers who are not well-versed in writing Perl applications that use
inheritance are referred to the fine Perl manuals such as C.
=head1 STATE MACHINE INTRODUCTION
At this point we have enough background information to begin to grasp the state
machine. (Instead of writing "state machine" we will follow the L
convention of referring to it as the "FSM".) This section presents selected
features and nodes of the FSM, how L implements them, and how to
use them. The discourse proceeds in the order in which the methods are called
when an HTTP request enters the FSM. We can envision these method calls as
decision nodes of a flow-chart, or "cogs" of the FSM.
And we needn't just imagine the flow-chart - it actually exists and can be
downloaded from L<...>. If you want to understand how L and
L work, this document is of fundamental importance. Hereinafter
it will be referred to as "the FSM diagram".
As you can see in the FSM diagram, each FSM cog has a code like C, for ease
of reference.
=head1 POLICIES AND FEATURES
L implements the FSM, and that's all it does. In particular, it
imposes no policies on distributions that use it. By taking this approach,
L maximizes its range of potential uses.
Powerful as it is, L can be confusing to use. When I started
writing my first application based on it, I found myself wanting an
intermediate module between my application and L - something that
would make L a little more friendly.
L is that module. It builds on L in an effort to
provide certain additional features. Inevitably, this means imposing some
policies (i.e., limitations) on users. To me that seems like an acceptable
trade-off.
=head2 Path dispatch
A key part of any web application is "path dispatch" (i.e. URI translation),
which answers the question: "how are URIs mapped to resources?"
Although L provides a way to specify handlers for various media
types that may appear in request and response entities, it provides no
way of getting from the URI to the handler. L bridges this gap
by providing a system of resource definitions (see L<"Resource definitions">,
below).
The definition of each resource specifies the URI-to-resource mapping and
provides the name of the resource's handler method. Internally, L
uses a single L object to parse URIs.
Before any URIs can be parsed, this L object must be initialized.
This is done in L, in the C method.
That method checks the scalar variable that is supposed to contain the
L object and, if needed, calls the C method to
initialize it.
In the L demo application, C is implemented in
L.
=head2 Resource handlers
The L documentation mentions "handlers" but doesn't go into
any detail on how to write them. L not only provides some working
resource handlers, but also implements a paradigm for writing them.
In this paradigm, the handler is called as a method, just like any of the other
methods in the chain of inheritance. (To avoid namespace issues, it is
recommended that handler method names start with C.) The name of the
method is specified in the resource definition.
The handler method is called twice - in other words, there are two passes. In
the first pass, the handler is called with the argument C<1> (scalar value) and
is expected to return a boolean value indicating whether the resource exists.
In the second pass, indicated by the argument C<2> (scalar value), the handler
is expected to return a C object. This object (rendered in
JSON) becomes the response entity unless overrided by a declared status (see
C in L.
B The request entity is not available to the handler (via
C<$self->context->{request_entity}> until the second pass!
=head2 Status objects
As mentioned in the previous section, L objects are returned
by resource handlers. Not only that - L tries its best to I
return an L object in the response entity.
Actually, it is not the object itself that is returned, but a JSON
representation of its underlying data structure. From this, the object can
easily be reconstituted on the client side by doing
my $status = $JSON->decode( $response_entity );
bless $status, 'App::CELL::Status';
For more on what status objects can do, see L, L,
and L.
=head2 Error statuses
L always tries to return the proper HTTP status code in the
response. The application developer will likely need to "force" a code in
certain cases. For example, the request may be "malformed" in a way that is
not discoverable until the handler runs. Or, caught exceptions may need to be
exposed to the client with C<500 - Internal Error>.
Also, the RFC says
. . . the server SHOULD include an entity containing an explanation of the
error situation, and whether it is a temporary or permanent condition.
Clearly, then, a mechanism is needed for providing such explanations and
indicating whether the error is temporary or permanent. And that mechanism
should enable an arbitrary status code to be declared.
By itself, L does not really provide such a mechanism. What it
does provide is a mechanism for "forcing" an arbitrary status code (e.g. C<404
- Not Found>) by returning a scalar reference. This mechanism has two
disadvantages:
=over
=item it is only available at certain junctions of the FSM
I wanted a way to "declare" a status code at any point and be certain that
L won't change it later on.
=item there is no obvious way to provide an explanation of the error
L considers this an implementation detail.
=back
Hence, L provides the C method. To learn
how to call it and how it works, see L.
=head1 THE FINE STATE MACHINE
In this section we take a detailed look at the FSM by considering some common
scenarios. For our purposes these are C, C, C, and C
requests. Handling can differ according to whether or not a C creates a
new resource and whether or not the resource is determined to exist.
=head2 Part One (sanity checks and information gathering)
The first few cogs are executed, in the same order, on all requests regardless
of method. They can be thought of both as a set of sanity checks and as an
information-gathering process.
=head3 C (B13)
The first method call is C, which is implemented by
L and should I be implemented by your application,
because it calls C to ensure that all the resource definitions are
loaded and the L singleton is properly initialized.
This is not really a limitation, however. Whatever code you need to run here
can be placed in a method called C, which should
return a boolean value (i.e. 1 or 0), which determines the return value from
the method.
If the service really isn't available, you can return false, which will trigger
a C<503 Service Not Available> response. Before returning you should do:
$self->mrest_declare_status( explanation => '...', permanent => 0 );
to provide an explanation of what is going on.
For details, see the C unit test.
=head3 C (B12)
Returns the list of supported ("known") methods in
C<< $site->MREST_SUPPORTED_HTTP_METHODS >>. If the request method is not
in that list, a C<501 Not Implemented> response is returned along with
an explanation that the method requested is not supported.
If this behavior is not appropriate, the method can be implemented by the
application.
=head3 C (B11)
If the request URI is longer than the value set in the C site parameter,
the client will receive a C<414 Request URI Too Long> response.
To override this behavior, provide your own C routine in your
resource module.
This functionality is demonstrated by the C unit.
=head3 C (B10)
"Is the method allowed on this resource?"
This next routine is where things start to get complicated. According to the
L,
we are expected to respond with a list of methods allowed on the resource. To
assemble such a list, we must first answer two questions:
=over
=item 1. Have the resource definitions been loaded?
=item 2. Does the URI match a known resource?
=back
After the server starts, the first time this method is called triggers a
call to the C method, which populates the C<$resources> package
variable in C with all the resource definitions.
This is explained in detail in L<"Resource definitions">. This takes care of
the first question.
The second question is answered by C. Once the request has
been associated with a known resource, completing our task becomes a matter of
getting and returning the set of methods for which the resource is defined.
=head3 C (B9)
A true return value from this method triggers a "400 Bad Request" response
status. RFC2616 does not stipulate exactly what constitutes a bad request.
We already (in allowed_methods) took care of the case when the URI
fails to match a known resource, and that includes applying any C
properties from the resource definition.
So, in this method (or your overlay) we take the "next step" (whatever that is)
in vetting the request. Keep in mind that this method is called before
the resource handler. If you have any sanity checks you wish to apply _after_
the URI is matched to a resource but _before_ the resource handler fires, this
is the place to put them.
If you would like to keep L's implementation of this method
(which, for example, pushes the Content-Length and Content-Type information
onto the context) and add your own logic, you can put it in
C instead of overriding C itself.
If you intend to return false from this method you should first do this:
$self->mrest_declare_status( explanation => '...' );
to ensure that an explanation is included with the 400 response.
=head3 C (B8)
In my mind, "authentication" is the process of determining who the user
is, and "authorization" determines if the user is allowed to do what she
is asking to do. However, RFC2616 does not make such a clear distinction.
For that reason, it is left to the application to implement this method
if needed.
=head3 C (B7)
The same thoughts as expressed under C, above, apply to
this method as well.
=head3 C (B6)
This is where you vet the C headers in the request. If the
request contains any invalid C headers (i.e., if the '*' part
does not appear in << $site->MREST_VALID_CONTENT_HEADERS >>),
a 501 will be generated.
The content headers are passed to the method in a L
object.
=head3 C (B5)
If the C header is relevant - i.e., if this is a PUT or
POST request and if there is a request entity - check it against
<< $site->MREST_SUPPORTED_CONTENT_TYPES >>.
=head3 C (B4)
A simple routine that compares the entity length (in bytes) with the
maximum set in C<< $site->MREST_MAX_LENGTH_REQUEST_BODY >>.
=head3 C (B3)
If your application needs to support the C method, you should
implement this yourself - otherwise, ignore it.
=head2 Part Two (content negotioation)
The HTTP standard provides some complicated logic to enable clients
and servers to "negotiate" the format (media type), language, encoding,
etc. in which content will be passed back and forth. Here in the L
documentation we gloss over this complexity and focus only on the media type.
However, L includes methods for handling all the content
negotiation decision nodes and the application developer is free to take
advantage of them.
That said, L itself provides JSON handlers for both the request and
the response entities, and should be fully UTF-8 clean. Hopefully, this will
save application developers some work. (For more information, see L<"STATUS
OBJECTS AND ERROR HANDLING">.)
The following subsections detail the principal content negotiation methods.
=head3 C
As the L documentation states, this method must be
implemented (i.e., by the application) - otherwise, "your resource will not be
able to return any useful content".
Quoting further: "This should return an ARRAY of HASH ref pairs where the key
is the name of the media type and the value is a CODE ref (or name of a method)
which can provide a resource representation in that media type."
The implementation provided by L allows clients to specify (via
an C header) one of two media types:
=over
=item C
Since it is the first hashref pair of the two, it is the default. That means
if the incoming request does not have an C header, the handler
specified for C will be called to generate the response entity.
=item C
This is the media type that L was written to support, both in
request entities and in response entities. However, there is nothing preventing
you as the application developer from specifying handlers for other media types.
=back
If the request includes an C header, but none of the media types
specified in it are found in C, L will
generate a C<406 Not Acceptable> response. (Unfortunately, there is no easy way
for L or the application to know in advance that this error will be
triggered, so it will be returned "bare" - i.e., without any explanatory
response entity.)
In the normal case when an acceptable handler exists, it will be called to
generate the response - in other words, whatever is returned by the chosen
handler becomes the response entity, unless an error occurs inside the handler.
In that case, the handler should return a reference to a scalar value
(e.g., \400), which L will interpret as an HTTP response code.
See L<"STATUS OBJECTS AND ERROR HANDLING">.
For more on response entity generation, see the sections dedicated to the
various HTTP methods (L<"GET">, L<"PUT">, L<"POST">, L<"DELETE">), below.
=head3 C
When the client sends C or C requests, it will typically provide a
'Content-Type' header specifying the media type of the bytes it is sending in
the request body. This content type is compared with the media types returned
by this method. If there is no match, L returns a C<415
Unsupported Media Type> error response. (Unfortunately, there is no easy way
for L or the application to know in advance that this error will be
triggered, so it will be returned "bare" - i.e., without any explanatory
response entity.)
=head3 Other methods
For handling character sets, encodings, and languages, L provides
a number of other content negotiation methods:
=over
=item C
=item C
=item C
=item C
=item C
=back
However, they are only needed if the application does complex content
negotiation.
=head2 Part Three (resource existence)
When we have made it past content negotiation, we know more than just which
routines will be used to process the request entity (if any) and generate the
response. We have gathered quite a bit of information about the request. All
this information has been pushed onto the context, so it is available to all
our resource methods, including the resource handler which we will get to
presently. This information includes:
(FIXME: verify this list as it is outdated)
=over
=item C
The request method
=item C
The resource name, which can be used as a key to look up the full resource
definition in the C<< $Web::MREST::InitRouter::resources >>
=item C
The name of the resource handler, e.g. C. In L,
the resource handlers reside in the L module.
=item C
The full URI provided with the request
=item C
The base part of the URI (e.g. "http://localhost:5000/" )
=item C
The relative path to the resource (e.g. "/bugreport")
=item C
Reference to an array the elements of which are the individual 'components'
(i.e., everything between the '/' characters) of the C
=item C
A hashref mapping resource parameter names (if any) to their values
=item C
The content-length header.
=item C
The content-type header.
=back
One major piece of information is missing, however: whether the resource exists
or not. For that, we have to actually call the resource handler.
=head3 C (G7)
The term "resource" is not precisely defined. It can refer to the resource
definition (a data structure), the resource handler (a Perl subroutine called
as an object method), or an object (set of records) in an underlying database.
Or it can refer to all of the above, or to something else. The following
paragraphs describe L's approach.
By the time control reaches this method, the request URI has already been
matched to a resource definition. So the resource handler is known. Since we
have no other way of knowing, we ask the resource itself, by calling the
handler with the scalar value C<1> (i.e. the numeral 1) as the sole argument.
This handler call is referred to as the "first pass".
How the handler is implemented does not concern us. We only ask that it return
a boolean value (true or false) when called with this argument. If the return
value from the handler is true, we can assume that the handler will be called
again (second pass) in the response generation phase - read on.
=head2 Part Four (generation of response entity)
At this point we have
=over
=item gathered information about the request and placed it on the context
=item run the resource handler (first pass) to determine resource existence
=back
Up until now (i.e., through determination of resource existence), the FSM
has been a series of steps applied, in the same order, regardless of the
HTTP method.
In the sections below, we examine how responses are generated for each of
four HTTP methods (C, C, C, and C) when the resource
exists and when it doesn't exist.
=head3 Resource exists
=head4 C
=over
=item 1. C method call
First, C is called to determine the name of the
method that is capable of generating the response in the required format.
This method is the one we mean when we refer to the "response generator".
=item 2. Response generator method call
Second, the response generator is called (from C in
L). It is expected to always return an
L object. If an error condition is detected, the
handler should declare it using C<< $self->mrest_declare_status >>
and then return a "non_ok" status.
=back
C is the only request method that demands a response entity
in the format specified by the C header. For the other methods,
response entities are optional, but recommended. In practice, this
means that we have to create them ourselves.
=head4 C
Here we have two possible paths, depending on the value returned by
C:
=over
=item C true
=over
=item C and C
If, and only if, C is true, processing continues via
C and C. Depending on the value of the
latter, the request handler (determined by consulting
C) is called either before or after C.
The request handler should stage the response entity in preparation for
finalization. The content type can be inferred from
C<< $request->env->{'web.machine.context'} >>.
=item Finalization
Request is finalized by a call to C.
=back
=item C false
If C returns false, all bets are off. For reasons I do not
understand, L does not consult C or
C on this type of request. The only thing it does is
call C, and so it is up to this method to do whatever needs to be
done to generate an entity and get it into the response.
L helps by making sure that the content type is stored in the
context (in the C<'content_type'> property), so C can look
there for it and generate the response entity accordingly.
=back
=head4 C
On all C requests, and those C requests that are handled as
C requests (see above), L uses the following process:
=over
=item C
This method is called to determine the name of the method that can process
the request body. This method is expected not only to process the request
body, but also to generate the response. Therefore, we refer to this
method as the "response generator" for C requests.
=item Response generator method call
Next, the response generator is called. For C requests, the response
generator is determined from C based on the Here again, the method referred
to by C is not called by L, but the
response generator is free to call C and find
out the method itself, and call it. Or do something else.
When C is true, the response generator is called from C
in L.
=back
Whenever a new resource is created, a C header is added to
the response with the URI path of the new resource.
In general, we understand C to be a request to write to a resource.
Typically, this will involve either creating (INSERT) or modifying (UPDATE) one
or more database records/objects.
Therefore, it has to be possible for a URI to resolve to a resource that
does not yet exist. For example:
PUT employee/nick/Bubba
There may or may not be an employee by the name of Bubba in the database,
but if we have a resource called 'employee/nick/:nick', Path::Router will
match it in C and the resource handler will be called in
C - up until this point, the same sequence of method
calls is used for C, C, C, and C.
L has no way of knowing whether there is an employee named Bubba.
It is up to the handler to determine this, and then do an INSERT or UPDATE
operation as appropriate. This operation is not expected to fail, but if it
does fail the handler should force a 4xx or 5xx status code (and provide an
explanation) by calling C<< $self->mrest_declare_status >>.
If the request causes a new object - and, hence, a new resource - to be
created, the handler should cause a C header with the URI of the
new resource to be added to the response. This tells L to
set the response status to C<201 Created>.
If the request only modifies an existing object/resource, simply do not
add a C header to the response. This will cause L
to return a C<200 OK> status in the response.
=head4 C