Dancer Advent Calendar 2011 http://advent.perldancer.org/ Thanking the contributors http://advent.perldancer.org/2011/24 perl http://advent.perldancer.org/2011/24 Sat, 24 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="thanking_the_contributors"></a>Thanking the contributors</h1> <p>Dancer's success and growth so far would not have been possible without contributions from a growing community of helpful contributors.</p> <p>GitHub reports a current total of 70 individual contributors, but this of course does not count people who reported bugs / requested features / offered feedback.</p> <p>This article has been written to offer thanks to the developers who have contributed directly through GitHub, a brief summary of which is below, and to everyone who has contributed in any way, whether through helping out in the Dancer IRC channel, answering questions on the mailing list, presenting Dancer at various Perl events, generally promoting Dancer, and of course using Dancer to build fun stuff! :)</p> <p>So, a big thank you to everyone, and best wishes from the Dancer team for a very merry Christmas and a happy and prosperous New Year!</p> <h2><a name="2010_s_contributors_according_to_github"></a>2010's contributors according to GitHub</h2> <p>In no particular order, thanks go to:</p> <ul> <li><a name="item_Alexis_Sukrieh"></a><b>Alexis Sukrieh</b> <ul> <li><a name="item_Cleanup_session_tests_folder"></a><b>Cleanup session tests folder</b> </li> <li><a name="item_Cleanup_on_Dancer__FileUtils"></a><b>Cleanup on Dancer::FileUtils</b> </li> <li><a name="item_Documenting_the_plack_middlewares_map"></a><b>Documenting the plack_middlewares_map</b> </li> </ul> </li> <li><a name="item_Sawyer_X"></a><b>Sawyer X</b> <ul> <li><a name="item_GH__391__Dancer__Logger__Note_now_exists_"></a><b>GH #391: Dancer::Logger::Note now exists.</b> </li> <li><a name="item_Porting_documentation_on_WRAPPER_to_Dancer__Template__TemplateToolkit_"></a><b>Porting documentation on WRAPPER to Dancer::Template::TemplateToolkit.</b> </li> <li><a name="item_GH__297__All_logging_options_can_automatically_serialize_references_"></a><b>GH #297: All logging options can automatically serialize references.</b> </li> <li><a name="item_GH_303__Generated_Makefile_PL_s_clean_is_done_correctly_now_"></a><b>GH#303: Generated Makefile.PL's clean is done correctly now.</b> </li> </ul> </li> <li><a name="item_Alberto_Sim&#xf5;es"></a><b>Alberto Sim&#xf5;es</b> <ul> <li><a name="item_Detected_errors_in_scaffolded_dispatchers"></a><b>Detected errors in scaffolded dispatchers</b> </li> <li><a name="item_Support_XML__Simple_configuration_for_serializing_deserializing"></a><b>Support XML::Simple configuration for serializing/deserializing</b> </li> <li><a name="item_Remove_hard_coded_version_from_404_html_and_500_html"></a><b>Remove hard-coded version from 404.html and 500.html</b> </li> <li><a name="item_Fix_a_bunch_of_cpan_testers_reports"></a><b>Fix a bunch of cpan testers reports</b> </li> </ul> </li> <li><a name="item_David_Precious"></a><b>David Precious</b> <ul> <li><a name="item_Make_template_work_outside_of_requests__Issue_592_"></a><b>Make template work outside of requests (Issue 592)</b> </li> <li><a name="item_Major_rewrite_reorganization_on_Dancer__Config_documentation"></a><b>Major rewrite/reorganization on Dancer::Config documentation</b> </li> <li><a name="item_Added_Dancer__Cookbook_to_provide_lots_of_concrete_examples_for_newcomers_"></a><b>Added Dancer::Cookbook to provide lots of concrete examples for newcomers.</b> </li> <li><a name="item_Added_session_backend_Dancer__Session__Simple"></a><b>Added session backend Dancer::Session::Simple</b> </li> </ul> </li> <li><a name="item_Damien_Krotkine"></a><b>Damien Krotkine</b> <ul> <li><a name="item_Created_continuations_style_exception_system_"></a><b>Created continuations-style exception system!</b> </li> <li><a name="item_Implement_session_directory_testing_cache_for_Session__YAML"></a><b>Implement session directory testing cache for Session::YAML</b> </li> <li><a name="item_Improve_Serializers_documentation"></a><b>Improve Serializers documentation</b> </li> </ul> </li> <li><a name="item_Michael_G__Schwern"></a><b>Michael G. Schwern</b> <ul> <li><a name="item_Improve_Dancer__Test_so_failures_report_the_correct_line_numbers_"></a><b>Improve Dancer::Test so failures report the correct line numbers.</b> </li> <li><a name="item_Tested_that_Dancer__Session__Cookie_isn_t_broken"></a><b>Tested that Dancer::Session::Cookie isn't broken</b> </li> <li><a name="item_Fixed_the_plack_middlewares_example_in_the_cookbook"></a><b>Fixed the plack_middlewares example in the cookbook</b> </li> </ul> </li> <li><a name="item_Philippe_Bruhat__BooK_"></a><b>Philippe Bruhat (BooK)</b> <ul> <li><a name="item_Added_script_wallflower__helper_to_turn_a_Dancer_application_into_a_static_web_site_"></a><b>Added script/wallflower, helper to turn a Dancer application into a static web site.</b> </li> <li><a name="item_better_behaviour_for_plugin_setting__better_search__more_user_friendly_"></a><b>better behaviour for plugin_setting (better search, more user-friendly)</b> </li> </ul> </li> <li><a name="item_Naveed_Massjouni"></a><b>Naveed Massjouni</b> <ul> <li><a name="item_default_layout_uses__lt___request_base___gt__in_order_to_support_mounted_apps"></a><b>default layout uses &lt;% request.base %&gt; in order to support mounted apps</b> </li> <li><a name="item_FIX_for_issues__111_and__108"></a><b>FIX for issues #111 and #108</b> </li> </ul> </li> <li><a name="item_Maurice"></a><b>Maurice</b> <ul> <li><a name="item_Provided_documentation_for_Dancing_on_command_line_"></a><b>Provided documentation for Dancing on command line.</b> </li> <li><a name="item_Improve_Dancer__Cookbook_"></a><b>Improve Dancer::Cookbook.</b> </li> </ul> </li> <li><a name="item_Roman_Galeev"></a><b>Roman Galeev</b> <ul> <li><a name="item_YAML_Session_UTF_8_Fix"></a><b>YAML Session UTF-8 Fix</b> </li> <li><a name="item_Introduce_new_timestamp_format_in_logger___T_"></a><b>Introduce new timestamp format in logger (%T)</b> </li> </ul> </li> <li><a name="item_Stefan_Hornburg__Racke_"></a><b>Stefan Hornburg (Racke)</b> <ul> <li><a name="item_POD_fix_"></a><b>POD fix.</b> </li> </ul> </li> <li><a name="item_Yanick_Champoux"></a><b>Yanick Champoux</b> <ul> <li><a name="item_Changed_Dancer__Test_tests_to_assume__GET__if_their_first_argument_is_scalar_"></a><b>Changed Dancer::Test tests to assume 'GET' if their first argument is scalar.</b> </li> <li><a name="item_Recognize_absolute_redirects"></a><b>Recognize absolute redirects</b> </li> <li><a name="item_Fix_before_serializer_POD_fix"></a><b>Fix before_serializer POD fix</b> </li> </ul> </li> <li><a name="item_Anirvan_Chatterjee"></a><b>Anirvan Chatterjee</b> <ul> <li><a name="item_Provided_various_documentation_typo_fixes"></a><b>Provided various documentation typo fixes</b> </li> </ul> </li> <li><a name="item_James_Aitken"></a><b>James Aitken</b> <ul> <li><a name="item_Fixed_issues_GH__84__86_and__87"></a><b>Fixed issues GH #84 #86 and #87</b> </li> </ul> </li> <li><a name="item_Rowan_Thorpe"></a><b>Rowan Thorpe</b> <ul> <li><a name="item_Fixed_anti_UNC_substitution_under_Cygwin"></a><b>Fixed anti UNC substitution under Cygwin</b> </li> <li><a name="item_GH_220__fix_for_path_issues_under_MacOS_X_and_Windows_platforms_"></a><b>GH#220: fix for path issues under MacOS X and Windows platforms.</b> </li> <li><a name="item_Better_detection_of_the_application_layout_under_non_UNIX_platforms_"></a><b>Better detection of the application layout under non-UNIX platforms.</b> </li> <li><a name="item_Set_binmode_in_write_data_to_file___to_fix_image_corruption_in_______Windows"></a><b>Set binmode in write_data_to_file() to fix image corruption in Windows</b> </li> </ul> </li> <li><a name="item_Geistteufel"></a><b>Geistteufel</b> <ul> <li><a name="item_Fixed_cookies_disappearing_when_more_than_one_is_set________Complete_refactoring_of_the_cookie_handling_"></a><b>Fixed cookies disappearing when more than one is set. Complete refactoring of the cookie handling.</b> </li> <li><a name="item_Documented_a_complete_working_example_of_deployment_under_Nginx_Starman_in_______Deployment_pod"></a><b>Documented a complete working example of deployment under Nginx/Starman in Deployment.pod</b> </li> </ul> </li> <li><a name="item_Paul_Driver"></a><b>Paul Driver</b> <ul> <li><a name="item_Provided_support_for_virtual_location_"></a><b>Provided support for virtual location.</b> </li> </ul> </li> <li><a name="item_Gabor_Szabo"></a><b>Gabor Szabo</b> <ul> <li><a name="item_Eliminated_test_warnings_on_Windows_"></a><b>Eliminated test warnings on Windows.</b> </li> <li><a name="item_Adding_test_for_multi_leveled_scaffolding_"></a><b>Adding test for multi-leveled scaffolding.</b> </li> </ul> </li> <li><a name="item_Alex_Kalderimis"></a><b>Alex Kalderimis</b> <ul> <li><a name="item_Documentation_and_tests_on_how_to_use_many_Dancer_application_______inside_one_PSGI_file__PR_564_"></a><b>Documentation and tests on how to use many Dancer application inside one PSGI file (PR 564)</b> </li> <li><a name="item_Documentation_and_tests_on_how_to_use_many_Dancer_application_______inside_one_PSGI_file__PR_564_"></a><b>Documentation and tests on how to use many Dancer application inside one PSGI file (PR 564)</b> </li> </ul> </li> <li><a name="item_felixdo"></a><b>felixdo</b> <ul> <li><a name="item_Fixed_a_bug_that_made_system___fail_with__1_under_Dancer"></a><b>Fixed a bug that made system() fail with -1 under Dancer</b> </li> </ul> </li> <li><a name="item_chromatic"></a><b>chromatic</b> <ul> <li><a name="item_Cleaned_up_PSGI_handler_code"></a><b>Cleaned up PSGI handler code</b> </li> <li><a name="item_Improved_warning_localizations"></a><b>Improved warning localizations</b> </li> </ul> </li> <li><a name="item_minty"></a><b>minty</b> <ul> <li><a name="item_Bump_HTTP__Body_dependency_to_1_07"></a><b>Bump HTTP::Body dependency to 1.07</b> </li> <li><a name="item_Updated_Introduction_pod_with_a_dancer_opt"></a><b>Updated Introduction pod with a dancer opt</b> </li> </ul> </li> <li><a name="item_Squeeks"></a><b>Squeeks</b> <ul> <li><a name="item_The_ability_for_dancer_response_to_send_file_contents_for_file_uploads_______as_a_scalar__instead_of_reading_from_file_on_disk"></a><b>The ability for dancer_response to send file contents for file uploads as a scalar, instead of reading from file on disk</b> </li> <li><a name="item_Providing_a_report_about_Query_string_params"></a><b>Providing a report about Query string params</b> </li> </ul> </li> <li><a name="item_Mark_Stosberg"></a><b>Mark Stosberg</b> <ul> <li><a name="item_Provided_a_report_on_CRLF_injection_in_response_headers"></a><b>Provided a report on CRLF injection in response headers</b> </li> <li><a name="item_Provided_a_report_on_multi_valued_params_in_GET_POST_data"></a><b>Provided a report on multi-valued params in GET/POST data</b> </li> </ul> </li> <li><a name="item_Nate_Jones"></a><b>Nate Jones</b> <ul> <li><a name="item_More_HTTP_codes_supported_for_a_better_REST_compat"></a><b>More HTTP codes supported for a better REST compat</b> </li> <li><a name="item_Thing_2"></a><b>Thing 2</b> </li> </ul> </li> <li><a name="item_niko"></a><b>niko</b> <ul> <li><a name="item_Cookie_accessor_to_manipulate_cookies_directly_"></a><b>Cookie accessor to manipulate cookies directly.</b> </li> </ul> </li> <li><a name="item_Pedro_Melo"></a><b>Pedro Melo</b> <ul> <li><a name="item_Tweak_tests_regular_expression_to_be_more_flexible"></a><b>Tweak tests regular expression to be more flexible</b> </li> <li><a name="item_Fix_hooks_implementation_that_failed_when_user_messes___"></a><b>Fix hooks implementation that failed when user messes $_</b> </li> </ul> </li> <li><a name="item_Ask_Bj&#xf8;rn_Hansen"></a><b>Ask Bj&#xf8;rn Hansen</b> <ul> <li><a name="item_In_development__pretty_print_JSON_serializations_for_easier_development"></a><b>In development, pretty-print JSON serializations for easier development</b> </li> </ul> </li> <li><a name="item_Sebastian_de_Castelberg"></a><b>Sebastian de Castelberg</b> <ul> <li><a name="item_Allowed_the_dancer_helper_to_download_files_via_a_transparent_proxy"></a><b>Allowed the dancer helper to download files via a transparent proxy</b> </li> <li><a name="item_Support_for_path_info___in_Dancer__Request_so_it_s_possible_to_mount_an_application_under_a_directory_"></a><b>Support for path_info() in Dancer::Request so it's possible to mount an application under a directory.</b> </li> <li><a name="item_Fixed_priority_in_D__S__Mutable_"></a><b>Fixed priority in D::S::Mutable.</b> </li> </ul> </li> <li><a name="item_Alessandro_Ranellucci"></a><b>Alessandro Ranellucci</b> <ul> <li><a name="item_Fix_prefix_behavior_with_load_app"></a><b>Fix prefix behavior with load_app</b> </li> </ul> </li> <li><a name="item_Emmanuel_Rodriguez"></a><b>Emmanuel Rodriguez</b> <ul> <li><a name="item_Support_for__content_type__option_on_send_file_when_sending_a_______system_wide_file"></a><b>Support for 'content_type' option on send_file when sending a system wide file</b> </li> </ul> </li> <li><a name="item_Adam_J__Foxson"></a><b>Adam J. Foxson</b> <ul> <li><a name="item_FIX_for_issue_GH_136___readline___on_closed_filehandle_DATA__error_that_appears_when_running_the_app_with_Starman"></a><b>FIX for issue GH#136: "readline() on closed filehandle DATA" error that appears when running the app with Starman</b> </li> <li><a name="item_Addresses_issue__136___readline___on_closed_filehandle_DATA_"></a><b>Addresses issue #136: "readline() on closed filehandle DATA"</b> </li> </ul> </li> <li><a name="item_Mark_Allen"></a><b>Mark Allen</b> <ul> <li><a name="item_Added_a_tutorial__Dancer__Tutorial_"></a><b>Added a tutorial (Dancer::Tutorial)</b> </li> <li><a name="item_Provided_an_example_application__Dancr___provided_in_example_"></a><b>Provided an example application 'Dancr', provided in example/</b> </li> </ul> </li> <li><a name="item_Joshua_Barratt"></a><b>Joshua Barratt</b> <ul> <li><a name="item_Dancer__Serializer__JSON_supports__allow_blessed__and__convert_blessed__options_"></a><b>Dancer::Serializer::JSON supports 'allow_blessed' and 'convert_blessed' options.</b> </li> </ul> </li> <li><a name="item_Ivan_Paponov"></a><b>Ivan Paponov</b> <ul> <li><a name="item_Support_HTTP_X_FORWARDED_HOST_in_behing_proxy"></a><b>Support HTTP_X_FORWARDED_HOST in behing proxy</b> </li> </ul> </li> <li><a name="item_Juan_J__Mart&#xed;nez"></a><b>Juan J. Mart&#xed;nez</b> <ul> <li><a name="item_Provided_a_report_about_a_bug_which_returned_a_voice_context_after_redirecting_a_route_"></a><b>Provided a report about a bug which returned a voice context after redirecting a route.</b> </li> </ul> </li> <li><a name="item_Hagen_Fuchs"></a><b>Hagen Fuchs</b> <ul> <li><a name="item_Request_pm_Decode_HTTP__Request_s_uploads"></a><b>Request.pm Decode HTTP::Request's uploads</b> </li> </ul> </li> <li><a name="item_Fran&#xe7;ois_Charlier"></a><b>Fran&#xe7;ois Charlier</b> <ul> <li><a name="item_Provided_a_fix_for_GH_76_and_GH_88"></a><b>Provided a fix for GH#76 and GH#88</b> </li> </ul> </li> <li><a name="item_JT_Smith"></a><b>JT Smith</b> <ul> <li><a name="item_Error_Hook__PR_563_"></a><b>Error Hook (PR 563)</b> </li> </ul> </li> <li><a name="item_Olof_Johansson"></a><b>Olof Johansson</b> <ul> <li><a name="item_Fixed_Dancer__Plugins_typos_in_the_documentation"></a><b>Fixed Dancer::Plugins typos in the documentation</b> </li> </ul> </li> <li><a name="item_Al_Newkirk"></a><b>Al Newkirk</b> <ul> <li><a name="item_fixed_redirect_to_redirect_immediately"></a><b>fixed redirect to redirect immediately</b> </li> </ul> </li> <li><a name="item_Ivan_Bessarabov"></a><b>Ivan Bessarabov</b> <ul> <li><a name="item_Worked_on_fixing_TT_example_config_"></a><b>Worked on fixing TT example config.</b> </li> </ul> </li> <li><a name="item_Sam_Kington"></a><b>Sam Kington</b> <ul> <li><a name="item_Deserialize_PATCH_requests"></a><b>Deserialize PATCH requests</b> </li> </ul> </li> <li><a name="item_Dave_Doyle"></a><b>Dave Doyle</b> <ul> <li><a name="item_Working_on_clarifying_Pod_as_to_how_before_template_works"></a><b>Working on clarifying Pod as to how before_template works</b> </li> </ul> </li> <li><a name="item_Flavio_Poletti"></a><b>Flavio Poletti</b> <ul> <li><a name="item_Added__git_fetch_upstream__for_remote_tracking"></a><b>Added "git fetch upstream" for remote tracking</b> </li> <li><a name="item_Turned_a_tab_into_the_right_number_of_spaces"></a><b>Turned a tab into the right number of spaces</b> </li> </ul> </li> </ul> <h1><a name="author"></a>AUTHOR</h1> <p>Kindly authored by Viktor C, a student partaking in the Google Code-In, mentored by David Precious - thanks Viktor for your contribution too!</p> <h1><a name="merry_christmas_"></a>MERRY CHRISTMAS!</h1> <p>That's it for this year's Dancer Advent Calendar - we hope it's been an enjoyable read for you, and thank you for your interest in the project. From all of the core development team, we wish you a happy Christmas (or happy holidays, if you don't observe Christmas) and a happy and prosperous New Year!</p> <p>We're all off to raise a glass of our favourite tipple to the success of the project, and warmly invite you to join us :)</p> </div> Meet the core team http://advent.perldancer.org/2011/23 perl http://advent.perldancer.org/2011/23 Fri, 23 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="meet_the_core_team"></a>Meet the core team</h1> <p>Dancer has evolved quickly from a prototype based on the idea of porting Ruby's <a href="http://sinatrarb.com/">Sinatra</a> to a fully featured and popular micro-framework. This has been possible thanks to a vast community of users who contributed ideas, bug reports and patches.</p> <p>Time after time, some of these users appeared to be very motivated and productive and it's quite natural that a <i>Core Team</i> emerged.</p> <p>In this article we'll present each member of the team, so you can put some faces behind the Git history and IRC users.</p> <p>The core team is probably the best feature of Dancer, so please, let me introduce you to the men who make Perl dance!</p> <h2><a name="alexis_sukrieh__sukria_"></a>Alexis Sukrieh (sukria)</h2> <img src="/images/2011/23/sukria.jpg"> <p>1442 commits so far, first commit on Jul 17th 2009 (<a href="https://github.com/sukria/Dancer/commit/da6c198">da6c198</a>)</p> <p>Alexis has been working in the Internet industry for more than ten years. He's always been passionate about computer programming and free software. Perl has always been the language Alexis enjoys the most, and luckily he always managed to find a paid job with Perl throughout his career.</p> <p>Before creating Dancer, Alexis used to be a Debian developer and wrote a popular backup tool called <a href="http://www.backup-manager.org">Backup Manager</a>.</p> <p>In summer 2009 he started experimenting with a port of the Ruby project <a href="http://sinatrarb.com">Sinatra</a> in Perl, and that's how Perl Dancer was born. Alexis tried hard to build a friendly and responsive community around Dancer, he's very happy to see the project evolving by itself. Alexis now dedicates all his free time on <a href="http://advent.perldancer.org/2011/8">Dancer 2</a>, a complete rewrite of the project.</p> <p>Alexis works at <a href="http://www.weborama.com">Weborama</a>, a company that works in the Internet advertisement industry. When not writing Perl code or terrorizing Weborama's R&amp;D Team, he listens to insane and loud music.</p> <p>Alexis runs a <a href="http://www.sukria.net/fr/">blog</a> and has a <a href="http://twitter.com/sukria">Twitter</a>.</p> <h2><a name="sawyer_x__sawyer_"></a>Sawyer X (sawyer)</h2> <img src="/images/2011/23/sawyer.jpg"> <p>581 commits so far, first one on Jan 13th, 2010 (<a href="https://github.com/sukria/Dancer/commit/b7cc27b">b7cc27b</a>)</p> <p>Sawyer X has been using Perl for almost 10 years now. We works as a Perl developer and systems administrator. He is responsible for Organising <a href="http://telaviv.pm.org">TelAviv.pm</a> meetings. Sawyer picked up Dancer after checking out several small web frameworks on CPAN. The responsiveness and kindness in the community prompted him to suggest and develop his first contribution to Dancer - a route caching system. Since then he has become a core developer, project mentor and lecturer world-wide.</p> <p>He is currently the maintainer and release manager of the 1.x branch.</p> <h2><a name="franck_cuny__franck_"></a>Franck Cuny (franck)</h2> <img src="/images/2011/23/franck.jpg"> <p>781 commits so far, first one on Jan 14th, 2010 (<a href="https://github.com/sukria/Dancer/commit/dff82bf">dff82bf</a>)</p> <p>Franck is passionate about <a href="http://lumberjaph.net/graph/2010/03/25/github-explorer.html">graphs</a>, code, and web technologies.</p> <p>He is a software engineer working at <a href="http://saymedia.com/">SAY: Media</a>, where most of his time is spent working on the platform, building services, tools, and help designing the architecture.</p> <p>He is also a member of <a href="http://sf.mongueurs.net/">SF.pm</a>, and was the previous organizer of Paris' technical meetings, before letting dams bringing the whole thing down.</p> <h2><a name="david_precious__bigpresh_"></a>David Precious (bigpresh)</h2> <img src="/images/2011/23/bigpresh.jpg"> <p>284 commits so far, first one on Feb 11th, 2010 (<a href="https://github.com/sukria/Dancer/commit/b92d612">b92d612</a>)</p> <p>David Precious (bigpresh) is a professional Perl developer from London, with 11 years of commercial experience working in the ISP and hosting market.</p> <p>He discovered Dancer in February 2010 whilst looking for a framework which was nice to use and didn't feel awkward, contributed a few improvements and fixes, and eventually ended up with a commit bit.</p> <p>Since then he's promoted the project in the Perl community, maintains the website and advent calendar, and helps improve the documentation as well as fixing bugs and adding features.</p> <p>When not in front of a keyboard, he is a keen motorcyclist, plays squash, and enjoys drinking beer. Quite a lot of beer.</p> <h2><a name="damien_krotkine__dams_"></a>Damien Krotkine (dams)</h2> <img src="/images/2011/23/dams.jpg"> <p>172 commits so far, first commit on Sep 26th, 2010 (<a href="https://github.com/sukria/Dancer/commit/16ad3a9">16ad3a9</a>)</p> <p>Damien has been using Perl since 1999. He started using Dancer in late 2010 for a small project, done in 2 days. Amazed by the ease of use, he started contributing, and got the commit bit soon after. He has worked at Mandrakesoft, Mandriva, IDM, Venda, and now Weborama. He organises the tech meeting of the <a href="http://paris.pm.org/">Paris Perl Mongers</a> since September 2011.</p> <p>When not coding Perl, he enjoys life with his lovely wife, mainly doing rock climbing.</p> <h2><a name="alberto_sim&#xf5;es__ambs_"></a>Alberto Sim&#xf5;es (ambs)</h2> <img src="/images/2011/23/ambs.jpg"> <p>426 commits so far, first commit on Dec 19th, 2010 (<a href="https://github.com/sukria/Dancer/commit/537c5aa">537c5aa</a>).</p> <p>Alberto started using Perl in 1999. He uses Perl mostly for natural language processing. He was a old school CGI programmer until he heard about Dancer in 2010's Dancer Advent Calendar. Since then he started using and patching Dancer and annoying Dancer core developers. He poked so much that he was promoted to a Dancer core developer.</p> <p>Alberto was also the organizer of <a href="http://conferences.yapceurope.org/ye2005/">YAPC::EU::2005</a> in Braga, Portugal and <a href="http://conferences.yapceurope.org/ye2009/">YAPC::EU::2009</a> in Lisbon, Portugal. He is the co-founder of the Portuguese Perl Users Group, and secretary of <a href="https://metacpan.org/module/www.perlfoundation.org/">The Perl Foundation</a> (TPF) grants committee.</p> <h2><a name="authors"></a>Authors</h2> <p>This article has been written by the core team for the Dancer Advent Calendar 2011.</p> </div> Generating CAPTCHAs using Dancer::Plugin::Captcha::SecurityImage http://advent.perldancer.org/2011/22 perl http://advent.perldancer.org/2011/22 Thu, 22 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="generating_captchas_using_dancer__plugin__captcha__securityimage"></a>Generating CAPTCHAs using Dancer::Plugin::Captcha::SecurityImage</h1> <p>Many sites uses a <a href="http://en.wikipedia.org/wiki/CAPTCHA">CAPTCHA</a> to prevent bots using comments for spam. If you want to add this feature to your site, you can do it using Dancer::Plugin::SecurityImage.</p> <p>For a CAPTCHA test to work, you need to generate an image with slightly obsfucated text which computer OCR (Optical Character Recognition) software will not be able to read, and store the text contained in the image in the user's session. Once they submit the form, you compare the text they entered with the text stored in the session, and you know if they entered the right text or not.</p> <p><a href="https://metacpan.org/module/Dancer::Plugin::Captcha::SecurityImage">Dancer::Plugin::Captcha::SecurityImage</a> makes this easy.</p> <h1><a name="description_of_common_functions"></a>Description of common functions</h1> <p><code>create_captcha</code></p> <p>This function expects argument which will be passed to the <a href="https://metacpan.org/module/GD::SecurityImage">GD::SecurityImage</a> constructor and methods.</p> <p><code>validate_captcha</code></p> <p>This function expects the value user entered in the form. It will check it against the code stored in the Dancer session and return <code>true</code> if they match.</p> <p><code>clear_captcha</code></p> <p>This function will remove the CAPTCHA value from your session data so that it won't match again.</p> <h1><a name="simple_example"></a>Simple example</h1> <pre class="prettyprint">use Dancer; use Dancer::Plugin::Captcha::SecurityImage; session 'simple'; get '/captcha' =&gt; sub { create_captcha { new =&gt; { width =&gt; 80, height =&gt; 30, lines =&gt; 10, gd_font =&gt; 'giant', }, create =&gt; [ normal =&gt; 'rect' ], particle =&gt; [ 100 ], out =&gt; { force =&gt; 'jpeg' }, #format of picture ('jpeg', 'png') random =&gt; $random_string = rand_pass(6), #random string for CAPTCHA }; }; post '/verify' =&gt; sub { #captcha validation my $p = request-&gt;params; if (!validate_captcha $p-&gt;{captcha}) { return "wrong code"; } clear_captcha; }; sub rand_pass { my $len = shift; my $pass; for (1..$len) {$pass .= chr(rand(94)+33)} return $pass; }</pre> <h1><a name="author"></a>AUTHOR</h1> <p>This article was written by Andrew Inishev, Google Code-in student, mentored by David Precious.</p> </div> Making RSS feeds using Dancer::Plugin::Feed http://advent.perldancer.org/2011/21 perl http://advent.perldancer.org/2011/21 Wed, 21 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="making_rss_feeds_using_dancer__plugin__feed"></a>Making RSS feeds using Dancer::Plugin::Feed</h1> <p>RSS is a very popular way to see updates of any site. Many sites use it, and you may well want to add RSS support to your site. You can easily do it with Dancer using <a href="https://metacpan.org/module/Dancer::Plugin::Feed">Dancer::Plugin::Feed</a>.</p> <h1><a name="description_of_common_functions"></a>Description of common functions</h1> <h2><a name="create_feed"></a>create_feed</h2> <p>This function returns a XML feed. All parameters can be define in the configuration</p> <p>Accepted parameters are:</p> <p><code>format</code> (required)</p> <p>The Content-Type header will be set to the appropriate value</p> <p><code>entries</code></p> <p>An arrayref containing a list of entries. Each item will be transformed to an XML::Feed::Entry object. Each entry is an hashref. Some common attributes for these hashrefs are title, link, summary, content, author, issued and modified. Check XML::Feed::Entry for more details.</p> <p><code>title</code></p> <p><code>base</code></p> <p><code>link</code></p> <p><code>tagline</code></p> <p><code>description</code></p> <p><code>author</code></p> <p><code>language</code></p> <p><code>copyright</code></p> <p><code>self_link</code></p> <p><code>modified</code></p> <h2><a name="create_atom_feed"></a>create_atom_feed</h2> <p>This method calls create_feed, setting the format to Atom.</p> <h2><a name="create_rss_feed"></a>create_rss_feed</h2> <p>This method calls create_feed, setting the format to RSS.</p> <h1><a name="simple_example"></a>Simple example</h1> <pre class="prettyprint">use Dancer; use Dancer::Plugin::Feed; get '/feed/:format' =&gt; sub { my $feed = create_feed( format =&gt; params-&gt;{format}, #Feed format (RSS or Atom) title =&gt; 'my great feed', entries =&gt; [ map { title =&gt; "entry $_" }, 1 .. 10 ], #makes collection of feed entries ); return $feed; }; dance;</pre> <h1><a name="author"></a>AUTHOR</h1> <p>This article was written by Andrew Inishev, Google Code-In student, mentored by David Precious.</p> </div> High-performance Dancer apps http://advent.perldancer.org/2011/20 perl http://advent.perldancer.org/2011/20 Tue, 20 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="high_performance_dancer_apps"></a>High-performance Dancer apps</h1> <p>Using or considering using Dancer in a high-traffic environment? There are some techniques you can use to help ensure good performance, which will be documented here.</p> <p>Some of these tips are based on a Dancer application in production at work - in a couple of months it's answered over 40 million requests for several hundred thousand individual domain names, so it's battle-proven.</p> <h2><a name="handle_static_files_via_the_webserver"></a>Handle static files via the webserver</h2> <p>For performance, you want your application's static files (images, Javascript, CSS etc) to be served up by your webserver, e.g. Nginx, rather than being passed to your Dancer app to serve.</p> <p>A short example Nginx configuration:</p> <pre class="prettyprint">server { listen 80; server_name foo.example.com; location / { # Serve static files directly: if (-f $request_filename) { expires 30d; break; } # Pass on other requests to Dancer app proxy_pass_header Server; proxy_pass http://localhost:3000/; } }</pre> <p>Similiar configuration methods should work with other deployment methods.</p> <h2><a name="run_under_a_suitable_backend"></a>Run under a suitable backend</h2> <p>For high-load situations, you'll want to be running under a suitable Plack back-end. <a href="https://metacpan.org/module/Starman">Starman</a> is a very high performance backend, and is recommended.</p> <p>A simple "hello world" benchmark test in the Starman documentation shows it capable of handling over 6800 requests per second. Naturally, with a real-world more complex app, you're not going to achieve quite that level of performance.</p> <h2><a name="pre_load_your_application"></a>Pre-load your application</h2> <p>When running with Starman, you can pre-load your application before forking worker processes, to increase performance and provide memory savings with copy-on-write memory management.</p> <p>Use Starman's <code>--preload-app</code> option to enable this (but be aware that this can cause Bad Things to happen if resources like database connections or other sockets are opened by your app at compile time, as they will be unintentionally shared amongst child processes. <a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a> contains code to ensure fork/thread safety, so you should be safe if using that plugin to manage your database connections.</p> <p>You can also pre-load individual modules using <code>plackup</code>'s <code>-M</code> for similar effect:</p> <pre class="prettyprint">starman -MDancer -MMoose -MFoo myapp.psgi</pre> <h2><a name="caching"></a>Caching</h2> <p>Using <a href="https://metacpan.org/module/Dancer::Plugin::Cache::CHI">Dancer::Plugin::Cache::CHI</a> to cache data and responses as much as possible (using a backend like Memcached) can save a lot of execution time, and help your application to handle more requests, faster.</p> <p>A simple example to cache a whole page response:</p> <pre class="prettyprint"># Arrange for the cache to be consulted for a matching response before route # handlers are invoked: check_page_cache(); get '/foo' =&gt; sub { my $data = some_expensive_slow_function(); my $content = template 'foo', $data; cache_page $content; return $content; };</pre> <h2><a name="profile_your_app_to_find_bottlenecks"></a>Profile your app to find bottlenecks</h2> <p>As <a href="http://advent.perldancer.org/2011/9">covered previously</a>, <a href="https://metacpan.org/module/Dancer::Plugin::NYTProf">Dancer::Plugin::NYTProf</a> can be useful to profile your Dancer applications and see where time is spent to identify bottlenecks where a little optimisation can pay off.</p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious, <code>&lt;davidp@preshweb.co.uk&gt;</code></p> </div> How to use Dancer::Plugin::Redis http://advent.perldancer.org/2011/19 perl http://advent.perldancer.org/2011/19 Mon, 19 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="how_to_use_dancer__plugin__redis"></a>How to use Dancer::Plugin::Redis</h1> <p>Dancer::Plugin::Redis is a plugin created to make an easy way to use Redis database in Dancer apps. In fact, Dancer::Plugin::Redis is an abstraction from Redis plugin. It has only one function <code>redis</code>, which returns a database handle. See Redis module documentation for the list of controlling functions.</p> <h1><a name="introduction_to_redis"></a>Introduction to Redis</h1> <p>Redis is key-value, networking, in-memory data store with optional durability. It is very useful technology because it simple and fast. It supports many data types (integers, strings, sets, etc).</p> <h1><a name="synopsis"></a>Synopsis</h1> <pre class="prettyprint">use Dancer; use Dancer::Plugin::Email; use Dancer::Plugin::Redis; post '/write_us' =&gt; sub{ email{ to =&gt; redis-&gt;get('support_email'), #gets destination email from database subject =&gt; $subject, encoding =&gt; redis-&gt;get('email_encoding'), #get email encoding from database message =&gt; $msg }; redis-&gt;incr ('count_of_messages'); #increments count of all emails sent by users }; }; dance;</pre> <p>When you use <code>redis</code> keyword it gives you a connected database handle or (if already connected) checks connection.</p> <h1><a name="simple_examples"></a>Simple examples</h1> <h2><a name="getting_a_value"></a>Getting a value</h2> <pre class="prettyprint">use Dancer; use Dancer::Plugin::Redis; get '/widget/view/:id' =&gt; sub { template 'display_widget', { widget =&gt; redis-&gt;get('time_applet'); }; }; dance;</pre> <h2><a name="incrementing_count_of_views_in_redis_database"></a>Incrementing count of views in Redis database</h2> <pre class="prettyprint">use Dancer; use Dancer::Plugin::Redis; get '/index' =&gt; sub{ redis-&gt;incr('count_of_views'); }; dance;</pre> <h1><a name="author"></a>Author</h1> <p>This article was written by Andrew Inishev, Google Code-in student, mentored by David Precious.</p> </div> Alternative Dancer Templating Engines http://advent.perldancer.org/2011/18 perl http://advent.perldancer.org/2011/18 Sun, 18 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="alternative_dancer_templating_engines"></a>Alternative Dancer Templating Engines</h1> <p>Dancer uses a simple model of interfacing with templating engines (based on <a href="https://metacpan.org/module/Dancer::Template::Abstract">Dancer::Template::Abstract</a>) and makes it very easy to add support for new engines. Thanks to this, if you're not happy with the default <code>simple</code> engine or with <a href="http://template-toolkit.org/index.html">Template Toolkit</a>, there is now a dozen different alternatives to choose from. Let's take a look at some of them.</p> <h2><a name="dancer__template__tiny"></a>Dancer::Template::Tiny</h2> <p><a href="https://metacpan.org/module/Template::Tiny">Template::Tiny</a> is a lightweight engine which reimplements a subset of Template Toolkit features. As the name implies, it aims to accomplish this with as little code as possible. If you're using just the basic functionality of Template Toolkit, you should be able to switch to Template::Tiny without any modifications to template files (and you can easily go back at any moment).</p> <p><a href="https://metacpan.org/module/Dancer::Template::Tiny">Dancer::Template::Tiny</a> is going to replace <a href="https://metacpan.org/module/Dancer::Template::Simple">Dancer::Template::Simple</a> as the default templating engine in Dancer2.</p> <p>Example template:</p> <pre class="prettyprint">&lt;html&gt; &lt;head&gt; &lt;title&gt;Tiny Example&lt;/title&gt; &lt;link rel="stylesheet" href="[% request.uri_base %]/css/style.css" /&gt; &lt;/head&gt; &lt;body&gt; &lt;h1&gt;Hello, World! This is Dancer [% dancer_version %]!&lt;/h1&gt; &lt;p&gt; [% IF morning %] Good morning! [% ELSE %] Good afternoon! [% END %] &lt;/p&gt; &lt;/body&gt; &lt;/html&gt;</pre> <p>Route handler:</p> <pre class="prettyprint">use DateTime; get '/hello' =&gt; sub { template 'hello', { morning =&gt; (localtime)[2] &lt; 12, now =&gt; DateTime-&gt;now }; };</pre> <h2><a name="dancer__template__tenjin"></a>Dancer::Template::Tenjin</h2> <p><a href="http://www.kuwata-lab.com/tenjin/">Tenjin</a> is a very fast templating engine with implementations for many languages -- including, of course, Perl. Its great performance comes from the fact that it uses the underlying language's constructs to process templates, instead of defining its own templating language and having to parse it. Support for this engine in Dancer is provided by <a href="https://metacpan.org/module/Dancer::Template::Tenjin">Dancer::Template::Tenjin</a>.</p> <p>Example template:</p> <pre class="prettyprint">&lt;html&gt; &lt;head&gt; &lt;title&gt;Tenjin Example&lt;/title&gt; &lt;link rel="stylesheet" href="[== $request-&gt;uri_base =]/css/style.css" /&gt; &lt;/head&gt; &lt;body&gt; &lt;h1&gt;Hello, World! This is Dancer [= $dancer_version =]!&lt;/h1&gt; &lt;p&gt; &lt;?pl if ((localtime)[2] &lt; 12) { ?&gt; Good morning! &lt;?pl } else { ?&gt; Good afternoon! &lt;?pl } ?&gt; &lt;/p&gt; &lt;p&gt; Current time is: [== DateTime-&gt;now-&gt;hms =] &lt;/p&gt; &lt;/body&gt; &lt;/html&gt;</pre> <p>Route handler:</p> <pre class="prettyprint">use DateTime; get '/hello' =&gt; sub { template 'hello'; };</pre> <h2><a name="dancer__template__haml"></a>Dancer::Template::Haml</h2> <p><a href="http://haml-lang.com/">Haml</a>, which stands for "HTML Abstraction Markup Language", brings a fresh, different approach to templating. It aims at making templates short, clean, and as easy to read as well-formatted source code. <a href="https://metacpan.org/module/Dancer::Template::Haml">Dancer::Template::Haml</a> is a wrapper around <a href="https://metacpan.org/module/Text::Haml">Text::Haml</a> and lets you use Haml templates in Dancer applications.</p> <p>Example template:</p> <pre class="prettyprint">%html %head %title Haml Example %link(rel="stylesheet" href="#{$request-&gt;uri_base}/css/style.css") %body %h1 Hello, World! This is Dancer #{$dancer_version}! %p - if ((localtime)[2] &lt; 12) { Good morning! - } else { Good afternoon! - } %p Current time is: #{DateTime-&gt;now-&gt;hms}</pre> <p>Route handler:</p> <pre class="prettyprint">use DateTime; get '/hello' =&gt; sub { template 'hello'; };</pre> <h2><a name="more"></a>More</h2> <p>There are many more interesting templating engines ready to be used with Dancer, such as <a href="http://www.masonhq.com/">Mason</a> (provided by <a href="https://metacpan.org/module/Dancer::Template::Mason">Dancer::Template::Mason</a>) or <a href="http://xslate.org/">Xslate</a> (<a href="https://metacpan.org/module/Dancer::Template::Xslate">Dancer::Template::Xslate</a>). Do a <a href="http://search.cpan.org/">CPAN</a> or <a href="https://metacpan.org/">MetaCPAN</a> search for "dancer template" to get a list of all the available engines, and choose the one that suits you best. In the true spirit of Perl, there's more than one way to write a template!</p> <h1><a name="author"></a>Author</h1> <p><a href="http://odyniec.net/">Michal Wojciechowski</a>, <code>&lt;odyniec@odyniec.net&gt;</code></p> </div> Dancer plugins ecosystem http://advent.perldancer.org/2011/17 perl http://advent.perldancer.org/2011/17 Sat, 17 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="dancer_plugins_ecosystem"></a>Dancer plugins ecosystem</h1> <p>Dancer has been designed to provide the built-in features you need, but to remain slim and not force your choice of technologies, so plugins and engines are an important feature for easy extensibility.</p> <p>It's easy to write plugins to extend Dancer's DSL and provide various useful extra features. Today, here is a write-up of a small selection of the wide variety of plugins available.</p> <ul> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Database__Dancer__Plugin__Database__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a></b> <p><a href="http://advent.perldancer.org/2011/5">Covered in more detail</a> already, but Dancer::Plugin::Database provides easy to use and easy to configure <a href="https://metacpan.org/module/DBI">DBI</a> database connection management along with a handful of convenience methods.</p> <p>It has been designed to make the common stuff as easy as possible.</p> <p>A quick example - fetching details of a user and passing them to a template to render a page with details on that user:</p> <pre class="prettyprint">get '/user/:id' =&gt; sub { my $user = database-&gt;quick_select('users', { id =&gt; params-&gt;{id} }); return template 'user', $user; };</pre> <p>Calling the <code>database</code> keyword gets you a database handle (which is actually a subclassed <code>DBI::db</code> object, which acts just as a normal DBI database handle but adds a few convenience methods such as <code>quick_select</code>.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__DBIC__Dancer__Plugin__DBIC__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::DBIC">Dancer::Plugin::DBIC</a></b> <p>If you plan to use <a href="https://metacpan.org/module/DBIx::Class">DBIx::Class</a> to access your database in an ORM-ish style, then this plugin provides a <code>schema</code> keyword which lets you do things like:</p> <pre class="prettyprint">my @authors = schema-&gt;resultset('Author')-&gt;search({ -or =&gt; [ firstname =&gt; { like =&gt; "%$query%" }, lastname =&gt; { like =&gt; "%$query%" }, ] });</pre> <p>When configuring the plugin, you can allow DBIC to auto-discover the schema for ultimate ease of use, or you can point it at your own schema classes.</p> <p><a href="http://advent.perldancer.org/2010/11">Covered in more detail</a> in last year's Dancer advent calendar.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Redis__Dancer__Plugin__Redis__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Redis">Dancer::Plugin::Redis</a></b> <p>Provides an easy way to obtain a connected Redis database handle by simply calling the redis keyword within your Dancer application.</p> <pre class="prettyprint">get '/widget/view/:id' =&gt; sub { template 'display_widget', { widget =&gt; redis-&gt;get('hash_key'); }; };</pre> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Mongo__Dancer__Plugin__Mongo__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Mongo">Dancer::Plugin::Mongo</a></b> <p>Provides a wrapper around <a href="https://metacpan.org/module/MongoDB">MongoDB</a>. Add the appropriate configuraton options to your config.yml and then you can access a MongoDB database using the 'mongo' keyword:</p> <pre class="prettyprint">get '/widget/view/:id' =&gt; sub { my $widget = mongo-&gt;database-&gt;collection-&gt;find_one({ id =&gt; params-&gt;{id} }); };</pre> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Email__Dancer__Plugin__Email__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Email">Dancer::Plugin::Email</a></b> <p>Provides simple email sending for your Dancer applications, powered by <a href="https://metacpan.org/module/Email::Send">Email::Send</a> via an <code>email</code> keyword:</p> <pre class="prettyprint">post '/contact' =&gt; sub { email { to =&gt; '...', subject =&gt; '...', message =&gt; $msg, attach =&gt; [ '/path/to/file' ] }; };</pre> <p><a href="http://advent.perldancer.org/2011/15">Covered in more detail</a> previously in this year's calendar.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__SMS__Dancer__Plugin__SMS__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::SMS">Dancer::Plugin::SMS</a></b> <p>Provides simple SMS text messaging sending, powered by <a href="https://metacpan.org/module/SMS::Send">SMS::Send</a>:</p> <pre class="prettyprint">post '/sendsms' =&gt; sub { sms to =&gt; '++447......', text =&gt; '......'; };</pre> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__EscapeHTML__Dancer__Plugin__EscapeHTML__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::EscapeHTML">Dancer::Plugin::EscapeHTML</a></b> <p>Makes it easy to escape HTML to help mitigate against <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a> vulnerabilities.</p> <pre class="prettyprint">my $encoded = escape_html($some_html);</pre> <p>In many cases, you'll be passing data to your templates to render, but will never be intentionally passing HTML, only data. In that case, you can arrange for all template params to be escaped before the template receives them by adding the following to config.yml:</p> <pre class="prettyprint">plugins: EscapeHTML: automatic_escaping: 1 exclude_pattern: '_html$'</pre> <p>The <code>exclude_pattern</code> illustrated means that any template param with a name ending in <code>_html</code> will be left untouched.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__SimpleCRUD__Dancer__Plugin__SimpleCRUD__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::SimpleCRUD">Dancer::Plugin::SimpleCRUD</a></b> <p>Provides simple <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> support for database tables, with automatic record display, searching, creating, editing, deletion, exporting, etc.</p> <p><a href="http://advent.perldancer.org/2011/2">Covered in more detail</a> previously in this year's calendar.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Ajax__Dancer__Plugin__Ajax__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Ajax">Dancer::Plugin::Ajax</a></b> <p>Provides an <code>ajax</code> keyword to match only requests submitted via AJAX:</p> <pre class="prettyprint">ajax '/check_for_update' =&gt; sub { # ... some Ajax code };</pre> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Passphrase__Dancer__Plugin__Passphrase__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Passphrase">Dancer::Plugin::Passphrase</a></b> <p>Makes it easy to securely handle passwords in your Dancer apps, storing and using secure salted hashed passwords with minimal effort.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Cache__CHI__Dancer__Plugin__Cache__CHI__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Cache::CHI">Dancer::Plugin::Cache::CHI</a></b> <p>Provides easy caching using the <a href="https://metacpan.org/module/CHI">CHI</a> module, which supports a wide variety of caching backends including <code>memcached</code> and various others. Can cache arbitrary bits of information or entire page responses.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Thumbnail__Dancer__Plugin__Thumbnail__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Thumbnail">Dancer::Plugin::Thumbnail</a></b> <p>Provides easy image thumbnail generation using <a href="https://metacpan.org/module/GD">GD</a>.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Facebook__Dancer__Plugin__Facebook__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Facebook">Dancer::Plugin::Facebook</a></b> <p>Makes it easy to interact with Facebook via <a href="https://metacpan.org/module/Facebook::Graph">Facebook::Graph</a> from your Dancer applications.</p> </li> <li><a name="item__a_href__https___metacpan_org_module_Dancer__Plugin__Stomp__Dancer__Plugin__Stomp__a_"></a><b><a href="https://metacpan.org/module/Dancer::Plugin::Stomp">Dancer::Plugin::Stomp</a></b> <p>Makes it as easy as possible to interact with a Stomp message broker. It provides one new keyword, <code>stomp</code>, which returns a <a href="https://metacpan.org/module/Net::Stomp">Net::Stomp</a> object.</p> <pre class="prettyprint">post '/messages' =&gt; sub { stomp-&gt;send({ destination =&gt; '/queue/foo', body =&gt; request-&gt;body }); };</pre> </li> </ul> <p>The above is just a small sample - there's plenty more on CPAN.</p> <p>Just <a href="https://metacpan.org/search?q=Dancer%3A%3APlugin%3A%3A">search for Dancer::Plugin::</a></p> <p>Why not help people find useful plugins by finding the plugins you use on <a href="http://metacpan.org/">MetaCPAN</a> and clicking the <code>++</code> button?</p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious</p> </div> How to use Dancer with Plack middlewares http://advent.perldancer.org/2011/16 perl http://advent.perldancer.org/2011/16 Fri, 16 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="how_to_use_dancer_with_plack_middlewares"></a>How to use Dancer with Plack middlewares</h1> <p>This article is a repeat from last year's advent calendar due to time constraints - sorry! It's a valuable read for anyone who hasn't seen it before, though; the ability to use Plack middleware is one of the features that makes Plack so powerful.</p> <p>Plack is an awesome addition to the Perl ecosystem. One of its key features is support for middlewares.</p> <p>You can see a middleware as a <a href="http://search.cpan.org/perldoc?Moose::Role">Role</a>: a reusable component shared between your applications. This component will act both as a client and as a server.</p> <p>This article doesn't aim to present in details how a middleware works. If you're not yet familiar with <a href="https://metacpan.org/module/Plack">Plack</a>'s middlewares, you can refer to these articles:</p> <ul> <li><a name="item__a_href__http___search_cpan_org__miyagawa_Plack_0_9951_lib_Plack_Middleware_pm__http___search_cpan_org__miyagawa_Plack_0_9951_lib_Plack_Middleware_pm__a_"></a><b><a href="http://search.cpan.org/~miyagawa/Plack-0.9951/lib/Plack/Middleware.pm">http://search.cpan.org/~miyagawa/Plack-0.9951/lib/Plack/Middleware.pm</a></b> </li> <li><a name="item__a_href__http___advent_plackperl_org_2009_12_day_10_using_plack_middleware_html__http___advent_plackperl_org_2009_12_day_10_using_plack_middleware_html__a_"></a><b><a href="http://advent.plackperl.org/2009/12/day-10-using-plack-middleware.html">http://advent.plackperl.org/2009/12/day-10-using-plack-middleware.html</a></b> </li> </ul> <h2><a name="dancer_and_plack"></a>Dancer and Plack</h2> <p>Let's start by creating a simple Dancer application:</p> <pre class="prettyprint">$ dancer -a myapp + myapp + myapp/bin + myapp/bin/app.pl ...</pre> <p>Every Dancer application is a valid Plack application. When you're starting your project, you can choose between a standalone server, or using Plack:</p> <pre class="prettyprint">$ ./bin/app.pl &gt;&gt; Dancer server 12481 listening on http://0.0.0.0:3000 == Entering the development dance floor ...</pre> <p>Doing this starts my application using Dancer's standalone server on port <b>3000</b> (by default; you can use the <code>--port</code> command-line argument to change this).</p> <p>Now, let's use Plack to start this application:</p> <pre class="prettyprint">$ plackup bin/app.pl HTTP::Server::PSGI: Accepting connections at http://0:5000/</pre> <p>This time, it's the PSGI's standalone server that serves our application, and it is listening on port <b>5000</b> (this is the default chosen by Plackup; again, you can use the <code>--port</code> argument to change this).</p> <h2><a name="adding_a_first_middleware"></a>Adding a first Middleware</h2> <p>For this example, we will add a basic middleware: <a href="https://metacpan.org/module/Plack::Middleware::ETag">Plack::Middleware::ETag</a>. This one will append to all our responses a new header: <b>ETag</b>. The ETag is a mechanism to control cache validation. Most of the time, the value of the ETag is a checksum of the page content returned to the client. The client will then store this value, and next time it requests the same page, it will request the content only if the checksum has changed.</p> <p>In your config.yml, add the following:</p> <pre class="prettyprint">plack_middlewares: - - ETag</pre> <p>Now restart your application (with plackup), and let's do a request:</p> <pre class="prettyprint">$ curl -D - http://localhost:5000 HTTP/1.0 200 OK Date: Tue, 09 Nov 2010 15:49:30 GMT Server: HTTP::Server::PSGI Content-Type: text/html; charset=UTF-8 X-Powered-By: Perl Dancer 1.1999_02 ETag: 5f6e450f378e384d4be6e0c081b9dd93026ff146 Content-Length: 5428</pre> <p>The ETag header has been added to your response. If you redo the request, you'll see that the ETag value is the same.</p> <p>Let's add another middleware: <a href="https://metacpan.org/module/Plack::Middleware::ConditionalGet">Plack::Middleware::ConditionalGet</a>. This middleware makes sure the application returns content to the client only if the content has been modified since the previous request:</p> <pre class="prettyprint">plack_middlewares: - - ConditionalGET - - ETag</pre> <p><i>Note that the order is important.</i></p> <pre class="prettyprint">$ curl -D - http://localhost:5000 \ -H "If-None-Match: 5f6e450f378e384d4be6e0c081b9dd93026ff146" HTTP/1.0 304 Not Modified Date: Tue, 09 Nov 2010 15:52:01 GMT Server: HTTP::Server::PSGI X-Powered-By: Perl Dancer 1.1999_02 ETag: 5f6e450f378e384d4be6e0c081b9dd93026ff146</pre> <p>This time there is no <b>Content-Length</b> header, because the value of the ETag header is the same, so we don't have any content returned for that request.</p> <h2><a name="content_compression"></a>Content compression</h2> <p>Another common use case is the need to send content from the server to the client in a compressed format. For this, you can use <a href="https://metacpan.org/module/Plack::Middleware::Deflater">Plack::Middleware::Deflater</a> which will compress the content on-the-fly with gzip if the client supports this feature.</p> <p>A simple:</p> <pre class="prettyprint">plack_middlewares: - - Deflater</pre> <p>will do the trick.</p> <h2><a name="using_the_debug_panels"></a>Using the Debug panels</h2> <p>Some very useful middlewares to use while debugging your application are <a href="https://metacpan.org/module/Plack::Middleware::Debug">Plack::Middleware::Debug</a> and <a href="https://metacpan.org/module/Dancer::Debug">Dancer::Debug</a>.</p> <p>Those middlewares will inject some HTML code in your page, providing lots of useful information about your application, the current request and the response returned. To activate their panels, add this to your configuration:</p> <pre class="prettyprint">plack_middlewares: - - Debug - panels - - Parameters - Dancer::Version - Dancer::Settings - Memory</pre> <p>Next time you'll visit your application, you should see this panel on the right:</p> <img src="/images/dancer_debug_01.png" /> <p>If you click on one of the element from the menu, the panel will open with something similar:</p> <img src="/images/dancer_debug_02.png" /> <h2><a name="more_complex"></a>More complex</h2> <p>Some middlewares require a more complex configuration, and you won't use them as in our previous examples. For this example, we want to add a simple authentication system to access our application.</p> <p>Edit your <code>bin/app.pl</code> application, and replace the code with this one:</p> <pre class="prettyprint">use Dancer; use myapp; use Plack::Builder; my $app = sub { my $env = shift; my $request = Dancer::Request-&gt;new($env); Dancer-&gt;dance($request); }; builder { enable "Auth::Basic", authenticator =&gt; sub { my ( $username, $password ) = @_; return $username eq 'admin' &amp;&amp; $password eq 's3cr3t'; }; $app; };</pre> <p>First, we create a PSGI application (line 5). This application processes the request and returns a PSGI-compatible result. Next, we use the <b>builder</b> keyword, provided by <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a>. Here we enable a middleware (<b>Auth::Basic</b>), and we create a code ref for the authentication method.</p> <p>If you start your application with plackup, and load the page in your browser, you will be prompted for a username and a password to access the page.</p> <h2><a name="credits"></a>Credits</h2> <p>A huge thanks to Marcel Gr&#xfc;nauer and Tatsuhiko Miyagawa for the awesome <a href="https://metacpan.org/module/Plack::Middleware::Debug">Plack::Middleware::Debug</a>.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by franck cuny <code>&lt;franck@lumberjaph.net&gt;</code> for the Perl Dancer Advent Calendar 2010.</p> <h2><a name="copyright"></a>Copyright</h2> <p>Copyright (C) 2010 by franck cuny</p> </div> Sending email in Dancer using Dancer::Plugin::Email http://advent.perldancer.org/2011/15 perl http://advent.perldancer.org/2011/15 Thu, 15 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="sending_email_in_dancer_using_dancer__plugin__email"></a>Sending email in Dancer using Dancer::Plugin::Email</h1> <p>Many sites use email forms to provide a fast and comfortable feedback method. The user just types their details and message and clicks on 'Submit' button, and the details are sent to a specified email address.</p> <p>If you want to send email from your Dancer application, you can do so easily using the <a href="https://metacpan.org/module/Dancer::Plugin::Email">Dancer::Plugin::Email</a> plugin.</p> <h2><a name="how_do_i_use_it"></a>How do I use it?</h2> <p><a href="https://metacpan.org/module/Dancer::Plugin::Email">Dancer::Plugin::Email</a> is very simple to use - in fact, there is only one function, <code>email</code>, which sends email with the options specified.. The <code>email</code> call with all options looks like:</p> <pre class="prettyprint">email { to =&gt; 'user@example.ru', subject =&gt; 'I found a bug in your site', msg =&gt; 'BlahBlahBlah', attachment =&gt; ['/sbin/rm'], type =&gt; 'text', headers =&gt; { "X-Mailer" =&gt; 'This fine Dancer application', "X-Accept-Language" =&gt; 'en' }, encoding =&gt; 'base64', };</pre> <h2><a name="simple_example"></a>Simple example</h2> <pre class="prettyprint">use Dancer; use Dancer::Plugin::Email; post '/contact' =&gt; sub { email { to =&gt; '...', subject =&gt; '...', message =&gt; $msg, }; };</pre> <h2><a name="code_recipes"></a>Code recipes</h2> <p>Below we give you some code recipes to show how to use Dancer::Plugin::Email</p> <h3><a name="errors_handling"></a>Errors handling</h3> <pre class="prettyprint"># Handle Email Failures post '/contact' =&gt; sub { my $msg = email { to =&gt; '...', subject =&gt; '...', message =&gt; $msg, encoding =&gt; 'base64', }; warn $msg-&gt;{string} if $msg-&gt;{type} eq 'failure'; };</pre> <h2><a name="adding_additional_email_headers"></a>Adding additional email headers</h2> <pre class="prettyprint">email { to =&gt; '...', subject =&gt; '...', message =&gt; $msg, headers =&gt; { "X-Mailer" =&gt; 'This fine Dancer application', "X-Accept-Language" =&gt; 'en' } };</pre> <h2><a name="sending_text_and_html_multi_part_messages"></a>Sending text and HTML multi-part messages</h2> <pre class="prettyprint">email { to =&gt; '...', subject =&gt; '...', type =&gt; 'multi', # must be set to "multi" to send both parts message =&gt; { text =&gt; $txt, html =&gt; $html, }, };</pre> <h1><a name="author"></a>AUTHOR</h1> <p>Kindly authored by Andrew Inishev, a student participating in the Google Code-In, mentored by David Precious - thanks Andrew for your contribution!</p> </div> Dynamic AJAX charting with Dancer and Highcharts http://advent.perldancer.org/2011/14 perl http://advent.perldancer.org/2011/14 Wed, 14 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="dynamic_ajax_charting_with_dancer_and_highcharts"></a>Dynamic AJAX charting with Dancer and Highcharts</h1> <p>Let's build a real simple AJAX-based application using Dancer to feed data to <a href="http://www.highcharts.com/">Highcharts</a> to display a real-time graph of the load average of the webserver the application is running on.</p> <p>We'll serve up a page with the appropriate Javascript to utilise Highcharts, polling via AJAX requests to fetch fresh data from our Dancer app regularly.</p> <p>First, we'll need to write a simple Dancer app to serve up the HTML, along with handling AJAX requests for the current load average.</p> <p>I scaffolded the app with <code>dancer -a ajaxchartingdemo</code>, then edited <code>lib/ajaxchartingdemo.pm</code> to contain the following simple code:</p> <pre class="prettyprint">package ajaxchartingdemo; use Dancer ':syntax'; use Dancer::Plugin::Ajax; use Unix::Uptime; get '/' =&gt; sub { template 'index'; }; ajax '/getloadavg' =&gt; sub { { timestamp =&gt; time, loadavg =&gt; ( Unix::Uptime-&gt;load )[0] }; }; true;</pre> <p>I want that hashref the <code>ajax</code> handler is returning to be serialised to JSON for me, so I edited the <code>config.yml</code> file and added:</p> <pre class="prettyprint">serializer: 'JSON'</pre> <p>With that done, I then had to download <a href="http://www.highcharts.com/">HighCharts</a> into <code>public/javascripts/highcharts</code>, and edit <code>views/index.tt</code> to contain the appropriate HTML and mostly Javascript to display the chart.</p> <p>I'm not going to repeat the whole of that here, as that part isn't Dancer-related, and you can <a href="https://github.com/bigpresh/dancer-ajaxloadavgchart-example/blob/master/views/index.tt">see it on GitHub</a> anyway, but it was simple stuff; the part which fetched the loadavg using an AJAX request (courtesy of jQuery) was as simple as:</p> <pre class="prettyprint">setInterval(function() { $.getJSON('/getloadavg', function(response) { var point = [ response.timestamp * 1000, response.loadavg - 0 ];; series.addPoint(point, true, shiftalong); }) }, 2000);</pre> <p>With all this done, we're ready to see what we get!</p> <p>During the advent calendar period, you can try it out live at:</p> <p><a href="http://advent.perldancer.org:4600/">http://advent.perldancer.org:4600/</a></p> <p>(This will likely be discontinued in the near future, but the demo app will still be available on GitHub for you to try yourself.)</p> <p>You should be presented with a pretty graph, which updates automatically:</p> <img src="/images/2011/14/chart-screenshot.png"> <h2><a name="getting_the_example_app_code"></a>Getting the example app code</h2> <p>The example application is available on GitHub:</p> <p><a href="https://github.com/bigpresh/dancer-ajaxloadavgchart-example">https://github.com/bigpresh/dancer-ajaxloadavgchart-example</a></p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious, with thanks to <code>ua</code> on IRC for the idea and <code>odyniec</code> for help whilst I was hurriedly writing this post.</p> </div> Serving Files with Dancer::Plugin::DirectoryView and Dancer::Plugin::Auth::Htpasswd http://advent.perldancer.org/2011/13 perl http://advent.perldancer.org/2011/13 Tue, 13 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="serving_files_with_dancer__plugin__directoryview_and_dancer__plugin__auth__htpasswd"></a>Serving Files with Dancer::Plugin::DirectoryView and Dancer::Plugin::Auth::Htpasswd</h1> <p>A while ago I was converting a simple PHP website to Dancer, and moving it from being deployed on Apache to Starman. There wasn't a lot of code, so rewriting went quickly -- but, the site used a few specific features of Apache, namely directory indexes (courtesy of <a href="http://httpd.apache.org/docs/current/mod/mod_autoindex.html">mod_autoindex</a>) to allow user access to directories/files on the server, and <code>htpasswd</code> files to password-protect some of those directories.</p> <p>I could just deploy the new Dancer website on Apache and keep using those goodies, but I thought that it would be nice if Dancer itself provided similar features. So, I created two plugins that do just that: <a href="https://metacpan.org/module/Dancer::Plugin::DirectoryView">Dancer::Plugin::DirectoryView</a> and <a href="https://metacpan.org/module/Dancer::Plugin::Auth::Htpasswd">Dancer::Plugin::Auth::Htpasswd</a>. Let me now show you how to use them.</p> <h2><a name="directory_indexes"></a>Directory Indexes</h2> <p>Let's say we have a <code>files</code> directory under <code>public</code>, and we'd like to allow users to browse it and download files. Enabling directory access is as simple as including the plugin in our Dancer application:</p> <pre class="prettyprint">package MyWebApp; ... use Dancer::Plugin::DirectoryView;</pre> <p>And updating the configuration file (<code>config.yml</code>) to tell the plugin which directory should be made available, and at which URL:</p> <pre class="prettyprint">plugins: DirectoryView: url: /pub root_dir: files</pre> <p>That's it -- now, if we launch our app and point the browser at the <code>/pub</code> URL, we'll see the contents of the directory:</p> <img src="/images/2011/13/screenshot-1-590.png"> <h2><a name="protecting_directories_with_htpasswd_files"></a>Protecting Directories with Htpasswd Files</h2> <p>As you might have noticed on the screenshot, there's a <code>secret</code> directory under <code>files</code>. It contains some super secret data that should only be available to authorized users, so now we're going to protect it using a <code>htpasswd</code> file.</p> <p>First, let's create the <code>htpasswd</code> file and an user, named "alice":</p> <pre class="prettyprint">$ htpasswd -c htpasswd alice</pre> <p>Once it is created, we need to put the <code>htpasswd</code> file in a safe location outside of the public directory, so let's create a new directory <code>passwd</code> and store the file in there.</p> <p>(If you're migrating from Apache and already have the <code>htpasswd</code> file, you just need to copy it to your Dancer application.)</p> <p>In our Dancer application, we include the Auth::Htpasswd plugin:</p> <pre class="prettyprint">package MyWebApp; ... use Dancer::Plugin::Auth::Htpasswd;</pre> <p>Now, we need to update our configuration file and add settings for the plugin. We'll tell it to protect the <code>/pub/secret</code> path, and to use the <code>htpasswd</code> file we just created:</p> <pre class="prettyprint">plugins: "Auth::Htpasswd": paths: "/pub/secret": realm: "Secret Files" passwd_file: passwd/htpasswd</pre> <p>The <code>realm</code> parameter lets us set the text that will be shown to the user in the login window displayed by the browser.</p> <p>Let's see if our protection works. We restart the application and try to access the <code>/pub/secret/</code> URL:</p> <img src="/images/2011/13/screenshot-2-590.png"> <p>Great, our confidential files are safe. Only when we log in as "Alice", we'll be able to access them:</p> <img src="/images/2011/13/screenshot-3-590.png"> <h1><a name="author"></a>AUTHOR</h1> <p><a href="http://odyniec.net/">Michal Wojciechowski</a>, <code>&lt;odyniec@odyniec.net&gt;</code></p> </div> Dancer workshop at London Perl Workshop 2011 http://advent.perldancer.org/2011/12 perl http://advent.perldancer.org/2011/12 Mon, 12 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="dancer_workshop_at_london_perl_workshop_2011"></a>Dancer workshop at London Perl Workshop 2011</h1> <p>Saturday, 12 November 2011 was the 2011 London Perl Workshop, held in the Cavendish Street Campus of Westminster University.</p> <p>Andrew Solomon ran <a href="http://conferences.yapceurope.org/lpw2011/talk/3888">a hands-on training session</a> entitled "Web development for beginners using Dancer", to help beginners to learn to use Dancer, Template Toolkit, learn the MVC concept, and understand structuring code for maintainability and using object orientation.</p> <p>In all, there were 19 attendees (in a room with only 18 terminals).</p> <p>Andew said that the students were very engaged, asking (and answering) valid questions until the end of the 2.5 hour class, and that almost all of them had a working web application up and running by the end of the session.</p> <p>Many of the students reported that they found it much simpler to get started than they'd expected.</p> <p>A quote from an attendee:</p> <p>"... if I do ever try to get something up and running in Perl, I feel like I could probably do it with Dancer"</p> <p>I also asked Andrew himself for his opinion, and he said:</p> <p>"make sure you say how much I enjoyed presenting Dancer! The way high level concepts and the actual code are aligned, I think that Dancer will give Perl a place in the 'standard' university IT curriculum before too long."</p> <p>All in all, it seems the workshop was well-received, helping raise the profile of Dancer and feedback from attendees confirms that Dancer is doing well at being a user-friendly framework which is easy for beginners to start working with, with an easy learning curve.</p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious</p> </div> Dancer 2, a Roadmap http://advent.perldancer.org/2011/11 perl http://advent.perldancer.org/2011/11 Sun, 11 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="dancer_2__a_roadmap"></a>Dancer 2, a Roadmap</h1> <p>OK, before we start, let's make it clear: this article won't answer the question everyone has in mind: <i>When ???!!!??</i>.</p> <p>But it will give a complete overview of what has been done and what remains to be done. This should give you a good overview of where we are and will also enlight how you can help.</p> <h2><a name="dsl"></a>DSL</h2> <p>Of course the very first milestone is to have a working DSL over the new core. It has been my main target and it's almost finished.</p> <p>All of the keywords we have in Dancer 1 are supported at the time of this writing except <code>send_error</code> and <code>load_app</code>. All the other keywords you won't find in Dancer 2 that exist in Dancer 1 will be deprecated (like <code>before_template</code> or <code>load</code> for instance).</p> <p>I plan to finish the DSL very soon (it's my top-priority for now) so I suppose it's a matter of weekends as that's when I'm able to work on Dancer 2.</p> <h2><a name="core_engines"></a>Core Engines</h2> <p>We can find several <i>engines</i> in the Dancer distribution. Engines are specific components dedicated to handle sessions, templates, loggers and serializers.</p> <p>The lists below show engines we found in Dancer 1, those in bold are the one ported in Dancer 2.</p> <ul> <li><a name="item_Logger_engines"></a><b>Logger engines</b> <p>Capture, <b>Console</b>, Diag, <b>File</b>, Note, Null.</p> </li> <li><a name="item_Session_engines"></a><b>Session engines</b> <p>Simple, <b>YAML</b>.</p> </li> <li><a name="item_Template_engines"></a><b>Template engines</b> <p>Simple, <b>TemplateToolkit</b>.</p> </li> <li><a name="item_Serializer_engines"></a><b>Serializer engines</b> <p><b>Dumper</b>, <b>JSON</b>, Mutable, <b>XML</b>, <b>YAML</b>.</p> </li> </ul> <p>As you can see, there is still some work to do there, but it should not take too long as all the <code>Moo</code> roles used to build engines are ready. Also some of these engines are really... dumb to implement!</p> <h2><a name="plugins"></a>Plugins</h2> <p>The support for plugins is namely the <code>Dancer::Plugin</code> module. In Dancer 2, lots of magic happens there because a plugin in Dancer 2 is actually a DSL role that is consumed into the core DSL (which itself is built via a default DSL role).</p> <p>The interesting part is that all the role composition is hidden by the syntactic sugar of <code>Dancer::Plugin</code>, the very same syntax of Dancer 1 is possible, but behind the scene, there are <code>Moo</code> roles consumed, it's insanely powerful and elegant! (I can say that without sounding pretentious, because it's not my idea, but one of mst's ;).</p> <p>So, in Dancer 1, we have one plugin shipped with the core, it's <code>Dancer::Plugin::Ajax</code> which provides a handy keyword <code>ajax</code> to define ... Ajax routes.</p> <p>That plugin has been ported to Dancer 2 and works as expected.</p> <h2><a name="dancer__test"></a>Dancer::Test</h2> <p>The <code>Dancer::Test</code> module is a helper to get Dancer tests, it provides lots of handy function to test a Dancer application. The most used one, <code>dancer_response</code> is implemented, but all the other helpers remain to be done.</p> <p>Also, due to design changes, Dancer::Test might not work exactly in the same conditions as with Dancer 1. So maybe some work here to polish it a bit more.</p> <h2><a name="ecosystem"></a>Ecosystem</h2> <p>The last part of the job will be quite a big challenge: we'll need to test every module on CPAN in the Dancer ecosytem with Dancer 2, see if it works and if not, patch it and send the patch to the author.</p> <p>This is going to be - I think - a very interesting marathon, and I think the best way to do it will be in a hackaton dedicated to the task.</p> <h2><a name="ok__so_____when_"></a>OK, so ... When ?</h2> <p>Well, not for Christmas! But we can say Dancer 2 will be out in 2012, is that precise enough? No? Well, didn't I say at the beginning that I won't answer that <i>when</i> question?</p> <h2><a name="author"></a>Author</h2> <p>This article was written by Alexis Sukrieh and reviewed by David Precious, for the Perl Dancer Advent Calendar 2011.</p> </div> Portable file handling in Dancer apps http://advent.perldancer.org/2011/10 perl http://advent.perldancer.org/2011/10 Sat, 10 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="portable_file_handling_in_dancer_apps"></a>Portable file handling in Dancer apps</h1> <p>If you want your app to be easily portable between different systems and different platforms, it's important not to write file-handling code in a platform-specific way.</p> <p>Dancer provides some utility functions in <a href="https://metacpan.org/module/Dancer::FileUtils">Dancer::FileUtils</a> which help you to deal with files in a portable manner.</p> <h2><a name="portable_file_paths"></a>Portable file paths</h2> <p>Depending on the platform, directory separators may vary.</p> <p>To get round this, <a href="https://metacpan.org/module/Dancer::FileUtils/path">Dancer::FileUtils/path</a> allows you to assemble paths easily:</p> <pre class="prettyprint">my $views_dir = Dancer::FileUtils::path(setting('appdir'), 'views');</pre> <p><code>path()</code> uses <a href="https://metacpan.org/module/File::Spec">File::Spec</a> internally.</p> <h2><a name="reading_file_contents"></a>Reading file contents</h2> <p><a href="https://metacpan.org/module/Dancer::FileUtils/read_file_content">Dancer::FileUtils/read_file_content</a> provides a way to quickly retrieve the content of a file, and behaves sensibly depending on the context it was called in:</p> <pre class="prettyprint"># Read entire file contents into $content: my $content = Dancer::FileUtils::read_file_content($filename); # Read each line of file into @lines: my @lines = Dancer::FileUtils::read_file_content($filename);</pre> <p>The application's <code>charset</code> setting will be taken into account when opening the file, and will default to UTF-8 if no charset setting is present, so UTF-8 data should Just Work.</p> <p><a href="https://metacpan.org/module/Dancer::FileUtils/read_glob_content">Dancer::FileUtils/read_glob_content</a> works in the same manner, but takes an open filehandle, reads the content from it, and <i>closes the handle</i>.</p> <h2><a name="opening_a_file"></a>Opening a file</h2> <p><a href="https://metacpan.org/module/Dancer::FileUtils/open_file">Dancer::FileUtils/open_file</a> provides a way to open a file, taking the app's <code>charset</code> setting into account, and returns a filehandle:</p> <pre class="prettyprint">my $fh = open_file('&lt;', $file) or die ...;</pre> <h2><a name="setting_filehandle_mode"></a>Setting filehandle mode</h2> <p>If you have a filehandle you've opened yourself, you can use <a href="https://metacpan.org/module/Dancer::FileUtils/set_file_mode">Dancer::FileUtils/set_file_mode</a> to apply the app's <code>charset</code> setting (or default to UTF-8) encoding.</p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious</p> </div> Profiling Dancer apps with Dancer::Plugin::NYTProf http://advent.perldancer.org/2011/9 perl http://advent.perldancer.org/2011/9 Fri, 9 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="profiling_dancer_apps_with_dancer__plugin__nytprof"></a>Profiling Dancer apps with Dancer::Plugin::NYTProf</h1> <p>Profiling is a good way to find bottlenecks in your code - if you find your app isn't as fast as you would like, it's good to be able to see where the time is being spent, so you know what areas of your code you should try to optmise to speed thing (although do be wary that <a href="http://en.wikipedia.org/wiki/Program_optimization">premature optimisation is the root of all evil</a>).</p> <p>There are various profilers available, but <a href="https://metacpan.org/module/Devel::NYTProf">Devel::NYTProf</a> from Tim Bunce is very popular and provides useful, detailed, readable output.</p> <p>But how can you easily profile a Dancer app?</p> <p><a href="https://metacpan.org/module/Dancer::Plugin::NYTProf">Dancer::Plugin::NYTProf</a> provides easy profiling - by simply loading the plugin, you'll have the detailed, helpful profiling provided by Devel::NYTProf. Each individual request is profiled, and going to the URL <code>/nytprof</code> will present a list of profile results; selecting one will serve up the pretty HTML report generated by Devel::NYTProf.</p> <h3><a name="using_the_plugin"></a>Using the plugin</h3> <p>The plugin will work by default without any configuration required - it will default to writing profiling data into a dir named profdir within your Dancer application's appdir, present profiling output at /nytprof (not yet configurable), and profile all requests.</p> <p>To start using it, simply load it in your app as you would any other plugin:</p> <pre class="prettyprint">use Dancer::Plugin::DevelNYTProf;</pre> <p>Start your app, make some requests to it, then go to <code>/nytprof</code> (e.g. <a href="http://localhost:3000/nytprof">http://localhost:3000/nytprof</a>) and you should receive a list of profile runs.</p> <p>Clicking one should bring up the usual pretty Devel::NYTProf output.</p> <h3><a name="security_warning"></a>Security warning</h3> <p>At this time, I would not recommend loading this plugin in your public-facing production environment, as it hasn't been extensively checked for vulnerabilities, particularly in the code which executes <code>nytprofhtml</code> to generate the HTML reports. I would recommend using this in your development environment only.</p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious</p> <p>This article was a little rushed, as it's pub time; I will try to extend it a little soon and add screenshots, but in the meantime it should be a taster on getting started profiling.</p> </div> Dancer 2, or Why I Rewrote Everything http://advent.perldancer.org/2011/8 perl http://advent.perldancer.org/2011/8 Thu, 8 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="dancer_2__or_why_i_rewrote_everything"></a>Dancer 2, or Why I Rewrote Everything</h1> <p>If you've been following developments in the Perl Dancer ecosystem recently, you might be aware that a complete rewrite of the core is on the way.</p> <p>I haven't advertised what I did, what happened and what is the plan, so this Advent calendar is a perfect opportunity to do it.</p> <p>In this article, I'll explain the reasons behind this decision and what were the most important targets of this rewrite.</p> <p>Firstly, though, it should be made clear that there's no need to panic - Dancer 2 will strive for backwards compatibility, providing the same user-friendly DSL as Dancer, so your existing Dancer apps should work with Dancer 2 with only minimal changes.</p> <h2><a name="a_bit_of_history"></a>A bit of history</h2> <p>Maybe I should start with how the development of Dancer started in the first place. It was in summer 2009, I was working at Yoolink at that time and we were making a lot of use of the Ruby language.</p> <p>I discovered the <a href="http://sinatrarb.com/">Sinatra</a> micro-framework at that time and found it really exciting. After a quick glance, it appeared that there was nothing similar in the Perl ecosystem at that time, so I decided it would be an interesting challenge to port it to Perl.</p> <p>Thus, the first Dancer prototype was born.</p> <p>The prototype evolved quickly and after a couple of months, the project was up available on CPAN and the source code hosted was pushed on GitHub.</p> <p>A community of motivated users emerged and after a year, Dancer was well-known and had quite a good reputation of being very easy to use and making web development fun with Perl.</p> <p>Needless to say that when you are powered by your community's energy, it's very hard to stop the flow for changing major design decisions.</p> <p>When I look back at what happened exactly, I'd say that Dancer was a very well-received and successful <i>prototype</i> of the easiest web DSL we could do with Perl.</p> <p>From that perspective, I'm very proud of Dancer, because from an end-user point of view, it's really kicking asses: it is intuitive as hell, it stays out of the way and gives you all the freedom to think of the one thing which matters most: your application.</p> <p>But, you know the drill, perfect software does not exist, there is always something we can do better. In the case of Dancer, there were a couple of design decisions which needed to be taken care of.</p> <p>Actually, when I took the time to think about it, I realized there were two major drawbacks in the design that would make it difficult for Dancer to continue its epic growth:</p> <ul> <li><a name="item_Globals_and_singletons"></a><b>Globals and singletons</b> <p>The major source of issues with edge-cases, scalability and maintenance in Dancer is the use of globals. Many developers who happened to hack around the core know that.</p> <p>I wanted Dancer to get rid of that design flaw.</p> </li> <li><a name="item_Consistent_and_object_oriented_core_API"></a><b>Consistent and object-oriented core API</b> <p>As Dancer has been built iteratively, the Core API was never a real target for me, that means hacking around the core is quite difficult, and not consistent. I wanted Dancer to be a clean DSL over a complete object-oriented API.</p> </li> </ul> <p>As a side-effect of these tow main decisions, I also wanted the core to follow the <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a>, in order to ensure a sane class/method hierarchy.</p> <p>I also wanted a strong concept of scope to be implemented in the rewrite, so that everything that happens within a caller would be scoped there (no more apps collisions, support for multiple engines per app, per-apps settings, etc).</p> <h2><a name="dancer2__the_origins"></a>Dancer2, the origins</h2> <p>All this was in my mind for quite a long time and I was wondering how I could do these changes while maintaining Dancer's evolutions.</p> <img src="http://farm4.staticflickr.com/3137/3067741605_83b86dda64.jpg" title="Dancer 2 is to Dancer 1 what Wolverine is to a human being: same shape, better skeleton." /> <p>I should also mention that among the contributors of Dancer, there were a couple of guys very productive and motivated, and I granted them a commit bit quite quickly. Soon enough, we created what we called the <i>Core Team</i>, a group of developers who knows Dancer well and who are able to process pull requests.</p> <p>Thanks to them (SawyerX, Franck Cuny, David Precious, Damien Krotkine and Alberto Sim&#xf5;es) Dancer had a strong team to take care of daily maintenance duties. I also made SawyerX a co-maintainer on CPAN so that he could become our <i>Release Manager</i>.</p> <p>All this setup was perfect for the Dancer 2 project: I had all in place to step aside, let the maintenance in the Core Team hands and focus entirely on the rewrite.</p> <p>Then, I decided to create a new repo and experiment these design ideas on a complete new prototype, to see where I could end up. At that time, I went to discuss with Matt S Trout (mst) on IRC, in order to brainstorm the new design. Matt also happened to become my <i>design architect mentor</i>, giving me ideas, tips and suggestions when I faced subtle design issues to solve.</p> <p>Matt sounded encouraging and provided lots of useful and enlightened suggestions to help me start.</p> <p>One of his suggestions was to use Moo to get a complete Moose-ish object system for the core yet fast and lightweight. That happened to be one of the more helpful choices to enforce a better design.</p> <p>My strategy was to start a new project, with one target in mind: support the DSL of Dancer, but make it a true DSL: a layer over a complete, consistent and object-oriented core.</p> <p>Mainly the idea was that I could write a Dancer app with raw objects if I wanted to. This would open new doors and allow strong flexibility.</p> <h2><a name="where_are_we"></a>Where are we?</h2> <p>I won't give you more details on the Core API in this article, neither will I give a roadmap for Dancer 2, because these topics will be covered in other articles, but I'll just give you a quick overview of Dancer 2 as of today.</p> <p>The repository is public on <a href="http://github.com/PerlDancer/Dancer2">Github</a>, you're very welcome to clone it if you want to test your app with Dancer 2. If you do so, please send me an email with your feedback, that will help a lot!</p> <p>Let's give it a try:</p> <pre class="prettyprint">$ echo "use Dancer; get '/' =&gt; sub { 2 }; start" &gt; test.pl $ perl -Ilib ./test.pl &amp; HTTP::Server::Simple::PSGI: You can connect to your server at http://localhost:3000/ $ curl http://0:3000/ 2</pre> <p>Nothing special here, we have our hello world app powered by Dancer2. If you look more precisely, you'll see that nearly all the DSL of Dancer 1 is already supported in Dancer 2.</p> <p>To get a quick teaser about the internal changes we have, let's enable the core debug messages:</p> <pre class="prettyprint">$ DANCER_DEBUG_CORE=1 perl -Ilib ./test.pl &amp; core: binding app to main core: [main] -&gt; get(/, CODE(0x172a1b0)) core: [main] -&gt; start() HTTP::Server::Simple::PSGI: You can connect to your server at http://localhost:3000/ $</pre> <p>As you can guess, with 2, for each package that uses Dancer, we have a <code>Dancer::Core::App</code> object (here for <i>main</i>). The DSL is just syntactic sugar over method calls to that object.</p> <p>Well, that's all for this introduction, again, you're welcome to test Dancer 2, just clone the repo and run your app with it, just don't forget to mail me or the list about how it went, that would be helpful.</p> <p>In the next article, I'll go over all the core API design, explaining all the entities we have and how it fits with the DSL.</p> <h2><a name="author"></a>AUTHOR</h2> <p>This article was written by Alexis Sukrieh and reviewed by David Precious, for the Perl Dancer Advent Calendar 2011.</p> </div> Building a blog engine using Perl Dancer http://advent.perldancer.org/2011/7 perl http://advent.perldancer.org/2011/7 Wed, 7 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="building_a_blog_engine_using_perl_dancer"></a>Building a blog engine using Perl Dancer</h1> <p>In this <a href="http://www.youtube.com/watch?v=NGX5pgKWVoc">screencast</a> we build a simple blog engine using Dancer.</p> <p>If you are on MS Windows start by downloading <a href="http://padre.perlide.org/">Padre on Strawberry Perl</a> which already has everything we need. On other systems you'll have to install <a href="https://metacpan.org/module/Dancer">Dancer</a>, <a href="https://metacpan.org/module/File::Slurp">File::Slurp</a> and <a href="https://metacpan.org/module/Template::Toolkit">Template::Toolkit</a>.</p> <iframe width="500" height="390" src="http://www.youtube.com/embed/NGX5pgKWVoc" frameborder="0" allowfullscreen></iframe> <p>The application we build is going to be called <a href="http://dwimmer.org/">Dwimmer</a>. We need to use the command line to build the skeleton of our application by typing in</p> <pre class="prettyprint">dancer -a Dwimmer</pre> <p>This will create a directory called Dwimmer and all the files necessary to build a Dancer application.</p> <p>The <code>bin/app.pl</code> file is just a simple launcher for a web server on port 3000</p> <p>The real code is in <code>lib/Dwimmer.pm</code></p> <p>The templates are in the <code>views/</code> directory.</p> <p>This is the full code:</p> <pre class="prettyprint">package Dwimmer; use Dancer ':syntax'; use File::Slurp qw(read_file write_file); our $VERSION = '0.01'; get '/' =&gt; sub { my $filename = config-&gt;{dwimmer}{json}; my $json = -e $filename ? read_file $filename : '{}'; my $data = from_json $json; template 'index', {data =&gt; $data}; }; get '/page' =&gt; sub { template 'page'; }; post '/page' =&gt; sub { my $filename = config-&gt;{dwimmer}{json}; my $json = -e $filename ? read_file $filename : '{}'; my $data = from_json $json; my $now = time; $data-&gt;{$now} = { title =&gt; params-&gt;{title}, text =&gt; params-&gt;{text}, }; write_file $filename, to_json($data); redirect '/'; }; true;</pre> <p>The module <a href="https://metacpan.org/module/File::Slurp">File::Slurp</a> provides two functions for reading and writing files in a simple way.</p> <p>Dancer is route based so you for each page out there you need to define a route. You can even differentiate between the HTTP METHOD types such as <code>GET</code> and <code>POST</code> though they are written in lower case in Dancer.</p> <p>We changed the config.yml file in the root of the application. Commented out the</p> <pre class="prettyprint"># template: "simple"</pre> <p>and enabled</p> <pre class="prettyprint">template: "template_toolkit" engines: template_toolkit: encoding: 'utf8'</pre> <p>Later we also added the following</p> <pre class="prettyprint">dwimmer: json: c:\work\dwimmer.json</pre> <p>to set where the json "database" is located. (Our home made NoSQL database.)</p> <p>We edited the file <code>views/index.tt</code> file replacing all of its content with simple HTML linking to the <i>page</i>.</p> <pre class="prettyprint">Hi &lt;a href="/page"&gt;add a new entry&lt;/a&gt;</pre> <p>clicking on that link would generate a 404-error so we also created a route to serve the request:</p> <pre class="prettyprint">get '/page' =&gt; sub { template 'page'; };</pre> <p>The page template is a simple form:</p> <pre class="prettyprint">&lt;form method="POST"&gt; &lt;input name="title" size="80"/&gt;&lt;br /&gt; &lt;textarea name="text" rows="20" cols="80"&gt; &lt;/textarea&gt;&lt;br /&gt; &lt;input type="submit" value="Post" /&gt; &lt;/form&gt;</pre> <p>Note we set the submission method to be POST! Hence when you submit this form you get a 404 error. We have to implement a separate route to handle this post request:</p> <pre class="prettyprint">post '/page' =&gt; sub { my $filename = config-&gt;{dwimmer}{json}; my $json = -e $filename ? read_file $filename : '{}'; my $data = from_json $json; my $now = time; $data-&gt;{$now} = { title =&gt; params-&gt;{title}, text =&gt; params-&gt;{text}, }; write_file $filename, to_json($data); redirect '/'; };</pre> <p>In this code the <i>config</i> method returns the all the configuration options where we already saved the name of the json file. <code>-e $filename</code> checks if the file exists. If it does, we read it in to the <code>$json</code> variable; if not then we assign to it a JSON string representing an empty hash.</p> <pre class="prettyprint">my $json = -e $filename ? read_file $filename : '{}';</pre> <p><code>from_json</code> is a built-in Dancer function turning a json string into a Perl data structure.</p> <p>We then add a new entry to our "database" with the key being the timestamp and having a hash containing the title and text as received from the user.</p> <pre class="prettyprint">write_file $filename, to_json($data);</pre> <p>This will write back the whole data structure after turning it into a json file.</p> <p>The last line redirects the user to the main page.</p> <p>This code will save the new blog submission to the json file but won't display yet.</p> <p>For that we changed the main route copying the data reading code to it. It then passes the data to the template call.</p> <pre class="prettyprint">get '/' =&gt; sub { my $filename = config-&gt;{dwimmer}{json}; my $json = -e $filename ? read_file $filename : '{}'; my $data = from_json $json; template 'index', {data =&gt; $data}; };</pre> <p>The <code>index.tt</code> template itself had to be changed as well to include this:</p> <pre class="prettyprint">&lt;% FOR e IN data.keys.sort %&gt; &lt;hr /&gt; &lt;h2&gt;&lt;% data.$e.title %&gt;&lt;/h2&gt; &lt;% data.$e.text %&gt; &lt;% END %&gt;</pre> <p>Which will display all the results from the data hash.</p> <p>That's it. <a href="http://dwimmer.org/">Dwimmer</a> is ready.</p> <p>Well, sort of.</p> <h1><a name="author"></a>AUTHOR</h1> <p><a href="http://szabgab.com/">Gabor Szabo</a>, <code>&lt;szabgab@gmail.com&gt;</code></p> </div> Flexible exceptions handling with Dancer::Exception http://advent.perldancer.org/2011/6 perl http://advent.perldancer.org/2011/6 Tue, 6 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="flexible_exceptions_handling_with_dancer__exception"></a>Flexible exceptions handling with Dancer::Exception</h1> <p>Among the new features added in Dancer, here is an important albeit not very visible one.</p> <p>When running a Dancer application, sometimes things get wrong, and an exception is raised. In earlier versions, Dancer was using <code>croak</code>. That's not bad, but when trying to catch an exception, it's not trivial to programatically know if it was raised by Dancer's code, or the web application's code, or some other module used.</p> <p>Now, all exceptions raised in Dancer's code are <a href="https://metacpan.org/module/Dancer::Exception">Dancer::Exception</a>s. It's also possible for the developer of the web application to create and raise their own Dancer::Exception.</p> <p>Technically, a Dancer's exception is an object inheriting from <a href="https://metacpan.org/module/Dancer::Exception::Base">Dancer::Exception::Base</a>, but may be composed from different roles, enabling different <i>flavours</i> of exceptions. There is one special flavour, called 'Core'. All exceptions raised by Dancer's core code are of this flavour, or derive from it. Dancer users are able to create new flavours, and new exceptions of these flavours.</p> <h1><a name="catch_dancer_s_core_exceptions"></a>Catch Dancer's core exceptions</h1> <p>First things first, exceptions means that there is a way to catch them. For that, Dancer technically relies on the very good <a href="https://metacpan.org/module/Try::Tiny">Try::Tiny</a>, but provides itself a slightly modified version of <code>try</code> and <code>catch</code>. Just use <a href="https://metacpan.org/module/Dancer::Exception">Dancer::Exception</a> and you're set.</p> <h2><a name="try_and_catch_exceptions"></a>Try and catch exceptions</h2> <pre class="prettyprint">use Dancer; use Dancer::Exception qw(:all); get '/' =&gt; sub { try { do_some_stuff(); } catch { # ah, something bad happened }; };</pre> <p><b>Beware</b>, the <code>try</code> and <code>catch</code> syntax requires to append a semi-colon <code>;</code> at the end.</p> <h2><a name="core_or_non_core_exceptions_"></a>Core or non core exceptions ?</h2> <p>When catching an exception, one of the first thing to do is testing if it's a core exception (coming from Dancer's code). To do that, use the <code>does</code> keyword:</p> <pre class="prettyprint">use Dancer; use Dancer::Exception qw(:all); get '/' =&gt; sub { try { do_some_stuff(); } catch { my ($exception) = @_; if ($exception-&gt;does('Core')) { # issues appeared in Dancer's code say "got a core exception: " . $exception-&gt;message; $exception-&gt;rethrow; } else # handle the issue } }; };</pre> <p>This example shows the usage of:</p> <ul> <li><a name="item_does"></a><b>does</b> <p>used to test the flavour of an exception</p> </li> <li><a name="item_rethrow"></a><b>rethrow</b> <p>if you just caught an exception, but you actually don't want to handle it, just <code>rethrow</code> it! It'll still come from the point it was originally emited from.</p> </li> <li><a name="item_message"></a><b>message</b> <p>exceptions contain a message, and the &lt;message()&gt; method returns it as a string. However, Dancer's exception objects overload stringification and string comparison just fine, so you can just <code>print $exception</code></p> </li> </ul> <h1><a name="create_your_own_exceptions"></a>Create your own exceptions</h1> <p><a href="https://metacpan.org/module/Dancer::Exception">Dancer::Exception</a> would be of limited use if it were just there to properly raise core exceptions. It is also possible for Dancer web developers to register new exception flavours, raise these exceptions, and catch and test them.</p> <h2><a name="register_your_custom_exception"></a>Register your custom exception</h2> <p>Before being able to raise a home made exception, you need to register it. Every exception has a message, but Dancer exceptions actually have a message pattern. Let's see what that means in an example:</p> <pre class="prettyprint">use Dancer::Exception qw(:all); register_exception('NoPermission', message_pattern =&gt; "not enough permission: %s" );</pre> <p>This will register a new kind of exception, that can be raised if the user tries to access a part of a website he doesn't have permission to.</p> <p>It's also possible to register new exceptions that are composed from other exceptions. We can consider that the 'NoPermission' exception is too vague, and we need two sub exceptions to specify if the login or the password was wrong:</p> <pre class="prettyprint">register_exception('InvalidLogin', message_pattern =&gt; "invalid login '%s'" composed_from =&gt; [ 'NoPermission' ] ); register_exception('InvalidPassword', message_pattern =&gt; "invalid password" composed_from =&gt; [ 'NoPermission' ] );</pre> <p>See how we set the message pattern? We want to display the wrong login, but not the wrong password.</p> <p>Now, take a look at this piece of code:</p> <pre class="prettyprint">use Dancer; use Dancer::Exception qw(:all); any ['get', 'post'] =&gt; '/login' =&gt; sub { try { _login(params-&gt;{'login'}, params-&gt;{'password'}); } catch { my ($exception) = @_; if ($exception-&gt;does('NoPermission')) { # deal with it template 'no permission', { message =&gt; $exception-&gt;message } } else { # we can't handle this $exception-&gt;rethrow; } }; }</pre> <p>What's great is that if the exception was an <code>InvalidLogin</code>, the message returnd by <code>&lt;$exception-</code>message&gt;&gt; will be:</p> <pre class="prettyprint">"not enough permission: invalid login 'foo'"</pre> <p>That's because message patterns are called one by one bottom up. But to fully understand the effect, one must see the function <code>_login</code>, which shows how to <b>raise</b> an exception.</p> <h2><a name="raise_a_custom_exception"></a>Raise a custom exception</h2> <p>Now that we have registered some exceptions, and seen how to catch them, let's see how to raise them. It's simple, it's done using the <code>raise</code> keyword:</p> <pre class="prettyprint">sub _login { my ($login, $password) = @_; _check($login) or raise InvalidLogin =&gt; $login; _check_credential($login,$password) or raise 'InvalidPassword'; }</pre> <p><code>raise</code> takes one or two parameters: the name of the exception's flavour, and the parameter to its message pattern. Here we pass the login to the <code>InvalidLogin</code>.</p> <h1><a name="dancer_exceptions_are_not_dancer_errors"></a>Dancer exceptions are not Dancer errors</h1> <p>On common mistake is to think that Dancer exceptions are the same than Dancer errors. They are not. Dancer::Exceptions are thrown when something goes wrong, either in core code, or the application code. They can be used to signify some malfunction, but can be properly handled by the application, or not.</p> <p>A <a href="https://metacpan.org/module/Dancer::Error">Dancer::Error</a> can be roughly seen as an object representation of an HTTP error. So it's what you want your application to send to your end users. When a <a href="https://metacpan.org/module/Dancer::Error">Dancer::Error</a> object is generated, Dancer's workflow is almost at its end. It's possible to add hooks to execute some code before or after a <a href="https://metacpan.org/module/Dancer::Error">Dancer::Error</a> generation, but it's not handy for exception handling.</p> <p>You should however note that when a Dancer::Exception is not caught by the application, it'll eventually be caught by Dancer's code internally, and a Dancer::Error will be generated, and sent to the end user.</p> <h1><a name="conclusion"></a>Conclusion</h1> <p>I think that's a good first demonstration of what <a href="https://metacpan.org/module/Dancer::Exception">Dancer::Exception</a> can do for you. As a bonus, here is the list of core exceptions that Dancer's core code uses, along with their message patterns:</p> <pre class="prettyprint">Core 'core - %s' Core::App 'app - %s' Core::Config 'config - %s' Core::Deprecation 'deprecation - %s' Core::Engine 'engine - %s' Core::Factory 'factory - %s' Core::Factory::Hook 'hook - %s' Core::Hook 'hook - %s' Core::Fileutils 'file utils - %s' Core::Handler 'handler - %s' Core::Handler::PSGI 'handler - %s' Core::Plugin 'plugin - %s' Core::Renderer 'renderer - %s' Core::Route 'route - %s' Core::Serializer 'serializer - %s' Core::Template 'template - %s' Core::Session 'session - %s'</pre> <p>So, when a core exception happens in a renderer, you'll see a message like:</p> <pre class="prettyprint">core - renderer - the frobnicator didn't frob properly</pre> <h1><a name="author"></a>AUTHOR</h1> <p>Damien Krotkine, <code>&lt;dams@zarb.org&gt;</code></p> </div> Easy Database Access with Dancer::Plugin::Database http://advent.perldancer.org/2011/5 perl http://advent.perldancer.org/2011/5 Mon, 5 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="easy_database_access_with_dancer__plugin__database"></a>Easy Database Access with Dancer::Plugin::Database</h1> <p>In last year's calendar, I wrote a basic post on <a href="http://advent.perldancer.org/2010/4">Database Connections with Dancer::Plugin::Database</a>.</p> <p>The article covered how to connect to databases using <a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a>, but not how to make use of any of the extra convenience methods (which hadn't been added at that time).</p> <h1><a name="why_would_i_use_dancer__plugin__database"></a>Why would I use Dancer::Plugin::Database</h1> <p>So - why use <a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a> at all? Why not just use DBI directly?</p> <ul> <li><a name="item_It_manages_database_connections_for_you"></a><b>It manages database connections for you</b> <p>When you call the <code>database()</code> keyword, Dancer::Plugin::Database will return a database handle, connecting first if needed, or if an existing connection is available, checking it's still usable then giving you that handle. It takes care to ensure that database handles are not shared between different processes or threads, which would often lead to Bad Things happening.</p> </li> <li><a name="item_It_s_easily_configurable"></a><b>It's easily configurable</b> <p>You can define your database connection details in your application config, where they belong, and simply use the <code>database()</code> keyword where you need a database handle to use. If you need connections to multiple databases, it's easy to declare multiple connections in your configuration, then pass a name to the <code>database</code> keyword when you call it - e.g. <code>database('foo')</code>.</p> </li> <li><a name="item_It_makes_the_common_stuff_very_easy"></a><b>It makes the common stuff very easy</b> <p>In many web apps, you'll find yourself doing certain basic queries very often, and writing the SQL for them each time gets very tedious. What you get when you call <code>database()</code> isn't actually a vanilla <a href="https://metacpan.org/module/DBI">DBI</a> <code>DBI::db</code> database handle - it's actually a <a href="https://metacpan.org/module/Dancer::Plugin::Database::Handle">Dancer::Plugin::Database::Handle</a> object, which subclasses <code>DBI::db</code> and provides additional convenience methods. This means you can use it exactly as you would a normal DBI database handle, but also have extra convenience methods available, letting you do the simple stuff easily without writing SQL:</p> <p><code>quick_select</code> lets you quickly find a record, for example:</p> <pre class="prettyprint"># Fetch the user whose ID is 42 (scalar context means we'll only get one # record). # Roughly equivalent to SELECT * FROM users WHERE id = 42 (but using # placeholders for safety) my $user = database-&gt;quick_select('users', { id =&gt; 42 }); # In list context, get multiple results: my @admins = database-&gt;quick_select('users', { is_admin =&gt; 1 });</pre> <p><code>quick_update</code> lets you quickly update records, for example:</p> <pre class="prettyprint"># Update the email address for the user whose ID is 42: database-&gt;quick_update('users', { id =&gt; 42 }, { email =&gt; 'new@email.com'});</pre> <p><code>quick_lookup</code> lets you quickly get a specific field from a record:</p> <pre class="prettyprint"># Get just the email address of a user: my $email = database-&gt;quick_lookup('users', { id =&gt; 42 }, 'email');</pre> <p>Using the convenience methods mentioned above helps make life easy, and care is taken by <a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a> to always use placeholders (parameters) rather than interpolation, to avoid you falling victim to SQL injection attacks (obligatory <a href="http://bobby-tables.com/">bobby-tables.com</a> link).</p> </li> <li><a name="item_It_doesn_t_get_in_your_way"></a><b>It doesn't get in your way</b> <p>You don't have to use the convenience methods; naturally, there will be many cases where any attempt at SQL abstraction will get in your way, and you just want to write a query yourself. You get a (subclassed) DBI database handle which you can use in whatever way you want.</p> </li> </ul> <p>Of course, there are other options; if you're a <a href="https://metacpan.org/module/DBIx::Class">DBIx::Class</a> fan, look at <a href="https://metacpan.org/module/Dancer::Plugin::DBIC">Dancer::Plugin::DBIC</a> instead.</p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious, <code>&lt;davidp@preshweb.co.uk&gt;</code></p> </div> How to safely store a password http://advent.perldancer.org/2011/4 perl http://advent.perldancer.org/2011/4 Sun, 4 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="how_to_safely_store_a_password"></a>How to safely store a password</h1> <p>Most developers will have to handle authentication at some point, and this usually means storing a password. Everyone knows that storing plain-text passwords is a Bad Idea, but this raises the question; how can I store the password safely?</p> <p>If you store passwords as plain-text, stop it! Right now. There is no good reason to store passwords as plain text, and it should never be done. Database security <i>will</i> be breached, no matter how secure you make your system. When that happens, an attacker has the login details for every user in your system. Knowing that people often use the same passwords for multiple systems, that plain-text password could open up your users to attacks on their social networks, email, or even bank accounts. This will land you as the system administrator in legal trouble, as most countries have very strict laws governing the storage of personal data.</p> <h1><a name="password_storage_basic_principles"></a>Password storage basic principles</h1> <p>The first step to safely storing a password is to not store the password at all. You should be storing a <a href="http://en.wikipedia.org/wiki/Cryptographic_hash_function">cryptographic hash</a> of the password. A cryptographic hash is a one-way function; it is easy to create one for a password, but almost impossible to get the original password out.</p> <p>To authenticate against a stored hash, you take the plain-text password provided by your user, concatenate it with the salt for that user, generate a hash using the same algorithm as your stored hash, and if the newly generated hash matches the stored version, the password is valid. The concept of salt is discussed later in this article.</p> <p>There are password-less authentication schemes like OAuth that don&rsquo;t require you to store or transmit the password or a hash of it. But that is beyond the scope of this article.</p> <h1><a name="features_of_a_safely_stored_password"></a>Features of a safely stored password</h1> <h2><a name="1_password_is_hashed_using_a_secure_one_way_hash"></a>1 Password is hashed using a secure one-way hash</h2> <p>There are many cryptographic hash functions, and the next step is deciding which one to use. Historically MD5 was the algorithm of choice, but some clever maths geezers figured out how to reverse MD5 very quickly and it should not be used now. SHA&ndash;1 is another popular choice, though it too is close to being broken in the same way as MD5.</p> <p>Next we have the SHA2 family of algorithms, SHA&ndash;256, and SHA&ndash;512 being the most popular variants. These are fine choices and are widely supported. They are not close to being broken, and provide an adequate level of security against most categories of attack.</p> <p>Alternatively, the Bcrypt (BlowfishCrypt) algorithm is at least as secure as the SHA2 family, but has one advantage - it is resistant to brute force attacks as it includes an extra &ldquo;cost&rdquo; that determines how computationally expensive it is to calculate the hash. It gets around the brute force problem by being purposefully slow to compute.</p> <p>There are other algorithms, and the SHA3 competition is underway. However these are the most commonly used, and are what this article focuses on.</p> <h2><a name="2_hashing_algorithm_should_be_resistant_to_brute_force_attack"></a>2 Hashing algorithm should be resistant to brute-force attack</h2> <p>All these hash algorithms have one flaw in common. They are designed to be quick, and are thus vulnerable to brute forcing.</p> <p>On standard desktop hardware with off-the-shelf software you can generate 2,300,000,000 SHA&ndash;1 hashes every second. That&rsquo;s not a typo, 2.3 billion hashes a second. Even using pure perl tools and using non-optimized code I can generate 1.3 million hashes a second on my year-old laptop.</p> <p>2.3 billion hashes a second means every single possible combination of alphanumeric passwords less than 8 characters can be brute forced in 23 minutes. If your password is less than 8 characters and is stored as a salted SHA&ndash;1 hash (A common scenario) - it is effectively plain text.</p> <p>Bcrypt can mitigate this class of attack by setting the cost to a high value. A higher cost forces the algorithm to generate hashes at a slower rate, making brute force attacks take an unfeasibly long amount of time again.</p> <h2><a name="3_password_hash_has_a_unique__cryptographically_random_salt"></a>3 Password hash has a unique, cryptographically random salt</h2> <p>In addition to storing the hash of the password rather than the plain-text, you must add a salt to it. The purpose of a salt is to make sure that the same password does not always generate the same hash. A salt is a bunch of random characters that are concatenated with the password before hashing. You must use a different salt for every password hash you generate for it to be effective.</p> <p>There is widespread misunderstanding about what a salt is supposed to do. Some people treat a salt like a secret key, specific to their application and use the same salt with every password - meaning the original point of a salt, to stop the same passwords hashing to the same value - is lost.</p> <p>Salt isn&rsquo;t any more secret than the password hash itself and should be stored along with the password hash. It isn&rsquo;t a secret key, and doesn&rsquo;t help preventing brute force attacks. If someone has access to your database and the password hashes, they have access to your salt too. Don&rsquo;t treat salt like a secret key.</p> <p>An ideal salt should be cryptographically random, so the chance that two hashes having the same salt is minimal.</p> <h1><a name="recommended_best_practice"></a>Recommended Best Practice?</h1> <p>The bcrypt algorithm is recommended for all new development work. Its resistance to brute force attacks is a key factor, and is only going to increase it&rsquo;s appeal as computers get ever faster and start generating trillions of hashes per second.</p> <p>If your legacy code is using SHA&ndash;256 or SHA&ndash;512, AND uses a random salt for every password - you should be fine for the time being. Brute forcing a SHA&ndash;512 hash still takes a length of time that borders of practicality.</p> <p>If you use SHA&ndash;1, MD5, or store passwords as plain-text - you need to change your policy right away. Your passwords are insecure, and at serious risk when your database is breached.</p> <p>If you don&rsquo;t have a random salt for each user, you should start doing so right away. Modules like <a href="https://metacpan.org/module/Data::Entropy">Data::Entropy</a> provide easy ways to get good random-ness.</p> <h1><a name="common_questions"></a>Common Questions</h1> <h2><a name="1_no_one_will_breach_my_security_and_access_my_database"></a>1 No one will breach my security and access my database</h2> <p>That is a bad attitude to have. Recent news shows database compromises on the most secure systems, staffed by experts with lots of money.</p> <ul> <li><a name="item_Sony___a_href__http___blog_us_playstation_com_2011_04_26_update_on_playstation_network_and_qriocity__http___blog_us_playstation_com_2011_04_26_update_on_playstation_network_and_qriocity__a_"></a><b>Sony: <a href="http://blog.us.playstation.com/2011/04/26/update-on-playstation-network-and-qriocity">http://blog.us.playstation.com/2011/04/26/update-on-playstation-network-and-qriocity</a></b> </li> <li><a name="item_Steam___a_href__http___www_valvesoftware_com_news__id_6761__http___www_valvesoftware_com_news__id_6761__a_"></a><b>Steam: <a href="http://www.valvesoftware.com/news/?id=6761">http://www.valvesoftware.com/news/?id=6761</a></b> </li> <li><a name="item_RSA___a_href__http___www_bloomberg_com_news_2011_06_08_emc_s_rsa_security_breach_may_cost_bank_customers_100_million_html__http___www_bloomberg_com_news_2011_06_08_emc_s_rsa_security_breach_may_cost_bank_customers_100_million_html__a_"></a><b>RSA: <a href="http://www.bloomberg.com/news/2011-06-08/emc-s-rsa-security-breach-may-cost-bank-customers-100-million.html">http://www.bloomberg.com/news/2011-06-08/emc-s-rsa-security-breach-may-cost-bank-customers-100-million.html</a></b> </li> <li><a name="item_Citibank___a_href__http___www_ft_com_cms_s_0_eed31c7c_9857_11e0_ae45_00144feab49a_html__http___www_ft_com_cms_s_0_eed31c7c_9857_11e0_ae45_00144feab49a_html__a_"></a><b>Citibank: <a href="http://www.ft.com/cms/s/0/eed31c7c-9857-11e0-ae45-00144feab49a.html">http://www.ft.com/cms/s/0/eed31c7c-9857-11e0-ae45-00144feab49a.html</a></b> </li> <li><a name="item_Epsilon___a_href__http___www_guardian_co_uk_technology_2011_apr_04_epsilon_email_hack__http___www_guardian_co_uk_technology_2011_apr_04_epsilon_email_hack__a_"></a><b>Epsilon: <a href="http://www.guardian.co.uk/technology/2011/apr/04/epsilon-email-hack">http://www.guardian.co.uk/technology/2011/apr/04/epsilon-email-hack</a></b> </li> </ul> <p>Do you really believe that your system is inherently more secure than theirs?</p> <h2><a name="2_why_not_my_own_custom__secret_algorithm"></a>2 Why not my own custom, secret algorithm?</h2> <p>Just because you can&rsquo;t find a shortcut to your algorithm, it doesn&rsquo;t mean that there isn&rsquo;t one.</p> <p>The hashing algorithms above have had some of the greatest mathematical minds of the 20th century working on them for the past 40 years, and they still made mistakes - leaving MD5 and SHA&ndash;1 vulnerable.</p> <p>Hubris is a characteristic of a great programmer, but it is highly unlikely that you are better at crypto-algorithms than the people who created these general purpose hashing algorithms</p> <h2><a name="3_what_modules_should_i_use_to_hash_my_passwords"></a>3 What modules should I use to hash my passwords?</h2> <p>As with everything in perl, There Is More Than One Way To Do It.</p> <p>If you want to do everything manually, you can use the venerable <a href="https://metacpan.org/module/Digest">Digest</a> set of modules, or <a href="https://metacpan.org/module/Crypt::Eksblowfish::Bcrypt">Crypt::Eksblowfish::Bcrypt</a> if you are using bcrypt.</p> <p>If you want a nicer interface that manages the dangerous bits for you, the <a href="https://metacpan.org/module/Authen::Passphrase">Authen::Passphrase</a> set of modules is a good choice.</p> <p>If you are using Dancer, you can use my own <a href="https://metacpan.org/module/Dancer::Plugin::Passphrase">Dancer::Plugin::Passphrase</a> module. It has an interface similar to <a href="https://metacpan.org/module/Authen::Passphrase">Authen::Passphrase</a>, and manages all the common hashing algorithms</p> <h1><a name="dancer__plugin__passphrase"></a>Dancer::Plugin::Passphrase</h1> <p>The plugin exports the passphrase keyword, to which you pass a plaintext password. From this you can generate a hash using whatever algorithm you specify. It defaults to bcrypt with a work factor of 4.</p> <p>You can match a plaintext password to a stored hash by using the matches method.</p> <p>An example Dancer app is below. See the documentation of <a href="https://metacpan.org/module/Dancer::Plugin::Passphrase">Dancer::Plugin::Passphrase</a> for further details</p> <pre class="prettyprint">package MyWebService; use Dancer ':syntax'; use Dancer::Plugin::Passphrase; post '/save_password' sub =&gt; { my $hash = passphrase( param('password') )-&gt;generate_hash; # [...] Store $hash in DB }; get '/check_password' sub =&gt; { # [...] Retrieve $stored_hash from the DB if ( passphrase( param('password') )-&gt;matches( $stored_hash ) ) { # Password matches! } };</pre> <h1><a name="tl_dr"></a>TL;DR?</h1> <p>Use Bcrypt.</p> <h1><a name="references_and_further_reading"></a>References and Further Reading</h1> <ul> <li><a name="item__a_href__http___en_wikipedia_org_wiki_Cryptographic_hash_function__http___en_wikipedia_org_wiki_Cryptographic_hash_function__a_"></a><b><a href="http://en.wikipedia.org/wiki/Cryptographic_hash_function">http://en.wikipedia.org/wiki/Cryptographic_hash_function</a></b> </li> <li><a name="item__a_href__http___www_lockdown_co_uk__pg_combi__http___www_lockdown_co_uk__pg_combi__a_"></a><b><a href="http://www.lockdown.co.uk/?pg=combi">http://www.lockdown.co.uk/?pg=combi</a></b> </li> <li><a name="item__a_href__http___www_golubev_com_hashgpu_htm__http___www_golubev_com_hashgpu_htm__a_"></a><b><a href="http://www.golubev.com/hashgpu.htm">http://www.golubev.com/hashgpu.htm</a></b> </li> <li><a name="item__a_href__http___codahale_com_how_to_safely_store_a_password__http___codahale_com_how_to_safely_store_a_password__a_"></a><b><a href="http://codahale.com/how-to-safely-store-a-password">http://codahale.com/how-to-safely-store-a-password</a></b> </li> </ul> <p><a href="https://metacpan.org/module/Digest">Digest</a> <a href="https://metacpan.org/module/Data::Entropy">Data::Entropy</a> <a href="https://metacpan.org/module/Authen::Passphrase">Authen::Passphrase</a> <a href="https://metacpan.org/module/Crypt::Eksblowfish::Bcrypt">Crypt::Eksblowfish::Bcrypt</a> <a href="https://metacpan.org/module/Dancer::Plugin::Passphrase">Dancer::Plugin::Passphrase</a></p> <h1><a name="author"></a>AUTHOR</h1> <p>This article was written by James Aitken. LoonyPandora on Twitter/GitHub, JAITKEN on CPAN</p> </div> Self-Contained Dancer Application http://advent.perldancer.org/2011/3 perl http://advent.perldancer.org/2011/3 Sat, 3 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="self_contained_dancer_application"></a>Self-Contained Dancer Application</h1> <p>Sometimes you just need a quick-and-dirty way to setup a simple (but powerful, feature-rich, perl-based) web-application, perhaps for personal use, or testing purposes, or any other reason. While creating stub <b>Dancer</b> application is easy enough, <b>Dancer</b> can work its magic even with a single file.</p> <h4><a name="note_about_examples_"></a>Note about examples.</h4> <p>All the examples shown in this page are fully-fledged, self-contained <b>Dancer</b> applications. No external files are needed. To try them out, save the code in a file (e.g. <code>example1.pl</code>), then run:</p> <pre class="prettyprint">$ perl example1.pl &gt;&gt; Dancer 1.3080 server 20729 listening on http://0.0.0.0:3000 == Entering the development dance floor ...</pre> <p>Then visit <a href="http://localhost:3000">http://localhost:3000</a> to see the application in action. For better deployment alternatives, see <a href="https://metacpan.org/module/Deployment">Deployment</a> below.</p> <h2><a name="a_simple_example"></a>A Simple Example</h2> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; get '/' =&gt; sub { return&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;H1&gt;Dance Dance Revolution!&lt;/h1&gt; This is a self-contained Dancer application. &lt;body&gt; &lt;/html&gt; EOF }; dance;</pre> <p>Try it: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/basic.pl">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/basic.pl</a>.</p> <p>Source: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/basic.txt">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/basic.txt</a>.</p> <p>Nothing much to see here. The <b>Dancer</b> keywords (e.g. <code>get</code>, <code>dance</code>) are well documented in <a href="https://metacpan.org/module/Dancer::Introduction">Dancer::Introduction</a> and <a href="https://metacpan.org/module/Dancer::tutorial">Dancer::tutorial</a> pages.</p> <h2><a name="custom_settings"></a>Custom Settings</h2> <p>By default, <b>Dancer</b> uses <code>config.yml</code> for the application's settings. But we can easily change them from our script, and not use <code>config.yml</code> at all:</p> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; set log =&gt; "core"; set logger =&gt; "console"; set warnings =&gt; 1; get '/' =&gt; sub { return&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;H1&gt;Dance Dance Revolution!&lt;/h1&gt; This is a self-contained Dancer application. &lt;body&gt; &lt;/html&gt; EOF }; dance;</pre> <p>The <code>set</code> keyword can be used to set any configuration key, just like the <code>config.yml</code> file. Common configuration keys are detailed in <a href="https://metacpan.org/module/Dancer::Tutorial">Dancer::Tutorial</a>. The above code is equivalent to using the following <code>config.yml</code> values in a normal <b>Dancer</b> application:</p> <pre class="prettyprint">log: "core" logger: "console" warnings: 1</pre> <h2><a name="using_templates"></a>Using Templates</h2> <p><b>Dancer</b>'s template engine can be easily used in self-contained applications:</p> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; set log =&gt; "core"; set logger =&gt; "console"; set warnings =&gt; 1; set template =&gt; "template_toolkit"; my $index_template=&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;h1&gt;Hello From Self-Contained Dancer Application&lt;/h1&gt; The answer to life the universe and everything is &lt;% answer %&gt;. &lt;br/&gt; Our URL is &lt;a href="&lt;% url %&gt;"&gt;&lt;% url %&gt;&lt;/a&gt;. &lt;br/&gt; Thanks for using Dancer! &lt;/body&gt; &lt;/html&gt; EOF get '/' =&gt; sub { my $t = engine 'template'; return $t-&gt;render(\$index_template, { url =&gt; request-&gt;uri_base, answer =&gt; 42 } ); }; dance;</pre> <p>Try it: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/template.pl">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/template.pl</a>.</p> <p>Source: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/template.txt">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/template.txt</a>.</p> <p><b>Notes and Limitations</b></p> <ul> <li> <p>Templates are stored in simple perl variables (we're trying to be self-contained, so no external files). The <code>$index_template</code> variable contains the template code.</p> </li> <li> <p>Using <code>set template =&gt; "template_toolkit"</code>, we're instructing <b>Dancer</b> to use the <a href="https://metacpan.org/module/Template::Toolkit">Template::Toolkit</a> instead of the default <a href="https://metacpan.org/module/Dancer::Template::Simple">Dancer::Template::Simple</a>.</p> </li> <li> <p><b>Dancer</b>'s powerful template features (e.g. <code>before_template</code>, <code>after_template</code>) are not available.</p> </li> <li> <p>We can't use <b>Dancer</b>'s <code>template</code> keyword (as it always expectes template files stored in the <code>/views/</code> folder). Instead, we find the template engine (<code>$t</code> in the above code) and call <code>render</code> directly. (Future versions of Dancer will likely allow scalar references to be passed to the <code>template</code> keyword in order to make this easier.)</p> </li> <li> <p>Normal <b>Dancer</b> applications automatically gain access to some useful variables (e.g. <code>settings</code>, <code>request</code>, <code>params</code>, <code>vars</code>, <code>session</code>) - these <b>are not</b> available here. You must explicitly specify each variable you want to pass to the template engine.</p> </li> </ul> <h2><a name="more_templates__and_forms_"></a>More Templates (and forms)</h2> <p>Here's a slightly more elaborate example of using templates, asking the user for his/her name:</p> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; set log =&gt; "core"; set logger =&gt; "console"; set warnings =&gt; 1; set template =&gt; "template_toolkit"; my $index_template=&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;h1&gt;Hello From Self-Contained Dancer Application&lt;/h1&gt; &lt;% IF missing_name %&gt; &lt;h2&gt;please enter your name!&lt;/h2&gt; &lt;% END %&gt; &lt;form action="&lt;% request.uri_for("/hello") %&gt;" method="post"&gt; What's your name ? &lt;input type="text" name="name" size="40" /&gt; &lt;input type="submit" name="submit" value="That's my name!" /&gt; &lt;/form&gt; &lt;/body&gt; &lt;/html&gt; EOF get '/' =&gt; sub { my $t = engine 'template'; my $r = request ; return $t-&gt;render(\$index_template, { request =&gt; $r } ); }; my $hello_template=&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;h1&gt;Hello &lt;% name %&gt;!&lt;/h1&gt; Thanks for using Dancer! &lt;br/&gt; &lt;br/&gt; If that's not your name, &lt;a href="&lt;% request.uri_base %&gt;"&gt;change it.&lt;/a&gt; &lt;/body&gt; &lt;/html&gt; EOF post '/hello' =&gt; sub { my $t = engine 'template'; my $r = request ; my $name = param 'name'; return $t-&gt;render(\$index_template, { request =&gt; $r, missing_name =&gt; 1} ) unless $name; return $t-&gt;render(\$hello_template, { request =&gt; $r, name =&gt; $name} ); }; dance;</pre> <p>Try it: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/more_templates.pl">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/more_templates.pl</a>.</p> <p>Source: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/more_templates.txt">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/more_templates.txt</a>.</p> <p><b>Notables</b>:</p> <ul> <li> <p>In the template variables (<code>$index_template</code> and <code>$hello_template</code>) we use the <code>request-&gt;uri_for</code> and <code>request-&gt;uri_base</code> methods to construct a valid URL, but we have to pass the <code>request</code> object explicity to the template engine.</p> </li> <li> <p>In the <code>post</code> handler, we can access CGI parameters using <code>param</code>, just like in a normal <b>Dancer</b> application.</p> </li> </ul> <h2><a name="using_plugins"></a>Using Plugins</h2> <p>Using plugins is straight-forward, just like in a normal <b>Dancer</b> application. The following example creates a SQLite database of shapes, and allows the user to modify and examine it:</p> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; use Dancer::Plugin::Database; use Dancer::Plugin::SimpleCRUD; set template =&gt; 'template_toolkit'; set log =&gt; "debug"; set logger =&gt; "console"; set warnings =&gt; 1; set plugins =&gt; { Database =&gt; { driver =&gt; 'SQLite', database =&gt; "foo.sqlite" } } ; my $index_template=&lt;&lt;EOF; &lt;html&gt; &lt;head&gt; &lt;/head&gt; &lt;body&gt; &lt;h1&gt;Hello From Self-Contained Dancer Application&lt;/h1&gt; &lt;h2&gt;(With Database plugin support)&lt;/h2&gt; &lt;h3&gt;Add a new shape to database&lt;/h3&gt; &lt;form action="add" method="post"&gt; Shape: &lt;select name="shape"&gt; &lt;option value="square"&gt;square&lt;/option&gt; &lt;option value="circle"&gt;circle&lt;/option&gt; &lt;option value="triangle"&gt;triangle&lt;/option&gt; &lt;/select&gt; Color: &lt;select name="color"&gt; &lt;option value="red"&gt;red&lt;/option&gt; &lt;option value="green"&gt;green&lt;/option&gt; &lt;option value="blue"&gt;blue&lt;/option&gt; &lt;/select&gt; &lt;input type="submit" name="submit" value="Add Shape" /&gt; &lt;/form&gt; Direct Database Access: &lt;a href="shapes"&gt;click here&lt;/a&gt;&lt;br/&gt; &lt;h3&gt;Current Shapes in database:&lt;/h3&gt; &lt;% IF shapes.size == 0 %&gt; Database is empty. Please add some shapes. &lt;% ELSE %&gt; &lt;% FOREACH s IN shapes %&gt; &lt;% s.count %&gt; &lt;% s.color %&gt; &lt;% s.shape %&gt;&lt;% s.count&gt;1 ? 's' : '' %&gt; &lt;br/&gt; &lt;% END %&gt; &lt;% END %&gt; &lt;/body&gt; &lt;/html&gt; EOF get '/' =&gt; sub { my $t = engine 'template'; my $sql="SELECT shape,color,count(id) AS count FROM shapes GROUP BY shape,color"; my $s = database-&gt;prepare($sql); $s-&gt;execute(); my $shapes = $s-&gt;fetchall_arrayref({}) ; return $t-&gt;render(\$index_template, { shapes =&gt; $shapes } ); }; post '/add' =&gt; sub { my $shape = params-&gt;{shape} or die "missing shape parameter"; my $color = params-&gt;{color} or die "missing color parameter"; $shape =~ s/[^\w]//g; # minimal input sanitization $color =~ s/[^\w]//g; database-&gt;quick_insert( 'shapes', { shape=&gt;$shape, color=&gt;$color } ); ## The shape was added to the DB, send to user back to the main page. redirect '/'; }; simple_crud ( record_title =&gt; 'Shape', prefix =&gt; '/shapes', db_table =&gt; 'shapes', editable =&gt; 1, deletable =&gt; 1, sortable =&gt; 1 ); ## ## On-time application initialization: create the database ## sub init_db { ## Create a SHAPE table if it doesn't exist my $sql=&lt;&lt;EOF; CREATE TABLE IF NOT EXISTS shapes ( id INTEGER PRIMARY KEY AUTOINCREMENT, shape TEXT, color TEXT, time TIMESTAMP default CURRENT_TIMESTAMP ) EOF database-&gt;do($sql); } init_db; dance;</pre> <p>Source: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/plugins.txt">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/plugins.txt</a>.</p> <p><b>Notables</b>:</p> <ul> <li> <p>This example requires the following perl modules: <a href="https://metacpan.org/module/DBD::SQLite">DBD::SQLite</a>, <a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a>, <a href="https://metacpan.org/module/Dancer::Plugin::SimpleCRUD">Dancer::Plugin::SimpleCRUD</a>.</p> </li> <li> <p>The <code>set plugins =&gt; ...</code> statement is equivalent to the following <code>config.yml</code> stanza:</p> <pre class="prettyprint">plugins: Database: driver: 'SQLite' database: 'foo.sqlite'</pre> </li> <li> <p>The <code>get</code> and <code>post</code> handlers use the <code>database</code> keyword just like normal <b>Dancer</b> applications. No special code required.</p> </li> <li> <p><code>init_db</code> creates a new SQLite table, if it doesn't exist. This is not Dancer specific at all, just makes the example completely self-contained.</p> </li> </ul> <h2><a name="embedding_images_and_files"></a>Embedding images and files</h2> <p>You can even embed images and files in a self-contained <b>Dancer</b> application (although, if you've reached the point you do need external files, a self-contained application is probably not what you want. Still - it's quite possible):</p> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; use MIME::Base64; set log =&gt; "core"; set logger =&gt; "console"; set warnings =&gt; 1; set template =&gt; "template_toolkit"; my $index_html=&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;h1&gt;Hello From Self-Contained Dancer&lt;/h1&gt; &lt;h2&gt;With embedded files&lt;/h2&gt; A PNG Star: &lt;img src="&lt;% request.uri_for("/files/star.png") %&gt;"/&gt; &lt;br/&gt; A PDF Star: &lt;a href="&lt;% request.uri_for("/files/red_star.pdf") %&gt;" /&gt;Download me!&lt;/a&gt; &lt;/body&gt; &lt;/html&gt; EOF get '/' =&gt; sub { my $t = engine 'template'; my $r = request ; return $t-&gt;render(\$index_html, { request =&gt; $r } ); }; # The stock-star image was made with OpenClipArt's stock-star png file: # $ base64 &lt; /usr/share/openclipart/png/computer/icons/stock-star.png my $openclipart_stock_star=&lt;&lt;EOF; iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz AAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAVdEVY dFRpdGxlAEV0aXF1ZXR0ZSBJY29uc3n31Q4AAAAVdEVYdEF1dGhvcgBBbmR5IEZpdHpzaW1vbta6 3GQAAASmSURBVEiJvZd/aFVlGMe/z/u859xt587t7rqpMxu6NkW9/ri7czlUEqEQpEKy/IFRUEEF RggOy8SEyMqwkjLIQAqhIOxPUaPSP/zLgoogRebmfk/Nue3u3nPvOefpj52r99p2Ngf6wpdzzvu+ 5/s5z/O873u5JCKYStvbUr4IQHz/BwPfTuV9NSUqAGa1U2ves293OT0w8P63IjOVwnYir15r2vDA wKyxo7x8mrdk6TI3ZPI7DwR84N1I2DR5R3PzGrO5eQ0TeY0H36tYdd/BmunlopAOLV4cQ7Qignm1 tVnT0HvuK/jQ+xU6FNK7lscbNLMHz7ORSDQZSrlPfP5xNHbfwFrTc8xSFYvFIGJDxMasWVWYOXNG xtBq9714UdA+PvxRlIkwmwg1RHiYmffVPVI/b9Xqxwo++Gr7FZw9d9oDZCcRtRLQQYSrL7x67UYg +LMPoyVE2EKEuUSo0cx1INSISCUgTARoZtcKh721a9cZZWVlBSYignPnfnIHbv7rZjJpAxAiAkiR zYp7iNDmee5lInQA+G7zi/2Xbkd85ND0HQR8YpgG1dfXIhy2YFkWwlYYVtiCaZqTSqGIIJ1OYWQk iVQqiXRqBF3dVzE0eBMAviSi15/Z3ucVpPqrw9O3KkXfzK+vVfH4simdSHe37u4O/PXnb55ADmzc 1vd2rv9/NT52pHK9UvTjnDnVOtG4nInG4U/ijO/oaMeli38LCLue2tx3MH9szMV1/GhVs1J0qrIy WpRILNXM937AtbddQVtbqwfCKxs29X599/i4q/r7Y1UxZvq5bFppWUNDzNCaJw1tbW2Vnt4eF5At 6zf2/jDWnMDtdOL4jLms6NfikqJZicRiQ6mJI29va5e+/v4MBE8+/nTP6fHmBTpt3NZ3RSnsyWZt BclAPHtCuW4GmulUEBQA9EQRsMaSsBXyIFkOXk+jg5Zl0vAwNU3kO2HuDK1WlpaGDE9sBCsDTzIo Lmawkhnnz1RXBvlOGLHWWGaVKIiXKegfHk7Bth1EIhaUurPlQiagNQkICQAnpwQ+e7J6HitYRUWA eDYAwM64uH496aTTWSZCamg4qSsiJWZpOAQAIAChIs66jtsYBA5MtWY0sIZnGC6yThr91wa97u5b 4jjOBda0gjXNJsinAwPJbG/fQCaVHoEnNoqLlGkY9Gigd9Aga4obBjmDg2lzaMh1iNCtNd5sWNN1 Im/arj/OP/QFIAdu3bKfDZnkMkMzY0WQd2DEhkYTRMxk0h1mphbFVHcXFACwtLmzbcnKzs1aU5Mn uOC4gGaKXvx9TvU9g4mImGkBgCNnfkkvjK/uOhpf1VVCRBEiqiCiqK8Kv6980YrOfxY2dq6zbdnE GpeVosZx/fNPLiLSAEwAxqIFRsnzW8O1LXtvtmO0JBoA+yJfwOgGFgCuLweAM7/OwGsvTZv+RsuN VgBZABkRcQrANPoTFAJg+GBznHsjT7n14frGWQAZX/n3Bc8iYiP3sogIEXkAcnL9MuQiyEUo/riT VyYvb16+chnw8q7emKn2081+dBqFKdY+LKf8lv/BBSn3I3VExC3gTOZPm1+KsQTcqfFtySRM/wP7 TwAUiu6U1QAAAABJRU5ErkJggg== EOF ## Cache the binary form of the PNG image, no need to re-decode on every HTTP request. my $stock_star_bin = decode_base64($openclipart_stock_star); # I made this red star using InkScape, then used: # $ base64 &lt; red_star.pdf my $red_star_pdf=&lt;&lt;EOF; JVBERi0xLjUKJbXtrvsKMyAwIG9iago8PCAvTGVuZ3RoIDQgMCBSCiAgIC9GaWx0ZXIgL0ZsYXRl RGVjb2RlCj4+CnN0cmVhbQp4nG2OTUoDQAyF93OKdwHTTP4mOYEguGhdSheioIhdlC56fTP7MoSE Ny/fy3VMMLm41e425wqcnnH4YHzfhpDhPhgvXb/j/dwextcwvOKK3uz3tFvapMxaa+LzMtSKqoEW RWqJC6QnV4dWEc/AH2YEMRtMnDS1FeEktgWVRTOylTGdqaEQDUr3bfJFuhxiQVbSijYgVBtopLw9 O37HSiRZbzfILCn6U3lR1c5Xb2QoNISW7rSfB3e/4TiO4x/aODrYCmVuZHN0cmVhbQplbmRvYmoK NCAwIG9iagogICAxOTMKZW5kb2JqCjIgMCBvYmoKPDwKICAgL0V4dEdTdGF0ZSA8PAogICAgICAv YTAgPDwgL0NBIDEgL2NhIDEgPj4KICAgPj4KPj4KZW5kb2JqCjUgMCBvYmoKPDwgL1R5cGUgL1Bh Z2UKICAgL1BhcmVudCAxIDAgUgogICAvTWVkaWFCb3ggWyAwIDAgNTk1LjI3NTU3NCA4NDEuODg5 NzcxIF0KICAgL0NvbnRlbnRzIDMgMCBSCiAgIC9Hcm91cCA8PAogICAgICAvVHlwZSAvR3JvdXAK ICAgICAgL1MgL1RyYW5zcGFyZW5jeQogICAgICAvQ1MgL0RldmljZVJHQgogICA+PgogICAvUmVz b3VyY2VzIDIgMCBSCj4+CmVuZG9iagoxIDAgb2JqCjw8IC9UeXBlIC9QYWdlcwogICAvS2lkcyBb IDUgMCBSIF0KICAgL0NvdW50IDEKPj4KZW5kb2JqCjYgMCBvYmoKPDwgL0NyZWF0b3IgKGNhaXJv IDEuMTAuMiAoaHR0cDovL2NhaXJvZ3JhcGhpY3Mub3JnKSkKICAgL1Byb2R1Y2VyIChjYWlybyAx LjEwLjIgKGh0dHA6Ly9jYWlyb2dyYXBoaWNzLm9yZykpCj4+CmVuZG9iago3IDAgb2JqCjw8IC9U eXBlIC9DYXRhbG9nCiAgIC9QYWdlcyAxIDAgUgo+PgplbmRvYmoKeHJlZgowIDgKMDAwMDAwMDAw MCA2NTUzNSBmIAowMDAwMDAwNTkzIDAwMDAwIG4gCjAwMDAwMDAzMDcgMDAwMDAgbiAKMDAwMDAw MDAxNSAwMDAwMCBuIAowMDAwMDAwMjg1IDAwMDAwIG4gCjAwMDAwMDAzNzkgMDAwMDAgbiAKMDAw MDAwMDY1OCAwMDAwMCBuIAowMDAwMDAwNzg1IDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUgOAog ICAvUm9vdCA3IDAgUgogICAvSW5mbyA2IDAgUgo+PgpzdGFydHhyZWYKODM3CiUlRU9GCg== EOF my $red_star_pdf_bin = decode_base64($red_star_pdf); get '/files/:file' =&gt; sub { my $file = params-&gt;{file}; if ( $file eq "star.png" ) { header('Content-Type' =&gt; 'image/png'); return $stock_star_bin; } if ( $file eq "red_star.pdf" ) { header('Content-Type' =&gt; 'application/pdf'); header('Content-Disposition' =&gt; "attachment; $file" ); return $red_star_pdf_bin; } status 'not_found'; return "File not found"; }; dance;</pre> <p>Try it: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/embed.pl">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/embed.pl</a>.</p> <p>Source: <a href="http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/embed.txt">http://cancan.cshl.edu/labmembers/gordon/dancer_advent_calendar_2011/embed.txt</a>.</p> <h2><a name="deployment_with_plackup_starman__etc_"></a>Deployment with Plackup/Starman, etc.</h2> <p>All the above examples will work as-is with <a href="https://metacpan.org/module/plackup">plackup</a> and <a href="https://metacpan.org/module/Starman">Starman</a>. Just run:</p> <pre class="prettyprint">$ plackup -s Starman example1.pl [19688] core @0.000759&gt; loading Dancer::Handler::PSGI handler in /usr/local/share/perl/5.12.4/Dancer/Handler.pm l. 41 [19688] core @0.004706&gt; loading handler 'Dancer::Handler::PSGI' in /usr/local/share/perl/5.12.4/Dancer.pm l. 436 2011/11/29-16:19:45 Starman::Server (type Net::Server::PreFork) starting! pid(19688) Binding to TCP port 5000 on host * Setting gid to "1000 1000 20 24 25 27 29 33 44 46 110 115 123 124 1000 1001 1002 1008"</pre> <p>Then visit <a href="http://localhost:5000">http://localhost:5000</a> or setup an Apache/nginx/lighttpd proxy to your <b>Dancer</b> daemon. See &lt;Dancer::Deployment&gt; for more details and examples.</p> <h2><a name="deployment_as_cgi_script"></a>Deployment as CGI script</h2> <p>Not very efficient, but easy to deploy. In a self-contained <b>Dancer</b> application, simply change the last <code>dance;</code> statement to the following:</p> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; use Plack::Runner; get '/' =&gt; sub { return&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;H1&gt;Dance Dance Revolution!&lt;/h1&gt; This is a self-contained Dancer application, served as a CGI script. &lt;body&gt; &lt;/html&gt; EOF }; my $app = sub { my $env = shift ; my $request = Dancer::Request-&gt;new ( env =&gt; $env ) ; Dancer-&gt;dance($request); }; Plack::Runner-&gt;run($app);</pre> <p><b>Notables</b>:</p> <ul> <li> <p>This example requires the <a href="https://metacpan.org/module/Plack::Runner">Plack::Runner</a> perl module.</p> </li> <li> <p>The <b>apache</b> configuration to run this CGI script will be something like:</p> <pre class="prettyprint">Alias /selfdance/ "/home/gordon/projects/perl_dancer_test/self_contained/" &lt;Directory "/home/gordon/projects/perl_dancer_test/self_contained/"&gt; AddHandler cgi-script .cgi AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch DirectoryIndex self2.cgi &lt;/Directory&gt; ReWriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^/selfdance/(.*)$ /home/gordon/projects/perl_dancer_test/self_contained/self2.cgi/$1 [QSA,L]</pre> </li> <li> <p>See <a href="https://metacpan.org/module/Dancer::Deployment">Dancer::Deployment</a> for more details.</p> </li> </ul> <h2><a name="deployment_as_fast_cgi_script"></a>Deployment as Fast-CGI script</h2> <pre class="prettyprint">#!/usr/bin/env perl use strict; use warnings; use Dancer; use Plack::Handler::FCGI; get '/' =&gt; sub { return&lt;&lt;EOF; &lt;html&gt; &lt;body&gt; &lt;H1&gt;Dance Dance Revolution!&lt;/h1&gt; This is a self-contained Dancer application, served as a CGI script. &lt;body&gt; &lt;/html&gt; EOF }; my $app = sub { Dancer-&gt;dance($request); }; my $server = Plack::Handler::FCGI-&gt;new(nproc =&gt; 5, detach =&gt; 1); $server-&gt;run($app);</pre> <p><b>Notables</b>:</p> <ul> <li> <p>This example requires the <a href="https://metacpan.org/module/Plack::Handler::FCGI">Plack::Handler::FCGI</a> perl module.</p> </li> <li> <p>The <b>apache</b> configuration to run this CGI script will be something like:</p> <pre class="prettyprint">Alias /selfdancefast/ "/home/gordon/projects/perl_dancer_test/self_contained/" &lt;Directory "/home/gordon/projects/perl_dancer_test/self_contained/"&gt; AddHandler fcgid-script .fcgi AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch DirectoryIndex self3.fcgi &lt;/Directory&gt; ReWriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^/selfdancefast/(.*)$ /home/gordon/projects/perl_dancer_test/self_contained/self3.fcgi/$1 [QSA,L]</pre> </li> <li> <p>See <a href="https://metacpan.org/module/Dancer::Deployment">Dancer::Deployment</a> for more details.</p> </li> </ul> <h1><a name="author"></a>AUTHOR</h1> <p>This article was kindly written by Assaf Gordon - thanks!</p> </div> Simple CRUD with Dancer::Plugin::SimpleCRUD http://advent.perldancer.org/2011/2 perl http://advent.perldancer.org/2011/2 Fri, 2 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="simple_crud_with_dancer__plugin__simplecrud"></a>Simple CRUD with Dancer::Plugin::SimpleCRUD</h1> <p>It's a common requirement to provide CRUD (create, read, update, delete) functionality from within webapps, and this can often lead to repeating tedious code, which is no good.</p> <p><a href="https://metacpan.org/module/Dancer::Plugin::SimpleCRUD">Dancer::Plugin::SimpleCRUD</a> has been designed to let you very easily put up a basic interface to allow data in a database table to be viewed, searched, added, edited and deleted.</p> <p>Once you've loaded the plugin, you can get a basic CRUD interface up and running with code as simple as:</p> <pre class="prettyprint">simple_crud( record_title =&gt; 'Widget', prefix =&gt; '/widgets', db_table =&gt; 'widgets', );</pre> <p>The above example states that we want an interface at &lt;/widgets&gt; to edit stuff in the database table named <code>widgets</code>, and sets the display name of a record in the table to <code>Widget</code> (used for user-facing titles like "Edit Widget", "Delete Widget" etc).</p> <p>For a ready-to-try example, <a href="https://metacpan.org/module/Dancer::Plugin::SimpleCRUD">Dancer::Plugin::SimpleCRUD</a> ships with an <a href="https://github.com/bigpresh/Dancer-Plugin-SimpleCRUD/tree/master/example">example app</a> complete with a ready-to-use SQLite database with some sample records.</p> <p>If you launch the example app and go to e.g. <a href="http://localhost:3000/people">http://localhost:3000/people</a> (tweak URL to suit if it's not on your local machine, or you start it on a different port, etc), you'll see a list of records already present:</p> <img src="/images/2011/simplecrud-people-list.png"> <p>The example app enables pagination, searching and downloading of the results as CSV/TSV/JSON/XML, to illustrate the easy options which are available.</p> <p>From the record listing page, Clicking the edit link to edit one of the records will bring up a form to edit the record:</p> <img src="/images/2011/simplecrud-people-edit.png"> <p>DWIMmery is used to look at the database table definition and work out sensible form control types etc (although of course there are configuration options to allow you to override various parts, control which fields are editable, define validation rules etc). The idea though is that the default settings should be sensible, so you should be able to get something usable up and running with the minimum of fuss.</p> <p>As examples, an <code>ENUM()</code> column will result in radio buttons/a dropdown of the specified choices, a <code>TEXT</code> column will result in a <code>TEXTAREA</code> input, and a column named e.g. <code>password</code> or <code>passwd</code> will result in a <code>PASSWORD</code> text entry field automatically.</p> <p>When adding a new record, of course the form is the same one as the edit form, but not pre-populated with the existing contents of the record being edited.</p> <h1><a name="author"></a>AUTHOR</h1> <p>David Precious <code>&lt;davidp@preshweb.co.uk&gt;</code></p> </div> Looking back on 2011 http://advent.perldancer.org/2011/1 perl http://advent.perldancer.org/2011/1 Thu, 1 Dec 2011 00:00:00 -0000 <div class="pod-document"><h1><a name="looking_back_on_2011"></a>Looking back on 2011</h1> <p>Firstly, a big welcome to the 2011 Dancer advent calendar - last year's advent calendar was successful and well-received, hopefully this year's will be even better. You can look forward to a series of posts on getting the most from Dancer and what's happened in 2011.</p> <p>So, let's start by taking a look back on 2011 and see what's new in the Dancer world.</p> <h2><a name="dancer_workshop_at_lpw2011"></a>Dancer workshop at LPW2011</h2> <p>Andrew Solomon presented a hands-on training session at this year's London Perl Workshop entitled "Web development for beginners with Dancer".</p> <p>The workshop was popular and well received, with 20 registered attendees.</p> <p>A full writeup will follow later in the calendar :)</p> <h2><a name="dancer_ecosystem_better_than_ever"></a>Dancer ecosystem better than ever</h2> <p>Currently, the Dancer repository on GitHub has 378 watchers and has been forked 116 times!</p> <p>The number of individual contributors according to GitHub is 70 - great to see such a vibrant and helpful community springing up around Dancer. Speaking of the community, our <a href="http://www.perldancer.org/irc">IRC channel</a> has 87 people present at the time of writing, with many helpful volunteers providing valuable assistance.</p> <p>More and more Dancer-powered sites are being added to the <a href="http://www.perldancer.org/dancefloor">Dancefloor (Websites using Dancer)</a> page.</p> <h2><a name="many_more_plugins_to_make_life_easy"></a>Many more plugins to make life easy</h2> <p>Many more valuable and useful plugins have been released - a search on MetaCPAN for <a href="https://metacpan.org/search?q=Dancer%3A%3APlugin">Dancer::Plugin::</a> gives 73 results.</p> <p>Later advent calendar posts will showcase some of the useful plugins which can make your life easier :)</p> <h2><a name="better_unicode_support___it_should_just_work"></a>Better Unicode support - it should Just Work</h2> <p>Unicode support has been extended and corrected, with some helpful guidance from Mike Whitaker (Penfold). With <code>charset: UTF-8</code> in your application's config, using Unicode should Just Work. If you're using <a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a>, that setting will also cause UTF-8 support in your database engine to be automatically enabled (for MySQL, Postgres or SQLite), so unicode strings fetched from the database should need no special handling.</p> <h2><a name="support_for_http_patch"></a>Support for HTTP PATCH</h2> <p>The HTTP 'PATCH' verb is defined in <a href="http://tools.ietf.org/html/rfc5789">RFC 5789</a>, allowing clients to perform a partial resource modification, and is slowly being adopted by RESTful APIs etc - GitHub's V3 API being one such example.</p> <p>Dancer now supports PATCH requests.</p> <p>One caveat is that it won't work in standalone mode until <a href="https://metacpan.org/module/HTTP::Server::Simple">HTTP::Server::Simple</a> has been updated to recognise PATCH requests. A pull request addressing this has been submitted, but, at the time of writing, has not been merged:</p> <p><a href="https://github.com/bestpractical/http-server-simple/pull/2">https://github.com/bestpractical/http-server-simple/pull/2</a></p> <h2><a name="get_hooked_"></a>Get hooked!</h2> <p>Support for hooks, both defined by Dancer itself and additional hooks registered by your app or plugins, to make it possible to customise how Dancer behaves easily.</p> <h2><a name="configurable_xml_serialising"></a>Configurable XML serialising</h2> <p>Options can now be passed to control serialisation to XML via <a href="https://metacpan.org/module/XML::Simple">XML::Simple</a>.</p> <h2><a name="send_file_can_send_data_from_a_scalar_and_set_filename"></a>send_file can send data from a scalar and set filename</h2> <p>The <a href="http://p3rl.org/Dancer#send_file">send_file</a> keyword can now be used to send data from a scalar and set the Content-Disposition header to suggest a filename, for example:</p> <pre class="prettyprint">send_file \$img_data, { filename =&gt; 'myimage.png' };</pre> <h2><a name="send_file_supports_streaming"></a>send_file supports streaming</h2> <p>The <a href="http://p3rl.org/Dancer#send_file">send_file</a> keyword now supports PSGI streaming, with callbacks to control what happens.</p> <h2><a name="exceptions"></a>Exceptions</h2> <p>The exceptional Damien Krotkine has added a continuations-style exceptions system to provide much more powerful error handling.</p> <h2><a name="behind_proxy_setting"></a>behind_proxy setting</h2> <p>The behind_proxy setting tells Dancer that it is deployed behind a proxy, causing it to honour the <code>X_FORWARDED_PROTOCOL</code>, <code>X_FORWARDED_HOST</code> etc env vars.</p> <p>And, of course, many more improvements and bug fixes - thanks to the awesome community.</p> </div>