Revision history for Kelp 2.22 - 2025-06-12 [New Interface] - Added Kelp::Context::run_method method [Changes] - Fixed Kelp::Response::template error with custom controllers 2.21 - 2025-04-02 [Changes] - kelp-generator now checks whether package name is a valid Perl package name - Documentation improvements - Add an example script - perldoc.psgi 2.20 - 2025-03-30 [Changes] - Fixed value 0 being ignored during url building - Bad attempt to build an url will now always croak (instead of sometimes raising a warning and returning undef) * this breaking change is considered a bugfix, since the old behavior was surprising and inconsistent [Deprecations] - Removed deprecated json_param scalar context behavior (deprecated in 2.10) 2.19 - 2024-10-10 [New Interface] - Added middleware_obj attribute to Kelp - Added NEXT_APP method to Kelp - Added psgi_middleware attribute to Kelp::Routes::Pattern [Changes] - Middleware building is now done using Kelp::Middleware, making it easier to customize - Kelp now uses a dynamic PSGI execution chain, allowing adding PSGI middlewares at route level - Fixed trailing slash bridges not applying for deeper paths (broken in 2.18) 2.18 - 2024-10-08 [New Interface] - Added after_unrendered hook to Kelp - Added order attribute and compare method to Kelp::Routes::Pattern [Changes] - Fixed bridge without trailing slash being used for longer routes on the same level * bridge /admin will now work for /admin and /admin/x, but not for /admins - Hooks are now run conditionally on controller objects and fall back to main app object - Module should now report errors with more useful locations 2.17 - 2024-07-06 [Changes] - Fixed psgi routes not working with custom controllers - Documentation improvements 2.16 - 2024-07-05 [New Interface] - Added context_obj attribute to Kelp - Added build_context method to Kelp - Added build_controller method to Kelp::Context [New Documentation] - Kelp::Context package is now documented - Kelp::Manual::Controllers has a new section: 'Use different method than reblessing' [Changes] - Fixed incorrect before_finalize class if last handler to execute did not belong to a controller [Deprecations] - Clarify that new_anon will not be removed, but rather use different implementation method in the future 2.15 - 2024-07-03 [Changes] - Kelp's req and res attributes were moved to Context and are now just facade methods - Added persistent_controllers config, which makes the system keep the reblessed instances [Deprecations] - new_anon method of Kelp is now deprecated due to incompatibilities with controllers 2.14 - 2024-07-02 [Changes] - Fixed config files having incorrect line endings on Windows due to raw slurp - Fixed generation templates not handling UTF8 correctly [Tweaks] - Minimum version of Test::Deep was bumped to avoid Test::Deep::NoTest issue in tests 2.13 - 2024-07-01 [New Interface] - Kelp::Base can now be imported with -attr - Added content_type_is method to Kelp::Request - Added a couple of is_* methods to Kelp::Request to match Kelp::Response's interface * is_text, is_html and is_xml have been added - Added merge to Kelp::Util, which implements the merge algorithm used by config [Changes] - Kelp::Base no longer imports namespace::autoclean with -strict - Fixed camelizing of controller names if they don't contain a hash sign - Fixed config loading Test::Builder through Test::Deep - now uses Test::Deep::NoTest 2.12 - 2024-06-26 [Changes] - Kelp::Exception->throw now also works on objects (rethrows an exception) - Fixed installed config method not returning the default value - Fixed Kelp::Test being sensitive to utf8 configuration of the JSON encoder - Config module now allows overriding of the config merging routine 2.11 - 2024-06-25 [New Interface] - Added a second optional argument to set_content_type in Response, which sets charset [Changes] - Fixed incorrect reading of filehandles passed to template - Fixed load_package from Kelp::Util failing if package is loaded and not in a file matching its name - It is now easier to customize Kelp::Response render behavior - Added a cookbook example of extending request and response to automatically handle YAML 2.10 - 2024-06-24 [New Interface] - PSGI-compatible applications can now be mounted directly by using 'psgi' route flag - Added a bunch of new methods with suffix '_param' to Kelp::Request, which work like 'param' but fetch from specific place - Added charset, charset_decode methods to Kelp::Request - Added charset, charset_encode methods to Kelp::Response - Added is_production, get_encoder methods and request_charset, encoder_modules, context attributes to Kelp - Added Kelp::Module::Encoder, a base class for encoders (like JSON, to be used by the new get_encoder method) - Added adapt_psgi, effective_charset, charset_encode, charset_decode, load_package functions to Kelp::Util - Added a third, optional argument to camelize in Kelp::Util [General] - Fixed Route destination getting executed if a response was already rendered by a previous one * Rendering a response in a bridge will work the same as if the bridge returned a false value * If more than one normal routes were matched, they will be run until one of them renders or returns a defined value * Delayed responses will no longer override a previously rendered normal response * The destination will still be run if the render happened inside 'before_dispatch' hook - Response 'render' method will now assume you passed a json-encoded string if content type is json and body is not a reference * The json string will still get its charset encoded, so the encoder should be utf8-disabled - Kelp now tracks its context via 'context' attribute * App will now rememeber if it was reblessed and will only rebless once into given controller per request * This fixes before_finalize not working when reimplemented inside a controller * This also improves performance if a lot of bridges are defined as methods inside a controller - Fixed Kelp attribute 'charset' being readonly (was documented as read/write) - Fixed template bugs: * templates named '0' are now getting properly rendered * template is now correctly providing an 'app' object by default, with the correct rebless context * template now correctly rewinds a filehandle after reading from it, allowing reuse - Fixed ::Null modules containing testing behavior - now they really do nothing - Repeatedly fetching parameters from json request with the param method is now much faster - Kelp::Module::Logger now sorts keys in Data::Dumper output - Kelp can now be debugged using KELP_DEBUG environmental variable - Performance of accessors and request/response building was improved - 'Kelp' script has been renamed to 'kelp-generator' and documented - Documentation was vastly improved [Encoding] - Request data will now be properly decoded using either charset from Content-Type or request_charset * Request body parameters and content are automatically decoded * Path and query is automatically decoded, but always uses request_charset * Headers, cookies and sessions are unaffected (session encoding must be configured at the middleware level) * Explicitly setting request_charset to undef will disable all automatic decoding * Please use methods with prefix 'raw_' from Kelp::Request to access undecoded request data if needed * Not decoding input was a bug which needed to be fixed (the response was already being encoded correctly, so double encoding could happen) - Calling json and xml from Kelp::Response now also sets the charset in Content-Type header - Framework now internally uses a UTF8-disabled JSON encoder * The extra encoder will be created with the same options as the normal one, but without utf8 * It will no longer react to runtime changes in config of the main encoder * Application will now encode the JSON response manually using proper charset - Methods with prefix 'raw_' were added to Kelp::Request, returning undecoded request data (see "Bug fixes" below) [Configuration] - Added log_format, date_format configuration values to Kelp::Module::Logger - Added stdout configuration value to Kelp::Module::Logger::Simple - Added default_modes attribute and an optional argument for 'get' which will be the default value returned to Module::Config - Kelp::Module::Config method 'get' never croaks if the config value was not set at all - Application can be now configured to do no encoding of responses by setting 'charset' to undef - Application now has a second charset configuration used for requests: request_charset - Fixed Kelp::Module::Config::Less using the same reference for middleware and modules [Testing] - Kelp::Test no longer uses HTTP::Cookies, implements a much slimmer cookie jar with the same interface * The new cookie jar only stores key/value pairs without any special data for cookies like domains, paths or expiration dates - Kelp::Test now has a new import flag: '-utf8' * Importing with this flag will automatically set Test::More to encode wide characters on output - Added charset attribute to Kelp::Test - Added full_content_type_is and content_bytes_are methods to Kelp::Test [Deprecations] - Scalar context behavior of the param method called without arguments on json request is now deprecated * This is done in effort to make param method easier to use and harder to misuse [Backward-Incompatible Changes] - Application now tries to decode request data - see [Encoding] - Routes no longer allow regex unless the pattern is a Regexp object (qr//) * This was a result of a bug - they were never documented to support regex and would not build correctly with it * Any non-placeholder regex syntax is now correctly quoted and matched as text * This fix helps to avoid bugs which may cause serious issues, like pattern '/index.html' matching '/index/html' - Kelp::Exception no longer renders its body attribute, but instead logs it if it is present * Throwing Kelp::Exception now produces error template or plaintext response with proper HTTP status string * Log will happen at 'error' level, while regular errors are going to 'critical' * Status 500 exceptions will behave the same as errors - print their body on non-production * Rendering the body was dangerous as it could leak internal data if misused - Application main handler now clears all headers when an error or exception is caught * This fixes a class of bugs where content encoding of the error page was mismatching the rendered error [Tweaks] - 'kelp' template has been adjusted to match framework looks - Added a homepage on GitHub - Kelp now has a logo - Kelp is now developed by the Kelp-framework organization on GitHub 2.00 - 2024-06-10 [New Features] - Added a return value to 'add' method from Kelp::Routes, * it can be used to call add again, adding a child and making the parent a bridge - Added new placeholder to routes: >slurpy (a mix of optional + wildcard) - Added before_dispatch hook in Kelp - Added Kelp::Util, which contains some general utilities (previously as private code in Kelp::Routes) - Added has_name and dest methods to Kelp::Routes::Pattern - Kelp::Generator has a new filename shortcut: DOT (dotfiles support) [Changes] - Kelp::Routes module overhaul * Handles reblessing the app into a controller class by itself, with rebless => 1 * Kelp::Routes::Controller is no longer required, but will be kept for backward compatibility * Resolves all of its checks at application build time (not during the request dispatching) * Does stricter validation of routing configuration * Route building errors can now be turned into exceptions (rather than just being skipped), with fatal => 1 * Easier to subclass due to new overridable methods: format_to and load_destination * More performant at runtime, especially for deeply nested trees with many bridges - Removed safe_param configuration field, since param method is now safe by default - Improved the quality of configuration generated by the 'kelp' template [Backward-Incompatible Changes] - Disable unsafe param calls (cgi_param may be used instead if necessary) - Routes with invalid destinations will no longer be added and yield HTTP status 404 instead of 500 - Some specific extensions of Kelp::Routes may no longer work correctly due to stricter build-time route checks [Bug fixes] - Instances created with new_anon now have correct default 'base' for routes - Fixed bridge behavior in some cases by removing duplicated slashes from non-regex pattern - Fixed unnamed wildcard not being honored in non-regex patterns as documented - Fixed ?placeholder possibly matching other routes, for example '/not/?here' matching '/nothing' - Fixed *placeholder not honoring rules from checks while matching a pattern - Optional capture groups in custom-regex routes no longer produce a warning when not matched - Kelp::Generator now ignores empty lines in index files [Examples] - Added an example script for benchmarking router matching and dispatching speeds in ex/router_bench.pl 1.07 - 2024-06-02 [Changes] - Kelp::Routes now uses a dedicated method to build a pattern object 1.06 - 2022-05-09 [Changes] - Removed broken homepage link 1.05 - 2021-01-21 [New Features] - Added HTTP exceptions through Kelp::Exception [New Documentation] - Added Kelp::Generator [Changes] - Kelp::Module::JSON now uses JSON::MaybeXS - POD fixes and improvements 1.04 - 2021-01-18 [New Features] - Added new_anon constructor, allowing for multiple instances of an app - Added safe_param configuration - see Kelp::Request::param - Added Kelp::Generator, allowing for pluggable generation templates and custom generation scripts - Rewrote the CLI script using Kelp::Generator - Added a welcome HTML page to generated application listing registered routes and config [New Documentation] - Cookbook: template layouts - Cookbook: deploying [Changes] - List context Kelp::Request::param call with parameter now is deprecated without safe_param - Kelp::Module::JSON will now prefer Cpanel::JSON::XS before other options - Kelp script now requires --type=less for a Kelp::Less app, instead of --less - All of Kelp file slurping is now done using Path::Tiny - POD fixes and improvements [Bug fixes] - exception thrown during response JSON encoding with no explicit content_type will now show correct error cause 1.03 - 2021-01-11 [New Features] - Kelp::Request now holds the name of a route - Kelp script can now use tabs for indentation with --tabs flag [New Documentation] - Added Kelp::Manual - moved from old Kelp POD - Added Kelp::Manual::Cookbook [Changes] - POD fixes 1.02 - 2018-01-08 [Bug fixes] - clean namespace inside import, fix for Path::Tiny 1.01 - 2017-12-29 No changes. Stable version. 0.9091 - 2016-11-08 [Changes] - Change bridge error respose. Bridges will return 403 Forbidden (Konstantin Yakunin) - attr can be ether scalar, undef or CODEref but not HASHREF or ARRAYREF (Nikolay Mishin) - POD (Nikolay Mishin) 0.9071 - 2015-08-10 [Bug Fixes] - Bridges will correctly return 401 (instead of 500) when non existing location is accessed (Konstantin Yakunin) - Undefined value warning fixed. (Ben Hengst) - Correct handle errors on deployment and silence STDERR in Stack Trace tests (Konstantin Yakunin) [New Features] - New attributes request_obj and response_obj used to specify the name of the request and response classes. (Ben Hengst) 0.9051 - 2015-04-02 [Bug Fixes] - Stringify 500 errors avoiding the JSON-ification of returned structures and blessed objects. (basiliscos) - Increate the level of Test::Bulder in Kelp::Test, providing more relevant messages upon error. (basiliscos) - POD typos corrected [New Features] - Add json_content method to Kelp::Test, allowing for the testing of the returned JSON structure. - Abstract the initialization of the Config and Routes modules - More POD and examples added (roy-tate, Christian Froemmel, Perlover) 0.9021 - 2014-12-14 [Bug Fixes] - POD fixes [New features] - Session now accepts hashref, which also allows for the destruction of the enitire session. - Add "include" function to config files, making it possible to include other file into the configuration. 0.9015 - 2014-08-08 [Bug Fixes] - Fix a typo causing a fatal error in Routes::Controller - Fix debug and error keywords in Kelp::Less - Remove an explicit return undef, per Perl::Critic [New Features and Improvements] - Allow for route methods outside of base class It is now possible to add a route that lives outside of the base class by prefixing it with '+'. This works for both Perl and camelized strings. - Add config keyword to Kelp::Less - Virtualize the logger instantiation Add a _logger function in Module::Logger, which creates the logger instance, making it easier to subclass the Logger module. Add a Logger::Simple module, which dumps everything to STDERR This module is convenient to use during development with Kelp::Less. - Update bin/Kelp * bin/Kelp --less will now create a psgi file with the specified name (previously it would always create app.psgi). * Existing files will not be overwritten, unless --force specified. - Simplify Less application boilerplate Add a Config subclass with simplified configuration that will be used by default by any Kelp::Less application. This configuration will not load any modules or middleware, leaving it up to the user to manually load any modules needed. Additionally, bin/Kelp --less will now only generate the psgi application, and not any other folders, views, templates etc. - Downgrade confess to croak and croak to die Kelp::Response used confess and croak excessively. Both changed to die, so that the user can control how much stack trace they want via the 'long_error' attribute or the KELP_LONG_ERROR env variable. 0.9012 - 2014-07-12 [New features] - Add access to the application instance from the config files - Kelp.pm methods 'requiest' and 'response' renamed to 'build_request' and 'build_response', in order to minimize cofusion. NOTE: If your application is overriding any of those, make sure to rename them too. - Replace explicit UTF-8 encoding with $app->charset - Rename pattern attribute 'via' to 'method'. 'via' will still work as a shortcut to 'method', so this will not break backwards compatibility. [Fixes] - POD fixes [Other] - Using Pod::Markdown::Github to generate README.md from Kelp.pm 0.9001 - 2014-05-30 [Bug Fixes:] - Curly braces get stripped from pattern checks - Remove HTTP_X headers from Kelp::Request (security hole) [New features] - Allow for extending Kelp::Routes and using custom routers (Maurice Aubrey) - Create Kelp::Routes::Controller, which reblesses the web app into a controller class (Maurice Aubrey) - Set env KELP_CONFIG_WARN to warn for missing config files - Set rendered to true when redirecting (Julio Fraire) - Add request_ok method to Kelp::Test - Config module optionally registers _cfg method, to help manipulate the configuration. - Add a cookie jar to Kelp::Test 0.4602 - 2014-03-31 Replace $json->property with $json->get_utf8 in order to maintain compatibility across different JSON implementations 0.4601 - 2014-03-27 If no placeholders in route, param array should be empty (Maurice Aubrey) Move route cache to a CHI-like interface, in order to allow for custom cache modules Don't double encode JSON repsonse (Ruslan Zakirov) 0.4570 - 2014-03-02 Allow attributes to set undef values do not append default template extension if ext() is undef Added POD Added tests 0.4560 - 2013-11-19 Allow for fully qualified Kelp module names Config merge sigils will now only work for ARRAY POD and typo fixes 0.4550 - 2013-11-11 Flip nginx env vars. Change param to accept no JSON content or non-hash JSON Make Kelp::Test::request only load the PSGI app once POD and comments typo fixes 0.4501 - 2013-08-14 Minor fixes Add render_binary Add missing header_like POD changes 0.4011 - 2013-07-05 Removed modules_disable and middleware_disable, and added the ability to add and remove elements in an array by adding a '+' or '-' in front of the key name. 0.4001 - 2013-07-02 Added modules_disable and middleware_disable arrays in config Added a REMOTE_USER fallback for nginx Added loaded_modules attribute to Kelp Fixed utf8 encoding for OSX Added a session convenience method PSGI creation remodeled to leverage the StackTrace middleware Introduced render_error method in Kelp::Response, which will look for error templates (404, 500, etc) 0.3101 - 2013-06-13 Remove dependency of Template, replace it with Template::Tiny. Reason being that Template does not pass its tests under Perl 5.18. Use Kelp::Module::Template::Toolkit (available on CPAN) if your code depends on Template. 0.3001 - 2013-05-25 Fix typo in test paths Bridges accessed directly will now return 401 - Unathorized Introduce "panic" and "finalize" methods Add "long_error" attribute Rename "before_render" to "before_finalize" Change all _croak statements to return panic, improving the natural flow of the route logic 0.2191 - 2013-05-14 Add arguments to load_module Fix tests and small issues 0.2190 - 2013-05-05 Add property for partial rendering Address an issue with nginx and headers Add more pod 0.2182 - 2013-05-02 Fix issue with content-type params Set explicit utf8 encoding for module Template Replace wizardly Perl code with Class::Inspector 0.2181 - 2013-04-20 Fix test failing under Perl 5.10 0.218 - 2013-04-19 Add auto load class when adding a route. 0.217 - 2013-04-17 Fix Github issue #1 Revamp the Template module to allow for more standard subclassing Remove Config::Hash from test units 0.21 - 2013-04-16 Allow for using templates w/o extension. Allow for subclassing the templates module. Implement testing of a Less app, via the psgi attribute. 0.2 - 2013-04-13 Complete rewrite of the Config module, allow for subclassing of it. Write more tests. Write more POD. 0.1 - 2013-04-12 First upload to CPAN