libdancer-perl-1.3120+dfsg.orig/0000755000175000017500000000000012256332256015641 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/LICENSE0000644000175000017500000004354212233013020016632 0ustar gregoagregoaThis software is copyright (c) 2009-2010 by Alexis Sukrieh. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2009-2010 by Alexis Sukrieh. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2009-2010 by Alexis Sukrieh. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End libdancer-perl-1.3120+dfsg.orig/MANIFEST0000644000175000017500000002304412256332256016775 0ustar gregoagregoaAUTHORS CHANGES examples/dancr/dancr.pl examples/dancr/public/css/style.css examples/dancr/schema.sql examples/dancr/views/layouts/main.tt examples/dancr/views/login.tt examples/dancr/views/show_entries.tt lib/Dancer.pm lib/Dancer/App.pm lib/Dancer/Config.pm lib/Dancer/Config/Object.pm lib/Dancer/Continuation.pm lib/Dancer/Continuation/Halted.pm lib/Dancer/Continuation/Route.pm lib/Dancer/Continuation/Route/ErrorSent.pm lib/Dancer/Continuation/Route/FileSent.pm lib/Dancer/Continuation/Route/Forwarded.pm lib/Dancer/Continuation/Route/Passed.pm lib/Dancer/Continuation/Route/Templated.pm lib/Dancer/Cookbook.pod lib/Dancer/Cookie.pm lib/Dancer/Cookies.pm lib/Dancer/Deployment.pod lib/Dancer/Deprecation.pm lib/Dancer/Development.pod lib/Dancer/Development/Integration.pod lib/Dancer/Engine.pm lib/Dancer/Error.pm lib/Dancer/Exception.pm lib/Dancer/Exception/Base.pm lib/Dancer/Factory/Hook.pm lib/Dancer/FileUtils.pm lib/Dancer/GetOpt.pm lib/Dancer/Handler.pm lib/Dancer/Handler/Debug.pm lib/Dancer/Handler/PSGI.pm lib/Dancer/Handler/Standalone.pm lib/Dancer/Hook.pm lib/Dancer/Hook/Properties.pm lib/Dancer/HTTP.pm lib/Dancer/Introduction.pod lib/Dancer/Logger.pm lib/Dancer/Logger/Abstract.pm lib/Dancer/Logger/Capture.pm lib/Dancer/Logger/Capture/Trap.pm lib/Dancer/Logger/Console.pm lib/Dancer/Logger/Diag.pm lib/Dancer/Logger/File.pm lib/Dancer/Logger/Note.pm lib/Dancer/Logger/Null.pm lib/Dancer/MIME.pm lib/Dancer/ModuleLoader.pm lib/Dancer/Object.pm lib/Dancer/Object/Singleton.pm lib/Dancer/Plugin.pm lib/Dancer/Plugin/Ajax.pm lib/Dancer/Plugins.pod lib/Dancer/Renderer.pm lib/Dancer/Request.pm lib/Dancer/Request/Upload.pm lib/Dancer/Response.pm lib/Dancer/Route.pm lib/Dancer/Route/Cache.pm lib/Dancer/Route/Registry.pm lib/Dancer/Serializer.pm lib/Dancer/Serializer/Abstract.pm lib/Dancer/Serializer/Dumper.pm lib/Dancer/Serializer/JSON.pm lib/Dancer/Serializer/Mutable.pm lib/Dancer/Serializer/XML.pm lib/Dancer/Serializer/YAML.pm lib/Dancer/Session.pm lib/Dancer/Session/Abstract.pm lib/Dancer/Session/Simple.pm lib/Dancer/Session/YAML.pm lib/Dancer/SharedData.pm lib/Dancer/Template.pm lib/Dancer/Template/Abstract.pm lib/Dancer/Template/Simple.pm lib/Dancer/Template/TemplateToolkit.pm lib/Dancer/Test.pm lib/Dancer/Timer.pm lib/Dancer/Tutorial.pod LICENSE Makefile.PL MANIFEST This list of files README script/dancer t/00_base/000_create_fake_env.t t/00_base/001_load.t t/00_base/002_strict_and_warnings.t t/00_base/003_syntax.t t/00_base/004_args.t t/00_base/005_module_loader.t t/00_base/007_load_syntax.t t/00_base/008_export.t t/00_base/009_syntax_export.t t/00_base/010_export_script.t t/00_base/06_dancer_object.t t/00_base/08_pod_coverage_dancer.t t/00_base/09_load_app.t t/00_base/11_file_utils.t t/00_base/12_utf8_charset.t t/00_base/13_dancer_singleton.t t/00_base/14_changelog.t t/00_base/15_dependent_modules.t t/00_base/16_version.t t/00_base/17_globalwarnings_config_on.t t/00_base/config.t t/00_base/lib/AppWithError.pm t/00_base/lib/WorkingApp.pm t/00_base/normalize_path.t t/00_base/optional-module-versions.t t/00_base/uri_for.t t/00_base/utf8.tt t/00_base/views/unicode.tt t/01_config/01_settings.t t/01_config/02_mime_type.t t/01_config/03_logger.t t/01_config/04_config_file.t t/01_config/05_serializers.t t/01_config/06_config_api.t t/01_config/06_stack_trace.t t/01_config/07_strict_config.t t/01_config/08_environments.t t/01_config/environments/development.pl t/01_config/yaml_dependency.t t/02_request/000_create_fake_env.t t/02_request/01_load.t t/02_request/04_custom.t t/02_request/04_forward.t t/02_request/05_cgi_pm_compat.t t/02_request/06_init_env.t t/02_request/07_raw_data.t t/02_request/08_params.t t/02_request/10_mixed_params.t t/02_request/11_accessors.t t/02_request/12_base.t t/02_request/13_ajax.t t/02_request/14_uploads.t t/02_request/15_headers.t t/02_request/16_delete.t t/02_request/17_uri_base.t t/02_request/18_param_accessor.t t/03_route_handler/01_http_methods.t t/03_route_handler/02_params.t t/03_route_handler/03_routes_api.t t/03_route_handler/04_routes_matching.t t/03_route_handler/04_wildcards_megasplat.t t/03_route_handler/05_filter.t t/03_route_handler/05_unicode.t t/03_route_handler/06_redirect.t t/03_route_handler/07_compilation_warning.t t/03_route_handler/08_errors.t t/03_route_handler/12_response.t t/03_route_handler/14_options.t t/03_route_handler/15_prefix.t t/03_route_handler/16_caching.t t/03_route_handler/18_auto_page.t t/03_route_handler/21_ajax.t t/03_route_handler/23_filter_error_catching.t t/03_route_handler/24_multiple_params.t t/03_route_handler/24_named_captures.t t/03_route_handler/28_plack_mount.t t/03_route_handler/29_forward.t t/03_route_handler/29_redirect_immediately.t t/03_route_handler/31_infinite_loop.t t/03_route_handler/33_vars.t t/03_route_handler/34_forward_body_post.t t/03_route_handler/35_no_further_routes.t t/03_route_handler/99_bugs.t t/03_route_handler/public/404.html t/03_route_handler/public/utf8file.txt t/03_route_handler/views/error.tt t/03_route_handler/views/foo/bar.tt t/03_route_handler/views/foo/index.tt t/03_route_handler/views/hello.tt t/04_static_file/001_base.t t/04_static_file/003_mime_types_reinit.t t/04_static_file/01_mime_types.t t/04_static_file/02_dir_traversal.t t/04_static_file/secretfile t/04_static_file/static/hello.foo t/04_static_file/static/hello.txt t/05_views/002_view_rendering.t t/05_views/03_layout.t t/05_views/views/clock.tt t/05_views/views/index.tt t/05_views/views/layouts/custom.tt t/05_views/views/layouts/main.tt t/05_views/views/request.tt t/05_views/views/t03.tt t/05_views/views/vars.tt t/06_helpers/000_create_fake_env.t t/06_helpers/01_send_file.t t/06_helpers/02_http_status.t t/06_helpers/03_content_type.t t/06_helpers/04_status.t t/06_helpers/05_send_error.t t/06_helpers/06_load.t t/06_helpers/public/file.txt t/06_helpers/routes.pl t/07_apphandlers/000_create_fake_env.t t/07_apphandlers/01_base.t t/07_apphandlers/02_apache2_plack.t t/07_apphandlers/03_psgi_app.t t/07_apphandlers/04_standalone_app.t t/07_apphandlers/05_middlewares.t t/07_apphandlers/05_psgi_api.t t/07_apphandlers/06_debug.t t/07_apphandlers/07_middleware_map.t t/08_session/000_create_fake_env.t t/08_session/01_load.t t/08_session/02_dependency_check.t t/08_session/03_http_requests.t t/08_session/04_api.t t/08_session/05_yaml.t t/08_session/06_abstract.t t/08_session/07_session_expires.t t/08_session/08_simple.t t/08_session/09_session.t t/08_session/10_filter.t t/08_session/11_session_secure.t t/08_session/12_session_name.t t/08_session/13_session_httponly.t t/08_session/14_session_domain.t t/09_cookies/000_create_fake_env.t t/09_cookies/01_use.t t/09_cookies/02_cookie_object.t t/09_cookies/03_persistence.t t/09_cookies/04_secure.t t/09_cookies/05_api.t t/09_cookies/06_expires.t t/10_template/000_create_fake_env.t t/10_template/01_factory.t t/10_template/02_abstract_class.t t/10_template/03_simple.t t/10_template/05_template_toolkit.t t/10_template/extension.t t/10_template/index.txt t/10_template/template.t t/10_template/views/index.ts t/10_template/views/index.tt t/10_template/views/layouts/main.ts t/10_template/views/layouts/main.tt t/11_logger/000_create_fake_env.t t/11_logger/01_abstract.t t/11_logger/02_factory.t t/11_logger/03_file.t t/11_logger/04_console.t t/11_logger/05_format.t t/11_logger/06_null.t t/11_logger/07_diag.t t/11_logger/08_serialize.t t/11_logger/09_capture.t t/11_logger/10_note.t t/11_logger/11_runtime_file.t t/12_response/000_create_fake_env.t t/12_response/01_CRLF_injection.t t/12_response/02_headers.t t/12_response/03_charset.t t/12_response/04_charset_server.t t/12_response/05_api.t t/12_response/06_filter_halt_status.t t/12_response/07_cookies.t t/12_response/08_drop_content.t t/12_response/09_headers_to_array.t t/12_response/10_error_dumper.t t/12_response/11_CVE-2012-5572.t t/13_engines/00_load.t t/13_engines/02_template_init.t t/14_serializer/01_helpers.t t/14_serializer/02_request_json.t t/14_serializer/03_request_yaml.t t/14_serializer/04_request_xml.t t/14_serializer/05_request_mutable.t t/14_serializer/06_api.t t/14_serializer/17_clear_serializer.t t/14_serializer/99_bugs.t t/15_plugins/000_create_fake_env.t t/15_plugins/01_register.t t/15_plugins/02_config.t t/15_plugins/03_namespace.t t/15_plugins/04_apps_and_plugins.t t/15_plugins/05_keywords.t t/15_plugins/05_plugins_and_OO.t t/15_plugins/06_hook.t t/15_plugins/07_ajax_plack_builder.t t/16_timer/00_base.t t/17_apps/000_create_fake_env.t t/17_apps/00_base.t t/17_apps/01_settings.t t/17_apps/02_load_app.t t/17_apps/03_prefix.t t/17_apps/05_api.t t/19_dancer/01_script.t t/19_dancer/02_script_version_from.t t/20_deprecation/01_api.t t/21_dependents/Dancer-Session-Cookie.t t/22_hooks/00_syntax.t t/22_hooks/01_api.t t/22_hooks/02_before.t t/22_hooks/03_after.t t/22_hooks/04_template.t t/22_hooks/05_layout.t t/22_hooks/06_serializer.t t/22_hooks/07_file.t t/22_hooks/08_error.t t/22_hooks/09_before_error_init.t t/22_hooks/10_error_in_hook.t t/22_hooks/11_error_in_hook.t t/22_hooks/views/index.tt t/22_hooks/views/layouts/main.tt t/23_dancer_tests/01_basic.t t/23_dancer_tests/02_tests_functions.t t/24_deployment/01_multi_webapp.t t/25_exceptions/01_exceptions.t t/25_exceptions/02_exceptions.t t/25_exceptions/03_exceptions.t t/25_exceptions/04_exceptions_warn.t t/25_exceptions/views/error.tt t/25_exceptions/views/index.tt t/25_exceptions/views/layouts/main.tt t/lib/EasyMocker.pm t/lib/Forum.pm t/lib/Hookee.pm t/lib/LinkBlocker.pm t/lib/TestApp.pm t/lib/TestAppUnicode.pm t/lib/TestPlugin.pm t/lib/TestPlugin2.pm t/lib/TestUtils.pm t/manifest.t t/pod.t t/TestAppExt.pm t/TestPlugin.pm TODO META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) libdancer-perl-1.3120+dfsg.orig/AUTHORS0000644000175000017500000001115212256332107016704 0ustar gregoagregoa*** Meet the Dancer Crew *** The first version of Dancer was written by Alexis Sukrieh in summer 2009. The project has evolved a lot since that time, and a huge and very active community emerged to extend and improve Dancer.. The Project is now handled by an organised team of core developers, and many valued contributions are sent by motivated developers around the globe. This is what makes Dancer such a fun project to use - it's a living community of motivated people. A huge thank you to all of them! [ CORE TEAM ] Alberto Simões Alexis Sukrieh Damien Krotkine David Golden David Precious Franck Cuny Sawyer X Yanick Champoux [ CONTRIBUTORS ] Achim Adam Adam J. Foxson Al Newkirk Alan Haggai Alavi Alex Kalderimis Alex Kapranoff Andrei Anirvan Chatterjee Anton Gerasimov Ask Bjørn Hansen boris shomodjvarac Brian E. Lozier Brian Phillips burnersk Chris Andrews chromatic Colin Keith Craig Craig Treptow Daniel Perett Danijel Tasov Dave Doyle David Moreno David Steinbrunner Fabrice Gabolde Flavio Poletti Florian Larysch François Charlier Gabor Szabo geistteufel Grzegorz Rożniecki Hagen Fuchs Hans Dieter Pearcey Ilya Chesnokov ironcamel isync Ivan Bessarabov Jakob Voss James Aitken Jesse van Herk Joel Roth John Wittkoski Jonathan "Duke" Leto Jonathan Otsuka Jonathan Schatz Joshua Barratt Juan J. Martínez Jury Gorky Kaitlyn Parkhurst Kent Fredric Lee Carmichael Marc Chantreux Mark Allen Mark Stosberg Matthew Horsfall (alh) Maurice Max Maischein Michael G. Schwern Mikolaj Kucharski mlbarrow mokko Murray Natal Ngétal Nate Jones Naveed Naveed Massjouni Naveen Nicolas Franck Nicolas Oudard Niko Olivier Mengué Olof Johansson Ovid Paul Driver Paul Fenwick Paul Tomlin Perlover Philippe Bruhat (BooK) ppisar Rick Myers Rik Brown Roman Galeev Rowan Thorpe Sapphire Paw Scott Penrose sdeseille Sebastian de Castelberg Stefan Hornburg (Racke) Tatsuhiko Miyagawa tednolan Tom Heady Tom Hukins Tom Wyant Vyacheslav Matyukhin Xaerxess Zefram libdancer-perl-1.3120+dfsg.orig/README0000644000175000017500000000723612233013707016521 0ustar gregoagregoa Dancer The easiest way to write a webapp with Perl === ABOUT === This project is inspired by Ruby's Sinatra framework: a framework for building web applications with minimal effort, allowing a simple webapp to be created with very few lines of code, but allowing the flexibility to scale to much more complex applications. Dancer supports plugins to add various extra functionality you may want, whilst keeping the core streamlined. === NEWS === Dancer's development moves very quickly, to stay tuned follow PerlDancer on Twitter: http://twitter.com/PerlDancer See also Sukria's blog: http://www.sukria.net/fr/archives/tag/dancer/ See also the project on Github for the latest changes: http://github.com/PerlDancer/Dancer To keep even more up to date and talk to the developers, join us in #dancer on irc.perl.org (if you don't have an IRC client, use http://www.perldancer.org/irc for easy access). === EXAMPLE === To create a new Dancer application, use the helper script "dancer" provided with this distribution: $ dancer -a MyWeb::App + MyWeb-App/bin + MyWeb-App/bin/app.pl + MyWeb-App/config.yml + MyWeb-App/environments [..] You then have a new Dancer application in 'MyWeb::App', which is already a functioning "Hello World" application, ready for you to work upon. Here is an example of a webapp built with Dancer: # MyWeb-App/bin/app.pl #!/usr/bin/perl use Dancer; get '/' => sub { "Hello There!" }; get '/hello/:name' => sub { "Hey ".params->{name}.", how are you?"; }; post '/new' => sub { "creating new entry: ".params->{name}; }; Dancer->dance; When running this script, a webserver is running and ready to serve: $ perl ./bin/app.pl >> Listening on 0.0.0.0:3000 == Entering the development dance floor ... Then it's possible to access any route defined in the script: $ curl http://localhost:3000/ Hello There! For a more in-depth example, see examples/dancr === DEPENDENCIES === Dancer depends on the following modules - HTTP::Server::Simple::PSGI - HTTP::Body - Exception::Class - MIME::Types - URI Optional modules may be needed if you want to use some features (but are not required for a basic usage). Dependency-checks for additional features are performed at runtime. Most common modules you may want are: - Template (for Template::Toolkit support) - YAML (for configuration files) - Plack (if you want to deploy your application with PSGI) === PRODUCTION MATTERS === This is a work in progress. Dancer supports PSGI/Plack, to run a Dancer app with PSGI/Plack just bootstrap your application with the helper script `dancer' like the following: $ dancer -a MyWeb::App You'll find a file in there called `app.psgi', use this file to configure your PSGI environment, as explained in the revelant documentation of your PSGI server. For instance, with plackup, just do the following: $ plackup -a app.psgi === WEBSITE === For more details about the project, checkout the official website: http://perldancer.org/ or checkout the documentation at http://search.cpan.org/dist/Dancer/ See also the Github project page: http://github.com/PerlDancer/Dancer for the latest changes. === REPORTING BUGS === Bug reports are appreciated and will receive prompt attention - the preferred method is to raise them using Github's basic issue tracking system: http://github.com/PerlDancer/Dancer/issues === CONTACT === You can reach the development team on IRC: irc://irc.perl.org/#dancer or http://www.perldancer.org/irc for a web-based IRC client. libdancer-perl-1.3120+dfsg.orig/TODO0000644000175000017500000000264112233013707016324 0ustar gregoagregoa TODO This is the roadmap of upcoming developments * see http://github.com/sukria/dancer/issues#issue/125 * headers (a sane Dancer::Header class for all headers, for D::H::PSGI, * D::H::Standalone, D::Request, D::Response); * rework the concept of D::Engines so we can have multiple D::Serializers loaded at once * possibility to define a serializer for a route, a list of routes, in a route (locally), ... * : nothing should be more global than to a Dancer app. Dancer should not become a bloated MVC, but to be pragmmatic : * a Dancer app should have at most only one template engine attached to it * a Dancer app should have at most only one session engine attached to it * a Dancer app should be able to have multiple serializer attached to it * : config should be changed so that * template, session, serializer defined would be by default global. * if specified in the config, templates and sessions could be set per app * if specified in the config, serializers could be set per app and routes. * : the serializer keyword should limit the serializer scope the route (if used inside a route definition) or to the app (if used outside of a route definition) * : Change Dancer::Plugin API : Dancer::Plugin::Foo should inherit from Dancer::Plugin themselves. * : Dancer::Error could be rewritten to use dancer::object attributes. [ Tests ] libdancer-perl-1.3120+dfsg.orig/CHANGES0000644000175000017500000022522612256331722016642 0ustar gregoagregoaRevision history for Dancer 1.3120 24.12.2013 [ ENHANCEMENTS ] * GH #974: Make plugins play nicely with mro 'c3'. (Fabrice Gabolde) [ DOCUMENTATION ] * GH #972: Correction of a truckload of typos. (David Steinbrunner) * GH #971: Stress that the request's 'env()' method is prefered over accessing '%ENV' directly. (isync) * GH #968: Fix 'ScriptAlias' example in Deployment docs. (reported by tednolan) * GH #976: Document and trap limitation in Dancer::Test. (Tom Hukins) * GH #976: Improve references to related modules. (Tom Hukins) 1.3119 26.10.2013 [ ENHANCEMENTS ] * GH #965: Serializer also serialize content for DELETE. (reported by Achim Adam) [ BUG FIXES ] * GH #959: hash randomization could cause .pl MIME to vary and test to fail. (Olof Johansson) * GH #961: fix bug in require_environment's logic. (reported by sapphirecat) [ DOCUMENTATION ] * GH #962: Improvements of the Dancer::Test docs. (Tom Hukins) * GH #970: Small documentation edit. (Matthew Horsfall) 1.3118 01.09.2013 [ ENHANCEMENTS ] * GH #946: new 'require_environment' setting. (Jesse van Herk) * GH #952: don't set defaults for Template subclasses for Dancer::Template::TemplateToolkit. (Rick Myers) * GH #945: add function 'template_or_serialize' to Dancer::Serializer::Mutable. (Yanick Champoux) [ BUG FIXES ] * GH #655: clarify logger error message. (Yanick Champoux, reported by Gabor Szabo) * GH #951: fix quoting of TemplateToolkit start_tag/stop_tag. (Rick Myers) * GH #940: carry over the session when we forward(). (Yanick Champoux, reported by sciurius) * GH #954: don't die on autoflush for older perls. (Yanick Champoux, reported by metateck and David Golden) * GH #950: Dancer::Test functions now populate REQUEST_URI. (Yanick Champoux, reported by Sören Kornetzki) [ DOCUMENTATION ] * GH #942: simpilify the Apache deployment docs for cgi/fcgi. (bug report by Scott Penrose) [ MISC ] * GH #949: fixes a few errors in the serializer testsuite. (Franck Cuny) 1.3117 31.07.2013 [ ENHANCEMENTS ] * GH #836: Provide more information when an engine fails to load. (Yanick Champoux, reported by Daniel Perrett) [ BUG FIXES ] * GH #794: Upload data was not kept for forwarded requests. (reported by William Wolf) * GH #898: calling halt() doesn't discard set headers anymore. (Yanick Champoux, reported by Nicolas Franck) * GH #842: embedded 'prefix' now properly localized. (Yanick Champoux, reported by Jashank Jeremy) [ DOCUMENTATION ] * GH #938: fix doc typos in Dancer::Serializer. (Fabrice Gabolde) * GH #712: add all status codes known to Dancer to Dancer::HTTP. (Yanick Champoux, reported by Brian J Miller) * Add warning that 'forward' doesn't preserver the session. (Alberto Simões) * GH #941: minor correction to code snippets in documentation. (Grzegorz Rożniecki) * GH #929: add warning on the use of Corona as underlying web server. (issue reported by berekuk) * GH #943: remove mention to 'Dancer::Plugin::Validation', clean 'dancer -a' sample output. (Grzegorz Rożniecki) 1.3116 03.07.2013 [ ENHANCEMENTS ] * GH #767: forwarded_for_address() now looks for HTTP_X_FORWARDED_FOR if X_FORWARDED_FOR is not there. (Jakob Voss) * GH #936: Add file locking to file logger. (David Golden) * GH #937: Add details to tutorial. (Craig Treptow) 1.3115 09.06.2013 [ BUG FIXES ] * GH #605: pass'ed megasplat with no further routes cause 404, not 500. (vlyon) [ DOCUMENTATION ] * GH #934: Added example of HAProxy deployment. (Anton Gerasimov) [ MISC ] * Tests now require Test::TCP v1.30+ (previous version had too short a timeout and tests were failing). (Yanick Champoux) 1.3114 02.06.2013 [ ENHANCEMENTS ] * GH #919: 'dancer' script exits with code 255 if application name is invalid. (ppisar) * GH #871: now recognize HTTP_X_FORWARDED_PROTO. (mlbarrow) * GH #926: make messages from fatal warnings show up in the logs. (Max Maischein) * GH #930: speed improvement. (ichesnokov) * GH #859: strip illegal characters from cookie name. (Colin Keith) * GH #924: non-'/' apps behind proxies now possible using 'request-base' header. (Mikolaj Kucharski) [ BUG FIXES ] * GH #724: app.pl obeys --confdir. (Yanick Champoux) * GH #927: logging format using 'h' now play nicely if no header present. (ironcamel) [ DOCUMENTATION ] * GH #922: Add example of request parameters. (Gabor Szabo) * Add scheme line for ngnix config in D::Deployment. 1.3113 08.05.2013 [ ENHANCEMENTS ] * GH #869: leave body parameters alone if deserialization failed (brianphillips). * GH #912: send_file was returning 500 instead of 404 for non-existent files. (Fabrice Gabolde) * GH #914: add link to melezhik's psgi chef cookbook. * GH #923: implement lazy session flushing. (David Golden) [ BUG FIXES ] * GH #920: fix pod for Dancer::Development. (ppisar) [ DOCUMENTATION ] * GH #915: add warning about behaviour of hooks with multiple packages loaded by load_app (racke). * GH #918: Fix headers syntax in Dancer::Response perldoc (Vyacheslav Matyukhin). 1.3112 10.04.2013 [ ENHANCEMENTS ] * GH #897 dancer script diagnostic more explicit if target directory does not exist or is not writable (reported by Andrew Grangaard). * GH #907: skip tests of deprecated features (mokko). [ BUG FIXES ] * GH #900: backport the security patch for Dancer::ModuleLoader from Dancer2 (mokko). 1.3111_02 01.04.2013 [ BUG FIXES ] * RT #84198: silencing wide-character in-memory file handle error (Tom Wyant). * wrong number of tests to skip in t/14_serializer/01_helpers.t. 1.3111_01 30.03.2013 [ ENHANCEMENTS ] * GH #895: JSON serializer now uses JSON's "-support_by_pp" (Jonathan Schatz). [ BUG FIXES ] * GH #891: silenced warnings from non-numeric versions in Makefile.PL (Olof Johansson). * GH #702: fix request->header call throwing exceptions inside routes of Dancer->dance($request) (Perlover). * GH #893, GH #636: handle binary files for uploads in Dancer::Test (Andrei). * GH #903: add plan for subtest (bug report by wfaulk). [ DOCUMENTATION ] * GH #899: mention that response_exist and response_doesnt_exist are deprecated (Fabrice Gabolde). * GH #902, #903: change example to use path_info() instead of path() (Anton Ukolov, Lee Carmichael). 1.3111 24.02.2013 [ BUG FIXES ] * GH #877: fix Dancer Error when so that 'exception' object is not passed to serializers, because XML/JSON serializers don't understand objects (rikbrown). * GH #858: Check for definedness, not truth, when testing if we read into the buffer when parsing a request body (florolf). * GH #845: Fix uninitialized warning when loading modules (Fabrice Gabolde). * GH #851, GH #853: Atomic YAML session writing (Roman Galeev). * GH #852: Saner UTF logging (Roman Galeev). * GH #849, GH #850: Serve autopages with text/html content type. (Philippe Bruhat - BooK) * GH #848: Handle If-Modified-Since header in the request for static files. (Philippe Bruhat - BooK) * GH #848: Send a Last-Modified header for static files. (Philippe Bruhat - BooK) * GH #856: Don't export non-existing subroutine (mokko). * GH #874: Reduce dependence on %ENV for internal code (Kent Fredric). * GH #875: Don't expect specific order in cookies (Yanick Champoux). * Remove 'exception' object from message being passed to serializers. (Rik Brown) * Added .travis.yml to MANIFEST.SKIP so t/manifest.t passes (Kaitlyn Parkhurst). * GH #887, GH #890: keyword 'global_warnings' added to replace 'import_warnings' (Kaitlyn Parkhurst). * GH #892: add 'private_key' to the list of potentially sensitive keys (Tom Heady). [ DOCUMENTATION ] * GH #847: Fix typo (John Wittkoski). * GH #865: Correct 'before' hook documentation (David Precious, Maurice). * GH #860, GH #844, GH #760: Misleading plack middleware documentation. (Paul Fenwick) * GH #862: Fix heading level for strict_config entry in Dancer::Config. (Stefan Hornburg - Racke) * GH #863: Correct example apache config (John Wittkoski). * GH #867: correct doc for ModuleLoader::load_with_params (mokko). * Document route_cache option (David Precious). * Docs for route_cache_size_limit & route_cache_path_limit (David Precious). * Remove meaningless 'encoding' to TT config (David Precious). * Remove docs for mounting multiple apps (Naveed Massjouni). * Update doc URLs (David Precious). * Fix inconsistency in Perlbal deployment example (Slaven Rezić, Racke). * GH #894: Replace spurious character in Dancer::Session's POD (Racke). * GH #880: Add deprecation mention for 'after' (pdl and Yanick Champoux). 1.3110 06.10.2012 [ BUG FIXES ] * GH #817, #823, #825: Removing Clone from core. Pure-perl environments supported again (Sawyer X). * GH #755, #819, #827, #828: HTTP::Headers accepted by dancer_response (Roberto Patriarca, Dagfinn Ilmari Mannsåker, draxil, perlpong). [ ENHANCEMENTS ] * GH #826: The version of wallflower shipped with Dancer has been removed. It was well out of date. BooK is now maintaining it as a more general solution under the name App::Wallflower. (BooK) * GH #834: Provide empty Headers object if not defined (Yanick Champoux). * GH #840, #841: Dancer::Plugin::Ajax now has content_type (Lee Carmichael). [ DOCUMENTATION ] * GH #821: Pointing to new homepage (alfie). * GH #822: Typos in documentation (Stefan Hornburg - racke). * GH #824: Fix in Dancer/Session.pm (pdl). * GH #830: Fix Github links to https:// (Olivier Mengué). * GH #838: Error in Dancer::Plugin::Ajax Documentation (Lee Carmichael). * GH #839: Typo (goblin). 1.3100 25.08.2012 [ BUG FIXES ] * GH #816: Improve wording when failed to load engine. (Sawyer X) * GH #817: Fix CODE reference uncloned using Clone::clone. (David Previous, Sawyer X) [ ENHANCEMENTS ] * GH #755: HTTP::Headers accepted by dancer_response. (Roberto Patriarca) [ DOCUMENTATION ] * GH #818: Use "MyWeb::App" instead of "mywebapp" in examples. (pdl) 1.3099 11.08.2012 [ BUG FIXES ] * GH #683: Fix uninitialized warnings. (Sawyer X) * GH #700: Take into account the app name in route caching. (Perlover) * GH #775: Clone variables for templates. (Reported by Wanradt Koell, fixed by David Precious, Sawyer X) * GH #776: get should be default to get/head even it's inside any. (Fayland Lam) * GH #788: Make sure ID key in sessions are clobbered. (kocoureasy) * Fix uninitialized variables in config file path. (Sawyer X) * GH #809: Require all necessarily modules in Dancer::Config. (John Wittkoski) [ ENHANCEMENTS ] * GH #799: New test function: response_redirect_location_is. (Martin Schut) * send_file now accepts an IO::Scalar. (David Precious) * Clean up $VERSION. (Damien Krotkine) [ DOCUMENTATION ] * GH #784: Synopsis fix in Dancer::Error. (Alex C) * Document session_domain in Dancer::Config. (David Precious) * Pod fixes in abstract session. (David Precious) * Synopsis fix in Dancer::Test. (Stefan Hornburg ) 1.3098 28.07.2012 [ ENHANCEMENTS ] * New keyword 'plugin_args' exported by Dancer::Plugin to provide a consistent way with Dancer 2 to obtain arguments from a plugin keyword. (Alberto Simões). * Add 'execute_hook' and deprecate 'execute_hooks' for homogeneity with Dancer 2. * send_file will do the right thing if given an IO::Scalar object (David Precious, prompted by Ilya Chesnokov). [ DOCUMENTATION ] * Fix escaping on some docs (Stefan Hornburg @racke). 1.3097 08.07.2012 [ ENHANCEMENTS ] * New keywords 'register_hook' and 'execute_hooks' exported by Dancer::Plugin to provide a consistent way with Dancer 2 to declare and run hooks from within a plugin (Alexis Sukrieh, idea from David Precious). 1.3096 06.07.2012 ** Codename: Chop Hooey // Neil Hooey ** [ ENHANCEMENTS ] * Finally released, thanks to Neil Hooey bugging my sorry ass. 1.3095_02 03.07.2012 [ BUG FIXES ] * fix exception tests in some cases (GH #734) (Damien Krotkine & katkad ) [ ENHANCEMENTS ] * If YAML does not load, Dancer::Config now reports why (Ovid) [ DOCUMENTATION ] * Clarify serialization in introduction POD (Mark A. Stratman) * Typo fix (Sam Kington) 1.3095_01 22.06.2012 [ BUG FIXES ] * Don't assume returned references are blessed when considering continuations (Neil Hooey, GH-778) * Malformed/missing cookies caused warnings (James Aitken/LoonyPandora, GH-782 and GH-783) * Avoid potential crash in t/14_serializer/06_api.t if tmp dir is replaced when %ENV gets cleared (Adam Kennedy) * Properly initialize %callbacks to default empty hashref in _send_file if not provided (Gary Mullen) [ ENHANCEMENTS ] * Add UTC timestamp options for logger_format (Alex C - perlpong). * Tests can now run in parallel (Richard Simões). * dancer_version keyword added (Damien "dams" Krotkine). * New session_domain paramter allows you to set the domain of the default session cookie (William Wolf) [ DOCUMENTATION ] * Update Ubic service example (Vyacheslav Matyukhin) * Silly typo fixing (Paul Fenwick) * Typo in Dancer::Test file upload example (Jonathan "Duke" Leto) * UTF-8 fixes in POD (ambs) 1.3095 01.04.2012 [ BUG FIXES ] * Small fix to skip tests when YAML is not available. (Sawyer X) [ ENHANCEMENTS ] * Added 'info' log level for messages that should always go to the logs but aren't really debug, warning or error messages (Ovid) 1.3094 31.03.2012 [ BUG FIXES ] * GH #763: Fix exceptions in ajax routes clobbering layout (ilmari) * GH #748 & GH 647: Don't force override environment from PLACK_ENV (jwittkoski) * GH #762: fix param parsing lacking limit on split (leejo) * GH #758: Fix Dancer::Test: make sure the request is properly converted to a response. (Ovid) * GH #729: Fix dancer exception composition, and message pattern application (Damien Krotkine) * GH #752: Exceptions raised in hooks were not propagated back to the route code, but instead canceleld and replaced by a Dancer halt exception. That was wrong. Now it is fixed, exceptions raised in hooks can be properly caught in route code. (Damien Krotkine) * Be more flexible in single vs. mutliple values in key hiding. (Sam Kington) * Use isa() for checking relationships instead of ref() in Dancer::Test. (Ovid) [ ENHANCEMENTS ] * Added 'strict_config' option to have the config return an object instead of a hashref. (Ovid) * GH #708: Added support for query strings in dancer_request (Jacob Rideout) * It's possible for the user to set the environments directory using a new environment variable (DANCER_ENVDIR) or using `set envdir => $path` * Sort hash keys when serializing references in log messages (Ovid). [ DOCUMENTATION ] * Explain in POD that if there are multiple fields with the same name, params('fieldname') returns an arrayref of them (alexrj). * GH #750: Fix in Dancer::Deployment: appdir needs to be set before calling load_app (Paul Johnson) * Update 'before' hook document (David Cantrell). 1.3093 29.02.2012 [ BUG FIXES ] * GH #738: Define exception type ::Core::Request, to avoid things blowing up when Dancer::Request raises exceptions of that type (David Precious, thanks to damog for reporting) * GH #671: Fix Dancer::Plugin::Ajax with Plack::Builders. (Activeg, Sawyer X) * Auto-page feature cleanup and fixup. (David Precious) * Remove uninitialized warnings. (Sawyer X, David Precious) [ ENHANCEMENTS ] * Winning release race to Catalyst (nice try rafl++!) * Add exception type ::Core::Request. (David Precious) * JSON decode from UTF8. (Sam Kington) * Provide the method when a route crashes to help debug. (Sam Kington) * More helpful log messages. (David Precious) [ DOCUMENTATION ] * Fix examples for multi-app deployment under Plack::Builder in deployment. * Deployment docs. (c0bra) * Update tutorial. (David Precious) * Clean up EXPORTS. (David Precious) * Keyword documentation fixups. (Kirk Kimmel) * Clarify forward docs with better examples. (David Precious) 1.3092 27.01.2012 [ BUG FIXES ] * Don't call isa() on unblessed refs in Dancer::Exception. (Sam Kington) * Assume UTF-8 by default when serialising JSON. (Sam Kington) * GH #725: If a cookie is set multiple times, last value wins. (David Precious) * More intuitive, backwards compatible appending of default template extension. (GH #716, David Precious) * Prevent recursion in censoring. (Yanick Champoux, Damien dams Krotkine) * GH #734: More tests flexibility (Sawyer X, reported by @birdy-) [ ENHANCEMENTS ] * Return the current set prefix using prefix(). (Michal Wojciechowski) * More intuitive appending of default template extension. Makes for cleaner more DWIM code. (David Precious, reported by Nick Knutov) * Allow any options to JSON serializer. (Lee Johnson) * Support complex views with multiple document roots. (Pedro Melo) [ DOCUMENTATION ] * Document how to work with Dotcloud. (Oliver Gorwits) * Clean ups and fix ups. (David Precious, Sawyer X, Michal Wojciechowski) 1.3091 17.12.2011 [ BUG FIXES ] * Reverting template() behavior by popular demand. (Damien Krotkine) * GH #714: Run post-request hooks when custom continuations were created. (Damien Krotkine) * Always call write_session_id() to update expires. (David Precious) [ ENHANCEMENTS ] * GH #711, #652: Add server_tokens variable to allow removal of headers. (John Wittkoski) [ DOCUMENTATION ] * GH #680: Document problems with multiple apps in Dancer using Plack::Handler::Apache2 and recommend a workaround. (Asaf Gordon, Pedro Melo) * RT #73258: Spelling glitches. (Damyan Ivanov) * Use ":script" instead of ":syntax" in Cookbook. (John Barrett) * Typos in Deployment doc. (David Precious) 1.3090 13.12.2011 ** Codename: Hornburg of Hannover // Stefan Hornburg (racke) ** [ BUG FIXES ] * GH #685: Set VERSION for Dancer::Plugin::Ajax. (Sawyer X, Naveed Massjouni) [ DOCUMENTATION ] * GH #694: Typo fix. (Yanick Champoux) * GH #698: Document further TT init options. (Dennis Lichtenthaeler) * GH #709: Update POD documentation regarding hook. (Stefan Hornburg) 1.3089_01 26.11.2011 [ BUG FIXES ] * Fix bug that made system() fail with -1 under Dancer (felixdo). * Support for 'content_type' option on send_file when sending a system wide file (Emmanuel Rodriguez). * Support HTTP_X_FORWARDED_HOST in behing proxy (Ipaponov). * Deserialize PATCH requests (Sam Kington). * Encode log messages properly if charset UTF-8 is set (David Precious, thanks to Penfold for the fix & MiklerGM for reporting). [ ENHANCEMENTS ] * Continuations-style exception system! (Damien Krotkine). * The ability for dancer_response to send file contents for file uploads as a scalar, instead of reading from file on disk (Squeeks). [ DOCUMENTATION ] * Clean up "plack_middlewares" example in docs (Richard Simões). 1.3080 25.10.2011 ** Codename: Sawyer's Sugar Stream // Sawyer X ** [ ENHANCEMENTS ] * No functional changes, just releasing as stable. 1.3079_05 02.10.2011 [ API CHANGES ] * Deprecation of 'before', 'before_template' and 'after' in favor of hook (Alberto Simões) [ BUG FIXES ] * Minor corrections (jamhed, felixdo) * Log if a view and or a layout is not found (Alberto Simões, reported by David Previous) [ ENHANCEMENTS ] * Add support for the HTTP 'PATCH' verb (David Precious) 1.3079_04 02.10.2011 [ ENHANCEMENTS ] * PSGI handler code cleaned up (chromatic). * Improved warning localizations (chromatic). [ DOCUMENTATION ] * Dancer::Plugins typos (Olof Johansson). * PSGI handler documented (chromatic). 1.3079_03 10.09.2011 [ ENHANCEMENTS ] * Support XML::Simple configuration for serializing/deserializing (Alberto Simões) * Hard deprecate lots of stuff (Alberto Simões) [ BUG FIXES ] * Don't clobber TT INCLUDE_PATH if the user set it specifically in the config file - Issue 643 (David Precious, reported by meraxes) * Don't require a space after semi-colon delimiting multiple name=value cookie pairs - Issue 642 (David Precious, reported by travisbeck) 1.3079_02 28.08.2011 [ BUG FIXES ] * Remove hard-coded version from 404.html and 500.html (Alberto Simões) * Fix logging of UTF8-encoded strings (jamhed) * Do not clean 'vars' during forward (Alberto Simões) [ ENHANCEMENTS ] * Add streaming support to send_file. (Sawyer X) 1.3072 23.08.2011 ** Codename: Precious David Precious // David Precious (bigpresh) ** [ ENHANCEMENTS ] * No functional changes, just releasing as stable. 1.3079_01 17.08.2011 [ BUG FIXES ] * Fix prefix behavior with load_app (alexrj) * send_file() shouldn't clobber previously-set response status (David Precious, reported by tylerdu - thanks!) * Depend on URI 1.59 - Fixes problems when redirecting with UTF-8 strings (Alberto Simões) * Fix before_serializer POD fix (Yanick Champoux) [ ENHANCEMENTS ] * send_file can send data (pass a reference to a scalar), and can specify a content-disposition filename. (Alberto Simões) * Set 'Server' HTTP response header as well as 'X-Powered-By'. For cases where Dancer is being accessed directly, or the proxy passes on this header, it's nice to see it. (David Precious) [ DOCUMENTATION ] * Cookbook links to canonical documentation of keywords in Dancer.pm, so readers encountering a new keyword can easily see the docs for it (David Precious) * Docs for debug/warning/error link to Dancer::Logger for details on how to control where logs go (David Precious) * Document import_warnings option, and mention it & link to that documentation in opportune places. * Document that 'get' also creates a route for 'HEAD' requests (David Precious, prompted by Matt S Trout) * Extend request() keyword docs with examples (David Precious) * Correct port in Lighty/FCGI example in Dancer::Deployment (David Precious, thanks to pwfraley in Issue 621) 1.3071 26.07.2011 ** Security release based on 1.3070 ** [ SECURITY ] * FIX directory traversal issue Since 1.3070, it was possible to abuse the static file serving feature to obtain files from a directory immediately above the directory configured to serve static files from. (Vladimir Lettiev and David Precious) 1.3070 14.07.2011 ** Codename: The Exceptional Mr. Dams // Damien Krotkine (dams) ** [ ENHANCEMENTS ] * No functional changes, just releasing as stable. 1.3069_02 10.07.2011 [ BUG FIXES ] * Fix a bunch of cpan testers reports (Alberto Simões) 1.3069_01 07.07.2011 [ BUG FIXES ] * Fix a bug while parsing some cookies (Franck Cuny) * Documentation and tests on how to use many Dancer application inside one PSGI file (PR 564) (Alex Kalderimis and Franck Cuny) * More flexible test for locale-aware logging (Alberto Simões) * Do not re-read config files when dance starts if they were already loaded. (Alberto Simões) * Fixed shell-dependent tests for Window testing. (Alberto Simões) * Die properly if halt is call inside an hook. (Damien Krotkine and Alberto Simões) * Make template work outside of requests (Issue 592) (David Precious) * Cleanup session tests folder (Issue 594) (Sawyer X) [ ENHANCEMENTS ] * Error Hook (PR 563 - JT Smith) * Exceptions system (Damien Krotkine) * The no prefix can be set using 'prefix "/";' (Alberto Simões) * Support for nested prefixes (Alberto Simões) * Cleanup on Dancer::FileUtils (Sawyer X) * Cleanup on File::Temp dependencies (Sawyer X) [ DOCUMENTATION ] * Documentation on tokens automatically added to templates. (Alberto Simões) * Documentation on serializer magical access to put/posted data. (Alberto Simões) 1.3060 15.06.2011 ** Codename: Pirouetting Pedro // Pedro Melo ** [ ENHANCEMENTS ] * No functional changes, just releasing as stable. 1.3059_04 12.06.2011 [ BUG FIXES ] * Fix a bunch of cpan testers reports (Alberto Simões) 1.3059_03 11.06.2011 [ BUG FIXES ] * Fix for issue #539 https://github.com/sukria/Dancer/issues/539 Don't decode twice entries in the params hash table, file uploads with UTF-8 characters in their name are now possible. (Toby Corkindale, Alexis Sukrieh) * Fix broken test with old version of HTTP::Parser::XS (Franck Cuny) * #492 - Don't run Test::TCP tests on win32 (Franck Cuny) * Fix a bug that when forwarding a post with post data stalled the code (read on no data handle). (Alberto Simões) * Tweak tests regular expression to be more flexible (Pedro Melo) * Require a recent Test::TCP (1.13) to run tests. (Alberto Simões) * Fix hooks implementation that failed when user messes $_ (Pedro Melo) * Fix broken params('query') and params('body') during forward and dancer_request test function. (Alberto Simões and Squeek) [ ENHANCEMENTS ] * Fix for issue #516 https://github.com/sukria/Dancer/issues/516 No more legacy code in Dancer::Route to handle routes created with the deprecated keyword "r". The related code is now more concise and should be slightly more efficient. (Alexis Sukrieh) * Merge PR #541 https://github.com/sukria/Dancer/pull/541 New "param" accessor to retrieve a parameter easily. (Alberto Simões) * Implement session directory testing cache for Session::YAML (Damien Krotkine) * Tests rework (improve speed, remove useless tests, ...) (Alberto Simões and Franck Cuny) * Configuration for log_dir and log_file. (Alberto Simões) * Pass vars to templates automatically (David Precious) * Support lexical prefix (Pedro Melo) [ DOCUMENTATION ] * Improve FileUtils documentation. (mokko) 1.3059_02 29.05.2011 [ BUG FIXES ] * Fix for smoker failure under Perl 5.13.4 http://www.cpantesters.org/cpan/report/b37416b8-88df-11e0-9c74-cad5bcb8094c Better use of Time::Hires in t/22_hooks/04_template.t (Franck Cuny) 1.3059_01 27.05.2011 [ API CHANGES ] * Second level of deprecation for render_with_layout method. (Alberto Simões) * Second level of deprecation for mime_type method. (Alberto Simões) [ BUG FIXES ] * Dancer::Test was broken for tests using data in POST (GH#534) (Franck Cuny) * Multiple setter implemented at 1.3039_01 was broken for App specific settings. (Alberto Simões) [ ENHANCEMENTS ] * Cookie accessor to manipulate cookies directly. (Niko) [ DOCUMENTATION ] * Improve Serializers documentation (Damien Krotkine) 1.3051 27.05.2011 ** Security release based on 1.3050 ** [ SECURITY ] * FIX CVE-2011-1589 (Mojolicious report, but Dancer was vulnerable as well). Return "400 Bad Request" when requested filename seems suspicious http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-1589 (Vladimir Lettiev and Franck Cuny) 1.3050 20.05.2011 ** Codename: The Captain Hook Adventure // Franck Cuny ** [ ENHANCEMENTS ] * No functional changes, just releasing as stable. [ DOCUMENTATION ] * Improve Dancer documentation (Damien Krotkine) 1.3049_01 14.05.2011 [ API CHANGES ] * Deprecation of 'logger' (use set). (Alberto Simões) * Deprecate 'layout' (use set). (Alberto Simões) * Definitely remove plack_middlewares HashRef deprecation. (Alberto Simões & Damien Krotkine) [ BUG FIXES ] * Unbreaking auto_page somewhat - the catch-all route added will pass unless a suitable view exists. This means that routes like /foo are not obscured, and made up URLs will result in a proper 404, not 500. A little more work required here, though. (David Precious) * Anchor regular expression routes. Before regular expressions were matching anywhere in the URL. (Alberto Simões) [ ENHANCEMENTS ] * GH #519: remove redundant lines from CSS (Alberto Simões) * When scaffolding an app, show a warning if YAML not installed. Prompted by Issue 496. (David Precious) * Hooks! add new positions for hooks, and possibility to create your own hooks inside your application and your plugin. (Franck Cuny) * Don't try to read/set session vars with empty/undef keys. It doesn't make sense to do so, and can cause warnings elsewhere. (David Precious) * Check HTTP status code/alias passed to status() is valid; previously, and invalid code would result in the response status being unset (David Precious, prompted on IRC by jonas) * Lowercase status aliases and swap spaces for underscores before trying to match (David Precious, suggested on IRC by jonas) * Added 'behind_proxy' setting, making Dancer honor X_FORWARDED_PROTOCOL and X_FORWARDED_HOST (Alberto Simões, requested by sukria and others) 1.3040 01.05.2011 ** Codename: Yanick in Black // Yanick Champoux, Labor Day - May Day ** [ ENHANCEMENTS ] * No functional changes, just releasing as stable. 1.3039_01 27.04.2011 [ BUG FIXES ] * Fix 404 results from forwarding. (Alberto Simões) * Don't remove trailing slashes from route patterns under prefix. (Brian E. Lozier) * Remove deprecated r() function from list of exports. (Stefan Hornburg) * GH #402: make session_expires honor +2h style formatting. (Michael G. Schwern) * GH #433: encoding issues with forward(). (Alberto Simões) * GH #390: Renaming access_log to startup_info (+doc). (Sawyer X) * Rewrite scalar usage of qw() that is incompatible with 5.14. (Alberto Simões) * Don't parse ARGV when under PSGI (closes #473) (Franck Cuny) [ ENHANCEMENTS ] * Forward can change method GH#493 (Alberto Simões) * Introducing the "megasplat"! (Yanick Champoux) * More tests for versions, setings and variables. (Alberto Simões) * Improve Dancer::Test so failures report the correct line numbers. (Michael G. Schwern) * GH #466: Can now set cookies with http_only => 0 for JS integration. (Alberto Simões) * Session engine can be told to set cookies without HttpOnly attribute using new session_is_http_only setting. (Alberto Simões, requested by JT Smith) * GH #296: Show versions of loaded modules in startup info. (Sawyer X) * Able to set more than one value at once using set(). (Alberto Simões) * GH #253: Use Clone::clone() if available to clone data before censoring. (Sawyer X) * GH #246: Dancer::Test can now test for file uploads as well. (Franck Cuny) * Allow parameters in forward(). (Alberto Simões) [ DOCUMENTATION ] * Major rewrite/reorganization on Dancer::Config documentation. (David Precious, pushed by Alberto Simões PR) * GH #284: Document hosting multiples Dancer apps in a single PSGI file. (Franck Cuny) * Dancer::Session POD typos and spurious characters. (Stefan Hornburg) 1.3030 13.04.2011 ** Codename: Silence of the ambs // Alberto Simões ** [ ENHANCEMENTS ] * Change the flag for sending system-wide path with send_file to 'system_path' (was 'absolute'). (Alberto Simões) 1.3029_03 10.04.2011 [ BUG FIXES ] * Dancer::Session::Cookie 0.14 is required for dependency test. * Only test for undef serializer if we have the default (JSON) available. (Sawyer X) [ ENHANCEMENTS ] * Test before_template & auto_page. 1.3029_02 08.04.2011 [ BUG FIXES ] * Better way to initialize the logdir in Dancer::Logger::File. Works now cleanly if the appdir is not writable but the logdir exist and is writable. (Alberto Simões) * fix warnings in t/03_route_handler/28_plack_mount.t. (Franck Cuny) [ ENHANCEMENTS ] * Support for error templates. If the setting "error_template" is set, it is used when building an error page instead of using the default template. Added the appropirate documentation as well. (Alberto Simões) * Dancer::Test::dancer_response() returns a 404 response when no route handler is found. This is consistent with what Dancer does internally. (Alberto Simões) * Dancer::Test provides a new helper for inspecting subsets of headers: "response_headers_include". (Alberto Simões, Alexis Sukrieh) * dancer_response now handles the rendering of static pages as well. (Alberto Simões) * Cleanup some tests. (Alberto Simões) [ DOCUMENTATION ] * POD fix. (Stefan Hornburg - Racke) 1.3029_01 01.04.2011 [ BUG FIXES ] * Fix t/14_serializer/02_json.t to work with older JSON (relates to GH#416) (Damien Krotkine) * the Changelog test now supports Codenames. It suggests to add codenames for table releaes as well (Damien Krotkine) * GH #420: Extra content generated (Alberto Simões, Damien Krotkine) * GH #409: If pass has no more matching routes, return 404. (Alberto Simões) [ ENHANCEMENTS ] * GH #396: Test that Dancer::Session::Cookie isn't broken (Michael G. Schwern) * GH #399: Make sure session can have their name changed. (Michael G. Schwern) * Dancer::Test tests assumes 'GET' if their first argument is scalar. (Yanick Champoux) * send_file accepts optional content-type declaration, to override guessed MIME type, e.g. send_file $filename, content_type => 'image/png' (Alberto Simões, requested by Michael G Schwern) * send_file accepts optional absolute option, to send an absolute path (Alberto Simões) * Have `dancer` cmd tool create MANIFEST and MANIFEST.SKIP. (Alberto Simões) * mime_type is deprecated; new keyword 'mime'; new config key 'default_mime_type'; (Alberto Simões and Michael G. Schwern) * Recognize absolute redirects (Yanick Champoux) [ DOCUMENTATION ] * Add documentation to send_file optional argument (Alberto Simões) * Fix plack_middlewares example in the cookbook (Michael G. Schwern) * Extend the POD on plugin_setting to prevent a pitfall with plugin modules more than 3 levels deep. (Stefan Hornburg) * GH #400: Documenting the plack_middlewares_map. (Michael G. Schwern, Sawyer X) * GH #422: Documenting no need for caret when you have a prefix. (Sawyer X) 1.3020 21.03.2011 ** Codename: The Schwern Cometh // Michael G. Schwern ** [ ENHANCEMENTS ] * No functional changes, just releasing as stable. 1.3019_02 14.03.2011 [ BUG FIXES ] * GH #354: Tokens are not passed to layout if no params are passed to template. (Damien Krotkine) 1.3019_01 13.03.2011 [ BUG FIXES ] * GH #393: Reset vars for each new request. (Franck Cuny) [ ENHANCEMENTS ] * GH #391: Dancer::Logger::Note now exists. :) (Sawyer X) * Porting documentation on WRAPPER to Dancer::Template::TemplateToolkit. (Sawyer X) * GH #387: Document views and appdir in Dancer::Config. (Michael G. Schwern) * Add a new symbol to exporter ':script'. (Franck Cuny) * GH #397: Support cookie expire times like "+2h". (Michael G. Schwern) 1.3014_01 10.03.2011 [ BUG FIXES ] * GH #373: Display valid path to the main app file in the welcome screen. (Franck Cuny) * GH #152, GH #170, GH #362: Log dir is not created when logger is not set to 'file', and setting log_path works as expected. (Franck Cuny) * GH #308: Use request's uri_base. (Sawyer X) * GH #378: Some routes with prefix where wrongly matched. (Franck Cuny) [ ENHANCEMENTS ] * GH #351: Explicitly exclude some keywords when important Dancer's syntax, add modes that also excludes some keywords (:moose, :tests). (Sawyer X, Naveed Massjouni, Michael G. Schwern, Franck Cuny) * All logging options accept any number of variables. (Sawyer X) * GH #297: All logging options can automatically serialize references. (Sawyer X) * Add Dancer::Logger::Capture to capture and read log messages during testing. (Michael G. Schwern) * Dancer::Cookie make secure (https only) cookies. It also adds the "session_secure" setting instructing sessions to use secure cookies. (Michael G. Schwern) * Adding uri_base to Request.pm. (Sawyer X) * Make Dancer::Test use the capture logger (Michael G. Schwern) [ DOCUMENTATION ] * Dancing on command line. (Maurice Mengel) * Improve Dancer::Cookbook. (Maurice Mengel) 1.3014 04.03.2011 [ BUG FIXES ] * YAML Session UTF-8 Fix (Roman Galeev) * Tests and documentations for Dancer::Request::Upload + type method in Dancer::Request::Upload (Michael G. Schwern) * Dancer::Test::dancer_response handles correctly its 'body' parameter We can now pass a hash ref as the body of dancer_response, it will automatically be serialized as an URL-encoded string with the appropriate content_type header. (Alexis Sukrieh) 1.3013 01.03.2011 [ ENHANCEMENTS ] * Fix test suite: the changelog test is skipped if not under RELEASE_TESTING environment. 1.3012 01.03.2011 [ BUG FIXES ] * Fix cookies disappearing when more than one is set. Complete refactoring of the cookie handling. (Chris Andrews, Geistteufel) * Properly set the settings in Dancer::Test only after config loading. (Sawyer X) * Fix possible loss of last directory in path. (Sawyer X) * No need for default upper directory in Dancer::Test. This fixes an issue raised on the list about the default scaffolded test failing. (Sawyer X) * Fix anti UNC substitution under Cygwin (Rowan Thorpe) * GH#299 Return appropriate headers on HEAD request (content-type, ...) (franck cuny) * Use the dancer_version variable in scaffolded app. (Sawyer X, reported by Brian E. Lozier) [ ENHANCEMENTS ] * Fix manifest (Damien Krotkine) * Various packaging, changelog and test fixes (Damien Krotkine) * Add a new accessor to Dancer::Request: ->uri. (it's an alias to ->request_uri) (Franck Cuny) * Removes Dancer::Helpers, refactor Dancer.pm accordingly. (Franck Cuny) * Introduce changelog test of hell. (Damien Krotkine) * Add Dancer::Logger::Null. (Sawyer X) * Add Dancer::Logger::Diag. (Sawyer X) * Refactor Dancer::Response (franck cuny) * Allow to use a subclass of Template::Toolkit. (Michael G. Schwern) * Dancer::Test now uses Dancer::Logger::Null instead of ::File. (Sawyer X) * Add Dancer::Deprecation. (handle deprecation messages) (franck cuny) * Introduce new timestamp format in logger (%T) (Roman Galeev) * Refactoring of the forward method (Alex Kalderimis) * Refactoring of internal objects in the core, use more of Dancer::Object. Introduce attributes_defaults (Damien Krotkine) * Add a perl_version variable to all templates, used in scaffolded app. (Sawyer X, reported by Brian E. Lozier) * Better output when template file is missing. (Brian E. Lozier, Sawyer X) [ DOCUMENTATION ] * Add missing methods (e.g. "referer"), sorting, clean up. (Flavio Poletti) * Complete working example of deployment under Nginx/Starman in Deployment.pod (Geistteufel) 1.3010_01 12.02.2011 [ BUG FIXES ] * GH#136: fix again Mime::Type issues in preforking environment (Chris Andrews) * GH#220: fix for path issues under MacOS X and Windows platforms. A new function is provided by Dancer::FileUtils: path_no_verify() (Rowan Thorpe) * Fix for infinite loops detection in before filters (Flavio Poletti) [ ENHANCEMENTS ] * Better detection of the application layout under non-UNIX platforms. (Rowan Thorpe, Alexis Sukrieh) [ DOCUMENTATION ] * Fix a typo in Dancer::Request::Upload's POD (Rowan Thorpe) * Better documentation for the before filters, explanations about the potential infinite loops that can happen when using before filters (and what Dancer does in that case). (Flavio Poletti) 1.3011 14.02.2011 [ BUG FIXES ] * Set binmode in write_data_to_file() to fix image corruption in Windows (Rowan Thorpe) * GH#319, GH#278, GH#276, GH#217: Fix file issues on Cygwin and Win32 platforms (Rowan Thorpe) * GH#322: Detect errors in scaffolded dispatchers (Alberto Simões) * Fix tests so that they don't fail if JSON is not installed (Damien Krotkine) [ DOCUMENTATION ] * Small spaces fix (Alberto Simões). 1.3010_01 12.02.2011 [ BUG FIXES ] * GH#136: fix again Mime::Type issues in preforking environment (Chris Andrews) * GH#220: fix for path issues under MacOS X and Windows platforms. A new function is provided by Dancer::FileUtils: path_no_verify() (Rowan Thorpe) * Fix for infinite loops detection in before filters (Flavio Poletti) [ ENHANCEMENTS ] * Better detection of the application layout under non-UNIX platforms. (Rowan Thorpe, Alexis Sukrieh) [ DOCUMENTATION ] * Fix a typo in Dancer::Request::Upload's POD (Rowan Thorpe) * Better documentation for the before filters, explanations about the potential infinite loops that can happen when using before filters (and what Dancer does in that case). (Flavio Poletti) 1.3010 10.02.2011 [ BUG FIXES ] * GH#303: Generated Makefile.PL's clean is done correctly now. (Sawyer X) * Minimum version of HTTP::Headers to avoid test fails. (LoonyPandora) * Do not require JSON to get version number (fixes tests). (Sawyer X) [ ENHANCEMENTS ] * Allow read_file DWIMishness using wantarray. (LoonyPandora) * Tidy up Dancer.pm (Damien Krotkine) * Document forward should use return. (Sawyer X) * GH#290: Use return with redirect examples in docs. (Damien Krotkine) * Document that base() returns a URI object. (David Precious) * Show version when starting standalone server. (David Precious) 1.3003 06.02.2011 [ API CHANGES ] * Remove load_plugin from the core's DSL (was deprecated). [ BUG FIXES ] * Eliminate test warnings on Windows. (Gabor Szabo) * GH#271 - use correct VERSION_FROM in scaffolded application. (Sawyer X) * GH#260 - send_file doesn't clobber existing headers (Alexis Sukrieh) * logger unicode bugfix in the formated date (jahmed) * GH#281 - Don't crash if splat is used with no captures (David Precious) * Possible to given "template" a view name with the extenstion. (Alexis Sukrieh) [ ENHANCEMENTS ] * New setting log_path to allow for alternalte logging path in logger "file". (Natal Ngétal) * GH#289: Add more aliases on the ENV, provide more smart accessors to Plack env entries (Franck Cuny) Dancer 1.3002 [ API CHANGES ] * to_json and from_json accept options as hashref instead of hash. Passing arguments as hash is deprecated (Franck Cuny). [ BUGFIXES ] * status is kept even when halt is used in a before filter (Alexis Sukrieh) * Proper handling of temporary file creation using File::Temp module instead of homebrew solution. (jahmed) * Logger::Abstract unicode bug fix. (jahmed) [ ENHANCEMENTS ] * In development, pretty-print JSON serializations for easier development (Ask Bjørn Hansen) Dancer 1.3001 [ Flavio Poletti ] * Added "git fetch upstream" for remote tracking * turned a tab into the right number of spaces * Fix weird Plack error "status code needs to be an integer greater than or equal to 100", because of a typo in a call to Dancer::Error (Closes issue GH#264) [ Franck Cuny ] * uri_(un)escape cookie value; closes GH-248 * remove websocket tutorial (it has its own distro now) * add a new tests to make sure unknown templates produce a warning * path for send_file must be relative from the public directory * Support for complex values in cookies (scalars, flat arrays and flat hashes). Fixes issue GH#249 [ David Precious ] * Point people towards D::P::Database in the tutorial. * Mention leaving ratings on cpanratings. * Some minor typo fixed in the documentations. [ mokko ] * typos and a little more substatial changes to Development.pod [ Hagen Fuchs ] * Request.pm Decode HTTP::Request's uploads [ Alberto Simoes ] * Support for aliases for content_type and refactoring of mime-types handling, with a new class Dancer::MIME (closes issue GH #124) * Deprecation of Dancer::Config::mime_types (now handled by Dancer::MIME). [ jahmed ] * Fix a bug in YAML session backend, during the creation of the session file. Dancer 1.3000_02 [ Sawyer X ] * Added forward() functionality (incl. tests and docs) [ Damien Krotkine ] * FIX for --no-check switch in script/dancer * Refactoring of Dancer::Template::Abstract - add support of apply_layout and apply_renderer - deprecation of render_with_layout (now handled better) - add an accessor "engine" to the DSL to access any engine singleton - better interface for Dancer::Object and Dancer::Object::Singleton - updated tests accordingly [ Jonathan Otsuka ] * Bring dancer application creation pod up-to-date 1.2003 Dancer 1.3000_01 [ Damien Krotkine ] * Better check of keywords used in plugins. * internal refactoring: - Dancer::Object::Singleton added to refactor engines later - Support of inheritance in attributes declared with Dancer::Object [ jamhed ] * Fix some unicode issues, refactored all file openings in one function in Dancer::FileUtils. [ Gabor Szabo ] * Adding test for multi-leveled scaffolding. [ Maurice Mengel (mokko) ] * Skip file upload tests on Cygwin, not just win32. [ Alan Haggai ] * Fixing up typos in various places. * Show the correct filename in usage. [ Alexis Sukrieh ] * Update documentation for developers. Dancer::Development reflects the new releases startegy since 1.2 is out. Also better explaining about how to contribute pull-requests to the core team. * New documentation for integrators: Dancer::Development::Integration describes precisely how integrators should handle pull-requests. [ Naveen ] * add a --no-check switch to script/dancer to disable remote check of new Dancer versions. [ Philippe Bruhat ] * add script/wallflower, helper to turn a Dancer application into a static web site. * better behaviour for plugin_setting (better search, more user-friendly) [ Franck Cuny ] * Support for configurable log format in logger engines * Refactoring of Dancer::Route, some optimisations and code cleanup * Add several tests to increase the coverage (reached 92.4%, for 1399 tests) Dancer 1.2003 * Production release. Dancer 1.2002_02 [ Danijel Tasov ] * Correct HTTP.pm POD's 503 entry with 403. [ Paul Tomlin ] * Tests for URI object in uri_for. * Update Plack middleware tests compatibility. Dancer 1.2002_01 [ Joel Roth ] * Code fixes in documentation (Dancer::Session, Dancer::Introduction). [ Franck Cuny ] * Fix test failures on old machines with Test::More without done_testing. Dancer 1.2002 * Productionized! :) Dancer 1.2001_01 [ David Precious, Ivan Bessarabov ] * Fixing TT example config. [ Danijel Tasov ] * Default layout now validates. Dancer 1.2001 [ Sawyer X ] * Fix clash with KiokuDB because of Dancer::Serializer::Dumper. [ Franck Cuny ] * Refactoring engine triggers. This resolves an issue of engine inits being run before all configuration is read. That also crashes D::S::Cookie. As a side effect we now have a refactored _set_setting() which does not trigger any engine hooks (unlike setting()). * Fix failing test t/07_apphandlers/06_debug.t [ David Precious ] * Doc fixes. Clarifications to Cookbook's REST section. * Don't crash if application name is invalid and provide better information. Dancer 1.2000 ** 1.2 is a stable release of Dancer ** ** We assure consistency and stability for this release and the following ** ** 1.2xxx releases; you should not have issues updating to any 1.2xxx ** ** version because of it. ** ++ A very special thanks goes to the Dancer community who improved and ++ ++ perfected this release and worked hard on reporting bugs, fixing them, ++ ++ improving the stability, providing important features and everything ++ ++ else which makes Dancer so attractive - and above all: its community ++ ++ so thank you! ++ [ Sawyer X ] * Fixing some more XML tests with missing preqreqs. Dancer 1.1999_04 (RC4) [ Sawyer X ] * Load Plack::Loader dynamically in test. [ Yanick Champoux ] * Doc fix. Dancer 1.1999_03 (RC3) [ Alexis Sukrieh ] * Transparent unicode support Dancer now takes care transparently of decoding unicode strings used within route handlers and encoding them back before sending a response content. Once the 'charset' setting is set, the user has nothing more to do to have a working unicode-aware application. * FIX for issue #172 More documentation added to Dancer::Request, all public method are documented. A pod coverage test has been added for this module. * Documentation update The deployment documentation is more precise about cgi/fast-cgi deployment under Apache. * FIX for issue GH#171 Scaffolded configuration files are fully commented in order to quickly guide the user in her first steps. [ Damien Krotkine ] * Fix Dancer::Plugin OO issue [ Danijel Tasov ] * Fixed expires in cookies + tests [ Philippe Bruhat ] * Dancer::Logger::Abstract: turn _should() into a closure, and avoid setting up the hash again and agai [ Franck Cuny ] * Closes issue 181 (unknown log level) * Plack middlewares must be listed in an arrayref (listing them in a hashref is now deprecated) [ Al Newkirk ] * fixed redirect to redirect immediately (+ refactoring by franck) [ Dave Doyle ] * clarify Pod as to how before_template works [ Sawyer X ] * Overhaul tests to use lib t/lib instead of t::lib::. (fixes Windows test fails) * PSGI envs on Windows is in capital letters. (fixes Windows test fails) * Add tests on every required directory to create a fake environment. (realpath() on Windows fails when path doesn't exist) Dancer 1.1999_02 (RC2) [ Mark Allen ] * Add a tutorial (Dancer::Tutorial) * example application 'Dancr', provided in example/ [ Franck Cuny ] * Dancer::Test load D::Session::Simple * rewrite how Dancer handle HTTP headers - no more Dancer::Headers - all headers are HTTP::Headers object [ Philippe Bruhat ] * use Pod::Usage [ Damien Krotkine ] * replace all die and warn with croak and carp [ Alexis Sukrieh ] * FIX for issue GH #151 utf8 pragma is imported automatically when Dancer is loaded to allow the usage of UTF-8 strings in the application code. (Thanks to kocoureasy for the report). * FIX for "UTF-8" issues (GH#153): - response content is encoded only if content_type is text - charset setting is normalized to UTF-8 when appropriate - automatically decode UTF-8 strings in params * FIX scaffolded dispatchers (script/dancer) The PLACK_ENV variable is not propagated by Apoache to the dispatchers (at least with our Deployment examples) so the dispatchers aren't aware of the PSGI context if we don't tell them explicitly. This patch forces the dispatchers in PSGI mode. * FIX (unknown bug) When a serializer is set and show_errors is true, don't expose internal errors caught. [ Naveen ] * add --version to the dancer CLI * changed the URI fetched by the dancer script to check Dancer's version Dancer 1.1999_01 (RC1) [ Alexis Sukrieh ] * FIX for utf8 content in views Dancer now handles correctly templates with non-ASCII characters in views. All you have to do is to set the "charset" setting in your config. Your content response will then be encoded appropriately on-the-fly by Dancer. * Scaffolded app sets the charset to "utf8" by default. * Better design for the scaffolded app (logo, favicon and background image added) * Environment info available on scaffolded app * LWP is used by the dancer helper to download files * jQuery 1.4.2 (minified) is included in the scaffolded app * default layout uses <% request.base %> in order to support mounted apps (Thanks to Naveed Massjouni and Franck Cuny for the concept/idea). * The main.tt layout sources jQuery first from Google CDN and falls back to the local minified version if on offline mode. * New default token provided to the "template" helper: dancer_version [ Sebastian de Castelberg ] * The dancer helper is able to download files via a transparent proxy (thanks to LWP). [ Adam J. Foxson ] * FIX for issue GH#136: "readline() on closed filehandle DATA" error that appears when running the app with Starman [ Naveed Massjouni ] * Dancer::Test function get_response is renamed to dancer_response get_response still works but is deprecated * dispatch.f?cgi scripts use FindBin to resolve their location. FIX a bug when using symlinks. [ Franck Cuny ] * FIX for issue GH#129 don't add multiple content-type to headers * fix broken tests (they were testing incorrect content type) [ Damien Krotkine ] * FIX for issue GH#115 documentation about compression in Dancer::Deployment [ David Precious ] * Make the 'layout' param to the template keyword work as you'd expect and allow you to set a custom layout to use, e.g.: template 'templatename', {}, { layout => 'layoutname' }; [ Philippe Bruhat ] * Make sure a plugin refuse to register a keyword twice [ Sawyer X ] * Lots of documentation updates * Dancer now logs caught crashes in rendering (easier to debug Ajax routes) Dancer 1.1904 [ Sawyer X, Franck Cuny ] * SAX, not Sax. * Check for XML::Parser or XML::SAX in test as well. Dancer 1.1903 [ Sawyer X, Franck Cuny ] * XML::Simple needs either XML::SAX or XML::Parser. (fixed test fails from Dancer::Serializer::XML) Dancer 1.1902 [ Adam J. Foxson ] * Addresses issue #136: "readline() on closed filehandle DATA" Dancer 1.1901 (1.2RC0) [ Franck Cuny ] * implemented GH#120: - methods {to,from}_{xml,json,yaml} accept more than one arguments. The first argument is the data to transform. All the remainings arguments are parameters to alter the behavior of the serializers. Refer to the documentation for more informations. * more tests added [ Alexis Sukrieh ] * load_plugin is DEPRECATED; 'use' should be used instead to load a plugin. This is fixes the major issue with plugins about symbol exports that didn't work well (issue #101). * All paths built in a scaffolded application are dynamic, it's now possible to move a scaffolded application after it's been generated. (fixes issues #88, * The auto_reload feature is now disabled by default due to too many unsolved issues (it works most of the time, but some race conditions are still present) This feature is still being working on, but it's now flagged "experimental"). * Default log level in development environment is now 'core' in order to provide more information. * New scaffolded application design. More neutral and with lots of information for a beginner, and links to useful material. Based on the Ruby on Rails start page (kudos to the Rails team, http://www.rubyonrails.org). [ Boris Shomodjvarac ] * Support for a clean way for Template engines to define their template file extensions (issue #126). Dancer 1.1812 [ Franck Cuny ] * Skip bogus uploads test on Win32 (thanks to Alias for reporting) [ Alexis Sukrieh ] * Fix for scaffolded apps * Dancer::Deployment cleanup (CGI section) * Declare LWP explicitly (already implied by HTTP::Body and HTTP::Headers) [ Sawyer X ] * Nitpicking at tabs and spaces at end of lines Dancer 1.1811 [ Franck Cuny ] * FIX for issue #113 and #112 [ Naveed Massjouni ] * FIX for issues #111 and #108 Dancer 1.1810 [ Naveed Massjouni ] * FIX for issue #108 replaced Clone::clone() with Storable::dclone(). * Fixed the plan of one of the test files. [ Alexis Sukrieh ] * Fix a test that depends on YAML (pass if not present) (Smoker failure '2010-08-30T11:07:59Z'). Dancer 1.1809 [ Franck Cuny ] * update Deployement.pod and Cookbook.pod * fix bug in route building with prefix * don't use app.psgi anymore in generated scripts * fix GH#106: serializer * fix bug in PSGI handler using HTTP::Headers when using some header * fix bug in ajax query * more tests [ Alexis Sukrieh ] * fix plan for t/03_route_handler/24_named_captures.t Dancer 1.1808 [ Alexis Sukrieh ] * FIX test failures - t/08_session/07_session_expires.t - t/08_session/07_session_expires.t Dancer 1.1807 [ Sawyer X ] * Fix for RT #60403: removing Test::Exception requirement [ Alexis Sukrieh ] * Global rewrite of Dancer's core to allow support for sub-application, better route resolution and a better design. * Support for mountable applications via "load_app". Mounted applications can have their own settings registry and can be mounted under a given prefix. [ Franck Cuny ] * Support for new hooks: - after: to allow response post-processing - before_template: to allow defaut tokens to be given at anytime to the template function. * Fix and test for bug RT#57829 (Custom response headers lost when using JSON serializer) * FIX PSGI compatibility layer (request->path_info is used when appropriate instead of request->path) * FIX for GH#100 When loading a module, it's possible to require a minimal version. * New option "ajax" for route handlers. * Fix a bug in ajax route when processing the route resolution (when a route is defined with options, it's pushed in the beggining of the route handler tree). [ jamhed ] * Support for new setting "session_expire" in order to allow session cookies to expire before the browser is closed. [ Naveed Massjouni ] * Dancer::Test can now test requests with a body Dancer 1.1806_02 [James Aitken] * fix issues GH #84 #86 and #87 (failing tests on < 5.10 due to regex with named captures) [franck cuny] * update cookbook [François Charlier] * fix for GH#76 and GH#88 [David Precious] * Add Dancer::Plugins POD, describing useful plugins * Extend sessions & logging in entry in cookbook Dancer 1.1806_01 [ sebastian de castelberg ] * Support for path_info() in Dancer::Request so it's possible to mount an application under a directory. [ Alexis Sukrieh ] * Fix for RT#56239 logger calls are better traced * Fix for GH#72 New keyword 'load_plugin' for loading a plugin in the current namespace. Plugins can be used anywhere thanks to that method. * Fix for issue #77 Passing and caching works well together again. * Applied miyagawa's patch for droping the app.psgi file. Refactoring of Dancer::Handler::PSGI and friends. * Applied LoonyPandora's patch for checking Dancer's VERSION when running script/dancer. Changed it a bit so it can check against CPAN rather than GitHub. * Documentation update: r('') is now DEPRECATED, the method triggers a warning when called and will be removed in the next stable release (1.2). * Transparent wrapping of Plack middlewares in Dancer's configuration. It's possible to enable/disable middlewares right from Dancer's config files. Thanks to Tatsuiko Miyagawa and Franck Cuny for their help. [jbarratt] * Dancer::Serializer::JSON supports 'allow_blessed' and 'convert_blessed' options. [ Marc Chantreux ] * Support for regexp objects in route definition * Support for named captures (keyword 'captures' added to Dancer's syntax). Dancer 1.1805 [ Alexis Sukrieh ] * Fix for RT#56239 logger calls are better traced * Fix for GH#72 New keyword 'load_plugin' for loading a plugin in the current namespace. Plugins can be used anywhere thanks to that method. [ Minty ] * Update Introduction pod with (required) -a dancer opt (Murray, 5 hours ago) * Bump HTTP::Body dependency to 1.07 (Murray, 6 hours ago) Dancer 1.804 [ sebastian de castelberg ] * Fix priority in D::S::Mutable. [ David Precious ] * Fix test failures with old Plack versions (Issue 73). * Don't surround content with

tags in layout. * Add $ENV{REMOTE_ADDR} in core log messages [ SawyerX ] * Fix issue #75, reported by nanis. perl -MDancer -e "print $Dancer::VERSION" now works as expected [ Daniel Pittman ] * FIX for issue #80 Make sure the tempfiles created during uploads are removed when the request object dies. [ Alexis Sukrieh ] * FIX for bug RT#58355 Rewrite of Dancer::Template::Simple's parser, now more robust, based on Perl's regexp engine. * FIX a warning when remote_address is undefined Dancer 1.1803 [ Alexis Sukrieh ] * Fix for issue #69 The issue was resolved in 1.1801, this time, the fix is working as expected. [ Sawyer X ] * Fix for RT #57715, require Test::More 0.88 and up. Dancer 1.1802 [ Sawyer X ] * Fix RT #57158 (route_cache does not work with multiple parameters) Cache revealed a small design overlook of not cloning a route before returning it to the user, making multiple parameters disabled. (Thanks to Stéphane Alnet for reporting and adding a test for it!) Dancer 1.1801 [ Alexis Sukrieh ] * FIX issue #69 Error are trapped even if occuring from Dancer's source code. auto_reload is set to false in scaffolded applications to prevent errors if Module::Refresh is not installed. Dancer 1.1800 [ Alexis Sukrieh ] * merge of the devel branch into master, first stable release of 1.178_01 and 1.178_02 Dancer 1.178_02 [ Alexis Sukrieh ] * Errors are caught in before filters * halt can be given a Dancer::Response object rahter than plain text content Dancer 1.178_01 [ Alexis Sukrieh ] * New logger for sending log message to STDERR: Dancer::Logger::Console Thanks to Gabor Szabo for the idea. * Logger engines don't have anymore to implement _format(), they can use $self->format_message instead. * New log level: "core" for letting Dancer's core express itself on crucial events. That way, when the app config sets log to "core", any core messages is sent to the logger, and the end-user can see which route is chosen for each request received. Thanks to Gabor Szabo for the idea. * New class Dancer::Timer added so any logger engine can now show a timer string. * Scaffolded applications are now built like a CPAN distribution, with a Makefile.PL and test scripts (thanks to Gabor Szabo for the idea). * Added Dancer::Test to provide helpers for writing test script for Dancer applications * FIX bug when returning a void context after redirecting a route. Thanks to Juan J. Martínez for the report. * Add support for request headers in Dancer::Request * Add support for halt() in Dancer's syntax. [ Alex Kapranof ] * Support for on-the-fly charset encoding when the setting is set and a content is sent by Dancer and needs to be encoded. The response Content-Type is updated accordingly as well. [ Sawyer X ] * Adding "import_warnings" settings. On by default, but allows to disable auto-import of "warnings" pragma. Reported by Adam Kennedy. Dnacer 1.176 * Bringing 1.175_01 into production. Dancer 1.175_01 (Developer release) [ Sawyer X ] * Documentation for Dancer::FileUtils. * Documentation for Dancer::Cookie. * Fixing PNG bug on IE (reported by Adam Kennedy - thank you). Dancer 1.175 [ Sawyer X ] * RT #56395 reported by Jonathan Yu on behalf of Debian Perl team. * Documentation for Dancer::Error. [ Alexis Sukrieh ] * fixed t/15_plugins/02_config.t when YAML is not installed Dancer 1.174 [ Gabor Szabo ] * Docs fixes, typo in warning. * TestUtils.pm is now in "t/lib". [ David Precious ] * Support semi-colons as name=value pair separators when parsing querystring. Satisfies feature request/issue 59. Thanks to deepakg for requesting this feature. [ Sawyer X ] * RT #56381 reported by Jonathan Yu on behalf of Debian Perl team. (Adding LICENSE file) Dancer 1.173_01 (Developer release) [ Franck Cuny ] * Doc fixes. (Thanks to poisonbit) * Plugins configuration * Cleaning up tests [ Alexis Sukrieh ] * New serializer: Dumper for easily output dumped variable in text/plain. * Before filters can now access route params * Support for '.' as a token separator in params parsing * The standalone server respect the 'access_log' setting, the starting banner is printed on STDERR only if the setting is set to true. [ Sawyer X ] * Fixed Windows PSGI.URL_SCHEME bug, causing tests to fail (Thanks to ADAMK for reporting) Dancer 1.173 [ Alexis Sukrieh ] * Documenting set_cookie in Dancer.pm. [ Franck Cuny ] * Cleaning up serializer test. [ François Charlier ] * Documenting layout disabling. [ Sawyer X ] * Fix a few failing tests because of compilation errors. * Add init{} subs for all serializers. * Dancer::Engine documentation [ David Precious ] * Fix issue 52 - creating invalid cookie expiration dates. Thanks to Juanjo (reidrac) for reporting! Dancer 1.172 [ Alexis Sukrieh ] * Plugin support. [ Franck Cuny ] * Prevent usage of reserved Dancer keywords in plugins. * Tests cleanups. [ Robert Olson ] * Fixing docs to clarify layouts can use variables too. Dancer 1.171 [ Alexis Sukrieh ] * Removed bogus TestApp/ directory Dancer 1.170 [ David Precious ] * Fixed bug with status keyword not converting aliases (e.g. 'not_found') to real usable status lines with valid HTTP codes. Thanks to P Kishor for reporting this on the dancer-users mailing list! * Accept end_tag as a synonym for stop_tag when configuring TemplateToolkit. Thanks to James Ronan for bringing this up. [ Sawyer X] * Route::Cache store_route = store_path, beefed up docs * Changed names of limits in settings * Added documentation for it in Dancer.pm * More documentation about Module::Refresh dependency (closes bug #48) * uri_for now accepts a boolean for not escaping URIs, and redirect calls uri_for with that boolean. (closes: bug #47) [ Alexis Sukrieh ] * Query string params are not dropped anymore when their value is 0. thanks to "Squeeks" for the report. (closes: bug #49) * Support for file uploads The Dancer::Request class provides a common interface to access file uploads. Syntactic sugar has been added to Dancer's as well (keyword 'upload'). (closes whish #36) [ Franck Cuny ] * Support for automatic serialization/deserialization Dancer is now able to serialize route handler's response in various format (JSON, YAML, XML); and can also deserialize request body when appropriate. (closes: wish #29) Dancer 1.160 [ David Precious ] * Added session backend Dancer::Session::Simple * Dump session contents on development error page, if session is in use * Censor sensitive-looking information on development error page settings / session dumps, to help avoid passwords / card details etc being leaked. * Add deployment guide [ Alexis Sukrieh ] * Dancer helper propagates its perl executable into the generated $appname.pl script (FIX for RT #54759). * FIX for issue #34 No more warnings undeer Win32 for tests script that needs a tempdir * FIX (unknown bug) The standalone server now parses commandline options (was broken since 1.140). * FIX for issue #37 A new setting "confdir" is provided for making Dancer read the application configuration files from an alternate location. * Core settings can be initialized via environment variables, prefixed with "DANCER_" (e.g. "DANCER_DAEMON" for the setting "daemon"). * Config and command-line arguments are parsed and loaded at import time, rather than when the handler is initialized. * Routes are compiled at startup instead of being compiled whenever a request is handled. This can increase performances up to 50%. * FIX Params are not polluted anymore by the 'splat' keyword when no capture is needed by the pattern. * New feature 'auto_page' (closes: #41) Lets the user have automatic route resolution for requests that match an existing template in the views dir. Thanks to David Precious for the idea and his help. [ Daniel Tasov ] * Plack environment is propagated to Dancer if none specified. [ Sawyer X ] * Route Caching with size and path number limits: Dancer::Route::Cache. * FIX for issue #39. * Dancer::ModuleLoader documentation * Cleaned Dancer::Template::Abstract docs * Cleaner die in Dancer::Engine if can't find engine * Added default route example in Dancer::Cookbook Dancer 1.150 [ Alexis Sukrieh ] * Refactored all core engines with Dancer::Engine * Support for engine configuration via config files * Each core template engine now uses start_tag/stop_tag from the configuration instead of harcoding '<%' and '%>'. * FIX for issue #34 Cookies can now be used when the application is ran under a Plack server. [ David Precious ] * Lots of documentation cleaning and fixes. * Make the session available to the views, if possible. * Added Dancer::Cookbook to provide lots of concrete examples for newcomers. * Helper script `dancer' now provides a default favicon.ico in the application public directory. * FIX for issue #30 Added 'config' method to provide easy access to app config [ Anirvan Chatterjee ] * Various documentation typo fixes [ Danijel Tasov ] * FIX for issue #24 Dancer now depends on MIME::Types rather than using File::MimeInfo::Simple which uses a fork(). [ Paul Driver ] * Support for virtual location. It's now possible to mount a Dancer app under a user-defined prefix. [ Franck Cuny ] * Test scripts cleanup: + Cleanup is performed in test scripts when necessary (all temp files are removed at the end of the script). + FIX for issue #23 Test scripts that try to write logfiles set the appdir. Dancer 1.140 * Dancer now depends on HTTP::Server::Simple::PSGI in order to rely on a PSGI environement even when running the app with the standalone server (Thanks to Tatsuiko Miyagawa). * Dancer::Request object enhancements: + Dancer::Request now provide an accesor to the raw body of the request. + FIX for issue #13 The params helper now provides accessors to route params, query string params and body params so the user can chose from which source they want to access params instead of dealing with a mixed structure. + Added accessors to referer and remote_address * The Standalone server now uses the setting 'server' to bind itself to the IP address given by the setting. Default value is 0.0.0.0 Dancer 1.130 * Fix a memory leak that could occur between two requests under mod_perl (Thanks to Nicolas Rennert for the report and diagnosis). * remove all optional modules from the core, they are now shipped as separate CPAN distributions: - Dancer::Template::MicroTemplate - Dancer::Session::Cookie - Dancer::Session::Memcached - Dancer::Logger::LogHandler - Dancer::Logger::Syslog * support for the `header' keyword in Dancer's syntax. The user is now able to alter response-headers in route handlers. * support for `prefix' keyword in Dancer's syntax. A prefix can be set by the user before defining routes handlers. All route defined then will be automatically prefixed accordingly. Dancer 1.122 * Fix the test suite under Perl 5.8.x * Security Fix: protection from CRLF injection in response headers (thanks to Mark Stosberg for the report). * Support for multi-valued params in GET/POST data (thanks to Mark Stosberg for the report). * Backward compatibility with old app.psgi files, don't die when a request is initialized with a CGI::PSGI object. Dancer 1.121 * Fix for POST data parsing (was broken in 1.120) now Dancer depends on HTTP::Body for that. Dancer 1.120 * ROADMAP updated * Dancer is now compliant with Plack::Server::Apache2 * Remove the CGI.pm dependency, huge refactoring * POD typo fixes (Naveed) * Support for syntax-only importation (Sawyer X) * Remove the example/ directory, useless and deprecated * New logger engine: Log::Handler (franck cuny) * New template engine Text::Microtemplate (franck cuny) * Remove compilation-time warnings catching (issue #14) Dancer 1.110 * Fix test script `t/11_logger/04_syslog.t' * Fix test script `t/10_template/05_template_toolkit.t' Dancer 1.100 * Support for multiple method routes at once with 'any' * Templates engines + Bug fixes in Dancer::Template::Simple (Jury Gorky) + Refactoring of the factory + option for disabling the layout in the template helper. * New session engine based on encrypted cookies (Alex Kapranof) * More HTTP codes supported for a better REST compat (Nate Jones) * Documentation updates * script/dancer now requires an appname * New Makefile.PL with better metadata (CPAN Service) Dancer 1.000 * Support for Syslog logger (Dancer::Logger::Syslog) * Basic template engine so Template is no more a hard deps. * Memcache Session support (Dancer::Session::Memcache) * YAML file-based session support (Dancer::Session::YAML) * Lots of tests (more than 80% of the code is covered) Dancer 0.9906 * move from File::MimeInfo to File::MimeInfo::Simple for smooth run on Mac OSX and Win32 systems. Dancer 0.9005 * Source code extract on error catching * Support for configurable error handling * New design for the starting app built with script/dancer Dancer 0.9004 * Support for PSGI/Plack environment * script/dancer helper script for bootstraping a new app Dancer 0.9003 * Detect differently compilation-time warnings and runtime warnings closes bug #48440 (Thanks to Enric Joffrion for the report, and to Vincent Pit for the diagnosis) libdancer-perl-1.3120+dfsg.orig/t/0000755000175000017500000000000012256332256016104 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/19_dancer/0000755000175000017500000000000012256332256017651 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/19_dancer/02_script_version_from.t0000644000175000017500000000263212233013710024420 0ustar gregoagregoause strict; use warnings; use Cwd; use Dancer::FileUtils; use Dancer::ModuleLoader; use Test::More import => ['!pass']; use File::Spec; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 6; my %cases = ( 'A' => [ 'A', 'lib/A.pm' ], 'A::B' => [ 'A-B', 'lib/A/B.pm' ], ); my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $cwd = cwd; chdir $dir; my $libdir = File::Spec->catdir($cwd, 'blib', 'lib'); $libdir = '"'.$libdir.'"' if $libdir =~ / /; my $dancer = File::Spec->catdir($cwd, 'script', 'dancer'); $dancer = '"'.$dancer.'"' if $dancer =~ / /; my $cmd = "$^X -I $libdir $dancer"; foreach my $case ( keys %cases ) { my ( $casedir, $casefile ) = @{ $cases{$case} }; # create the app qx{$cmd -x -a $case}; # check for directory my $exists = -d $casedir; ok( $exists, "Created directory for $case" ); if ($exists ) { chdir $casedir; $exists = -e $casefile && -f _; ok( $exists, "Created file for $case" ); if ( $exists ) { my $makefile = 'Makefile.PL'; my $content = Dancer::FileUtils::read_file_content($makefile); like( $content, qr/VERSION_FROM \s+ => \s+ '\Q$casefile\E', /x, 'Created correct VERSION_FROM', ); } chdir $dir; } } chdir $cwd; libdancer-perl-1.3120+dfsg.orig/t/19_dancer/01_script.t0000644000175000017500000000245112233013710021626 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; my @cases = ( 'A', 'A::B', 'A::B::C', 'A::B::C::D', ); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 3 + @cases; use Cwd qw(cwd); use Dancer; use Dancer::FileUtils; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $cwd = cwd; chdir $dir; END { chdir $cwd; } my $libdir = File::Spec->catdir($cwd,'blib','lib'); $libdir = '"'.$libdir.'"' if $libdir =~ / /; # this is for windows, but works in UNIX systems as well... my $dancer = File::Spec->catfile( $cwd, 'script', 'dancer' ); $dancer = '"'.$dancer.'"' if $dancer =~ / /; #same here. # the same can happen with perl itself, but while nobody complain, keep it quiet. my $cmd = "$^X -I $libdir $dancer"; chomp( my $version = qx{$cmd -v} ); is($version, "Dancer $Dancer::VERSION", "dancer -v"); my $nothing = qx{$cmd}; like($nothing, qr{Usage: .* dancer .* options}sx, 'dancer (without parameters)'); my $help = qx{$cmd}; like($help, qr{Usage: .* dancer .* options}sx, 'dancer (without parameters)'); foreach my $case (@cases) { my $create_here = qx{$cmd -x -a $case 2> err}; is scalar(Dancer::FileUtils::read_file_content('err')) => '', "create $case did not return error"; } libdancer-perl-1.3120+dfsg.orig/t/01_config/0000755000175000017500000000000012256332256017651 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/01_config/yaml_dependency.t0000644000175000017500000000135412233013707023171 0ustar gregoagregoause Test::More tests => 2; use strict; use warnings; use Dancer::Config; use Dancer::ModuleLoader; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; mock 'Dancer::Config' => method 'conffile' => should sub { __FILE__ }; mock 'Dancer::ModuleLoader' => method 'load' => should sub { 0, "Fish error. Goldfish in YAML." }; eval { Dancer::Config->load }; like $@, qr/Configuration file found but could not load YAML: Fish error. Goldfish in YAML./, "Dancer::Config cannot load without YAML"; mock 'YAML' => method 'LoadFile' => should sub { undef }; eval { Dancer::Config::load_settings_from_yaml('foo.yml') }; like $@, qr/Unable to parse the configuration file: foo.yml/, "YAML error caught"; libdancer-perl-1.3120+dfsg.orig/t/01_config/06_stack_trace.t0000644000175000017500000000526312233013707022624 0ustar gregoagregoause strict; use warnings; use Test::More tests => 18, import => ['!pass']; use Dancer ':syntax'; use Dancer::Template::TemplateToolkit; # scoping for $Carp::Verbose localization { # first of all, test without verbose Exceptions local $Dancer::Exception::Verbose = 0; eval { Dancer::Template::TemplateToolkit->render('/not/a/valid/file'); }; my @error_lines = split(/\n/, $@); is(scalar(@error_lines), 1, "test non verbose croak"); like($error_lines[0], qr!^core - template - '/not/a/valid/file' doesn\'t exist or not a regular file at!, "test non verbose croak"); } { # same with verbose Exceptions local $Dancer::Exception::Verbose = 1; eval { Dancer::Template::TemplateToolkit->render('/not/a/valid/file'); }; my @error_lines = split(/\n/, $@); is(scalar(@error_lines), 3, "test verbose croak"); like($error_lines[0], qr!^core - template - '/not/a/valid/file' doesn\'t exist or not a regular file at!, "test verbose croak"); like($error_lines[1], qr!^\s*Dancer::Template::TemplateToolkit::render\(['"]Dancer::Template::TemplateToolkit['"], ['"]/not/a/valid/file['"]\) called at!, "test verbose croak stack trace"); like($error_lines[2], qr!^\s*eval \{...\} called at (?:[.]/)?t/01_config/06_stack_trace.t!, "test verbose croak stack trace"); } { # test that default Dancer traces setting is no verbose is(setting('traces'), 0, "default 'traces' option set to 0"); is($Carp::Verbose, 0, "default Carp verbose is 0"); is($Dancer::Exception::Verbose, 0, "default Dancer Exception verbose is 0"); eval { Dancer::Template::TemplateToolkit->render('/not/a/valid/file'); }; my @error_lines = split(/\n/, $@); is(scalar(@error_lines), 1, "test non verbose croak 2"); like($error_lines[0], qr!^core - template - '/not/a/valid/file' doesn\'t exist or not a regular file at!, "test non verbose croak 2"); } { # test setting traces to 1 ok(setting(traces => 1), 'can set traces'); is($Carp::Verbose, 0, "new Carp verbose is 1"); is($Dancer::Exception::Verbose, 1, "default Dancer Exception verbose is 1"); eval { Dancer::Template::TemplateToolkit->render('/not/a/valid/file'); }; my @error_lines = split(/\n/, $@); is(scalar(@error_lines), 3, "test verbose croak"); like($error_lines[0], qr!^core - template - '/not/a/valid/file' doesn\'t exist or not a regular file at!, "test verbose croak"); like($error_lines[1], qr!^\s*Dancer::Template::TemplateToolkit::render\(['"]Dancer::Template::TemplateToolkit['"], ['"]/not/a/valid/file['"]\) called at!, "test verbose croak stack trace"); like($error_lines[2], qr!^\s*eval \{...\} called at (?:[.]/)?t/01_config/06_stack_trace.t!, "test verbose croak stack trace"); } libdancer-perl-1.3120+dfsg.orig/t/01_config/01_settings.t0000644000175000017500000000213012233013020022146 0ustar gregoagregoause strict; use warnings; use Test::More tests => 11, import => ['!pass']; use Dancer ':syntax'; # testing default values is(setting('port'), '3000', "default value for 'port' is OK"); is(setting('content_type'), 'text/html', "default value for 'content_type' is OK"); # testing new settings ok(setting(foo => '42'), 'setting a new value'); is(setting('foo'), 42, 'new value has been set'); # test the alias 'set' ok(set(bar => 43), "setting bar with set"); # testing private interface is( Dancer::Config::_set_setting( bar => 42 ), 42, 'setting bar with private interface' ); is( Dancer::Config::_get_setting('bar'), 42, 'getting bar with private interface' ); SKIP: { skip "YAML and JSON are needed to run this test", 4 unless ( Dancer::ModuleLoader->load('YAML') && Dancer::ModuleLoader->load('JSON') ); ok my $serializer = Dancer::Config::_trigger_hooks( 'serializer', 'YAML' ); isa_ok( $serializer, 'Dancer::Serializer::YAML' ); ok $serializer = Dancer::Config::_trigger_hooks( 'serializer', 'JSON' ); isa_ok( $serializer, 'Dancer::Serializer::JSON' ); } libdancer-perl-1.3120+dfsg.orig/t/01_config/environments/0000755000175000017500000000000012256332256022400 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/01_config/environments/development.pl0000644000175000017500000000000311506417160025243 0ustar gregoagregoa1; libdancer-perl-1.3120+dfsg.orig/t/01_config/08_environments.t0000644000175000017500000000264212233013707023070 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::ModuleLoader; Dancer::ModuleLoader->load('YAML') or plan skip_all => 'YAML is needed to run this test'; plan tests => 7; use File::Spec; use Dancer ':syntax'; use lib File::Spec->catdir('t', 'lib'); use TestUtils; my $app_dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $env_dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $app_dir; set envdir => $env_dir; my $conffile = Dancer::Config->conffile; my $conf = ' port: 4500 startup_info: 0 charset: "UTF8" logger: file log: "debug" '; write_file($conffile => $conf); ok(Dancer::Config->load, 'Config load works without conffile'); is(setting('log'), 'debug', 'log setting looks good'); my $prod_env = ' log: "warning" startup_info: 0 foo_prod: 42 '; setting('environment' => 'prod'); write_file(Dancer::Config->environment_file, $prod_env); my $path = File::Spec->catfile($env_dir, 'prod.yml'); ok -f $path; ok(Dancer::Config->load, 'load prod environment'); is(setting('log'), 'warning', 'log setting looks good'); # see what happens when envfile is required but not present setting('require_environment' => 1); setting('environment' => 'missing'); # expect it to fail with a confess() eval { Dancer::Config->load }; ok($@, 'dies if environment required but missing'); like($@, qr/missing\.yml/, '... error message includes environment file name'); File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/01_config/04_config_file.t0000644000175000017500000000423312233013707022577 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan skip_all => "YAML needed to run this tests" unless Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 17; use Dancer ':syntax'; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestUtils; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir; my $envdir = File::Spec->catdir($dir, 'environments'); mkdir $envdir; my $conffile = Dancer::Config->conffile; ok(defined($conffile), 'default conffile is defined'); ok(Dancer::Config->load, 'Config load works without conffile'); # create the conffile my $conf = ' port: 4500 startup_info: 0 charset: "UTF8" logger: file '; write_file($conffile => $conf); ok(Dancer::Config->load, 'Config load works with a conffile'); is(setting('environment'), 'development', 'setting environment looks good'); is(setting('port'), '4500', 'setting port looks good'); is(setting('startup_info'), 0, 'setting startup_info looks good'); is(setting('logger'), 'file', 'setting logger looks good'); # issue GH#153 is(setting('charset'), 'utf8', "charset setting is normalized"); ok(defined(Dancer::Logger->logger), 'logger is defined'); my $test_env = ' log: debug startup_info: 1 foo_test: 54 '; write_file(Dancer::Config->environment_file, $test_env); ok(Dancer::Config->load, 'load test environment'); is(setting('log'), 'debug', 'log setting looks good'); is(setting('startup_info'), '1', 'startup_info setting looks good'); is(setting('foo_test'), '54', 'random setting set'); unlink Dancer::Config->environment_file; my $prod_env = ' log: "warning" startup_info: 0 foo_prod: 42 '; setting('environment' => 'prod'); write_file(Dancer::Config->environment_file, $prod_env); ok(Dancer::Config->load, 'load prod environment'); is(setting('log'), 'warning', 'log setting looks good'); is(setting('foo_prod'), '42', 'random setting set'); is(setting('startup_info'), '0', 'startup_info setting looks good'); Dancer::Logger::logger->{fh}->close; unlink Dancer::Config->environment_file; unlink $conffile; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/01_config/06_config_api.t0000644000175000017500000000136612233013707022437 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Config; plan skip_all => "YAML needed to run this tests" unless Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 2; eval { Dancer::Config::load_settings_from_yaml('foo'); }; like $@, qr/Unable to parse the configuration file/; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $config_file = File::Spec->catfile($dir, 'settings.yml'); open my $fh, '>', $config_file; print $fh '---foo\n'; close $fh; eval { Dancer::Config::load_settings_from_yaml($config_file); }; like $@, qr/Unable to parse the configuration file/; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/01_config/02_mime_type.t0000644000175000017500000000174012233013020022305 0ustar gregoagregoause strict; use warnings; use Test::More tests => 10, import => ['!pass']; use Dancer ':syntax'; BEGIN { use_ok 'Dancer::MIME'; } my $mime = Dancer::MIME->instance(); is($mime->for_name('svg'), 'image/svg+xml', 'mime type svg is known'); is_deeply($mime->custom_types, {}, 'user defined mime_types are empty'); $mime->add_type(foo => 'text/foo'); is_deeply($mime->custom_types, {foo => 'text/foo'}, 'text/foo is saved'); is($mime->for_name('foo'), 'text/foo', 'mime type foo is found'); $mime->add_alias(bar => 'foo'); is($mime->for_name('bar'), 'text/foo', 'mime type bar is found'); is($mime->for_file('foo.bar'), 'text/foo', 'mime type for extension .bar is found'); is($mime->add_alias(xpto => 'BAR'), 'text/foo', 'mime gets correctly lowercased for user types'); is($mime->add_alias(xpto => 'SVG'), 'image/svg+xml', 'mime gets correctly lowercased for system types'); is($mime->add_alias(zbr => 'baz'), $mime->default, 'alias of unkown mime type gets default mime type'); libdancer-perl-1.3120+dfsg.orig/t/01_config/05_serializers.t0000644000175000017500000000223512233013020022654 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; plan tests => 9; my $struct = {eris => 23}; SKIP: { skip 'YAML is needed to run this test', 3 unless Dancer::ModuleLoader->load('YAML'); ok my $test = to_yaml($struct), 'to yaml'; ok my $final_struct = from_yaml($test), 'from yaml'; is_deeply $final_struct, $struct, 'from => to works'; } SKIP: { skip 'JSON is needed to run this test', 3 unless Dancer::ModuleLoader->load('JSON'); ok my $test = to_json($struct), 'to json'; ok my $final_struct = from_json($test), 'from json'; is_deeply $final_struct, $struct, 'from => to works'; } SKIP: { skip 'XML::Simple is needed to run this test', 3 unless Dancer::ModuleLoader->load('XML::Simple'); skip 'XML::Parser or XML::SAX are needed to run this test', 3 unless Dancer::ModuleLoader->load('XML::Parser') or Dancer::ModuleLoader->load('XML::SAX'); ok my $test = to_xml($struct), 'to xml'; ok my $final_struct = from_xml($test), 'from xml'; is_deeply $final_struct, $struct, 'from => to works'; } libdancer-perl-1.3120+dfsg.orig/t/01_config/03_logger.t0000644000175000017500000000321612233013707021611 0ustar gregoagregoause Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::FileUtils; use File::Spec qw/catfile/; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 15; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir; eval { set logger => 'foobar' }; like($@, qr/unable to load logger/, 'invalid logger detected'); ok(set(logger => 'file'), 'file-based logger correctly set'); my $message = 'this is a test log message'; ok(debug($message), "debug sent"); ok(warning($message), "warning sent"); ok(error($message), "error sent"); my $logdir = Dancer::FileUtils::path(setting('appdir'), 'logs'); ok((-d $logdir), "log directory exists"); my $dev_logfile = Dancer::FileUtils::path($logdir, "development.log"); ok((-r $dev_logfile), "logfile exists"); open LOGFILE, '<', $dev_logfile; my @content = ; close LOGFILE; ok(grep(/debug \@.*$message/, @content), 'debug message found'); ok(grep(/warn \@.*$message/, @content), 'warning message found'); ok(grep(/error \@.*$message/, @content), 'error message found'); set environment => 'test'; set logger => 'file'; my $test_logfile = Dancer::FileUtils::path($logdir, "test.log"); ok((-r $test_logfile), "environment logfile exists"); open LOGFILE, '<', $test_logfile; @content = ; close LOGFILE; ok(set(log => 'warning'), 'log level set to warning'); ok(!debug($message), 'debug message is dropped'); ok(warning($message), 'warning message is logged'); ok(error($message), 'error message is logged'); Dancer::Logger::logger->{fh}->close; unlink $dev_logfile; unlink $test_logfile; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/01_config/07_strict_config.t0000644000175000017500000000403512233013707023173 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan skip_all => "YAML needed to run this tests" unless Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 12; use Dancer ':syntax'; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestUtils; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir; my $envdir = File::Spec->catdir($dir, 'environments'); mkdir $envdir; my $conffile = Dancer::Config->conffile; # create the conffile my $conf = <<"END"; port: 4500 startup_info: 0 99_bottles: "can't touch this" 99_more_bottles: this_method: "can be called" alist: - first_element: foo: bar - second_element: baz: quux this: rocks charset: "UTF8" logger: file auth: username: ovid password: hahahah strict_config: 1 END write_file($conffile => $conf); ok(Dancer::Config->load, 'Config load works with a conffile'); ok(Dancer::Config->load, '... and it should be safe to call more than once'); can_ok config, 'port'; is config->port, '4500', 'basic methods should work with strict configs'; is config->auth->username, 'ovid', '... and as should chained methods'; is config->{port}, '4500', '... but we should still be able to reach into the config'; ok !config->can('99_bottles'), 'We do not try to build invalid method names'; is config->{'99_bottles'}, "can't touch this", "... but we do not discard them, either"; is config->{'99_more_bottles'}->this_method, 'can be called', "... but they can still chain methods"; is config->alist->[1]->baz, 'quux', '... and we still can call list methods'; eval { config->auth->pass }; my $error = $@; like $error, qr/Can't locate config attribute "pass"/, 'Calling non-existent config methods should die'; like $error, qr/Available attributes: password, username/, '... and tell us which attributes are available'; Dancer::Logger::logger->{fh}->close; unlink Dancer::Config->environment_file; unlink $conffile; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/17_apps/0000755000175000017500000000000012256332256017356 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/17_apps/00_base.t0000644000175000017500000000140712233013020020732 0ustar gregoagregoause Test::More tests => 9, import => ['!pass']; use strict; use warnings; use Dancer::App; my $app = Dancer::App->new; isa_ok $app, 'Dancer::App'; is $app->name, 'main', "default app is 'main'"; eval { my $other = Dancer::App->new }; like $@, qr/an app named 'main' already exists/, "cannot create twice the same app"; my $other = Dancer::App->new(name => 'Foo::Bar'); is $other->name, 'Foo::Bar', "Foo::Bar app created"; isa_ok(Dancer::App->current(), 'Dancer::App'); is(Dancer::App->current->name, 'main', "current is main"); ok(Dancer::App->current(Dancer::App->new(name => "Other")), "set current to 'Other'"); is(Dancer::App->current->name, 'Other', "current is 'Other'"); $app->prefix('foo'); is $app->prefix, 'foo', 'prefix is set'; libdancer-perl-1.3120+dfsg.orig/t/17_apps/05_api.t0000644000175000017500000000063212233013020020575 0ustar gregoagregoause strict; use warnings; use Test::More; use Dancer::App; plan tests => 7; ok my $app = Dancer::App->new(); ok $app->app_exists('main'); ok !$app->app_exists('foo'); ok my $current_app = $app->get('main'); isa_ok $current_app, 'Dancer::App'; my @routes = $app->routes('get'); is scalar @routes, 0; $app->registry->universal_add('get', '/', sub{1}); @routes = $app->routes('get'); is scalar @routes, 1; libdancer-perl-1.3120+dfsg.orig/t/17_apps/03_prefix.t0000644000175000017500000000175312233013710021332 0ustar gregoagregoause Test::More tests => 12, import => ['!pass']; use strict; use warnings; use Dancer; use Dancer::Test; is prefix, '', 'prefix returns empty string initially'; prefix '/foo'; is prefix, '/foo', 'prefix returns the currently set prefix'; get '/' => sub { '/foo and /foo/' }; get '/bar' => sub { "/foo/bar" }; prefix undef; is prefix, '', 'prefix returns empty string after prefix is unset'; get '/baz' => sub { "/baz" }; prefix '/foobar'; get '/' => sub { "/foobar/",; }; response_content_is [ GET => "/foo/bar" ], "/foo/bar"; response_content_is [ GET => "/foo/" ], "/foo and /foo/"; response_content_is [ GET => "/foo" ], "/foo and /foo/"; response_status_is [ GET => '/foo/baz' ], 404; response_content_is [ GET => "/baz" ], "/baz"; response_content_is [ GET => "/foobar" ], "/foobar/"; response_content_is [ GET => "/foobar/" ], "/foobar/"; response_status_is [ GET => '/foobar/foobar/' ], 404; response_status_is [ GET => '/foobar/foobar/foobar/' ], 404; libdancer-perl-1.3120+dfsg.orig/t/17_apps/01_settings.t0000644000175000017500000000232212233013020021656 0ustar gregoagregoause Test::More tests => 6; use strict; use warnings; use Dancer::App; use Dancer::Test; my $app = Dancer::App->new; is_deeply $app->settings, {}, "settings is an empty hashref"; is $app->setting('foo'), undef, "setting 'foo' is undefined"; ok $app->setting('foo' => 42), "set the 'foo' setting to 42"; is $app->setting('foo'), 42, "setting 'foo' is 42"; # a setting could be overwritten by a Dancer::App instance { package Webapp; use Dancer; setting onlyroot => 42; setting foo => "root"; get '/root_action' => sub { return { onlyroot => setting('onlyroot'), foo => setting('foo'), onlyapp => setting('onlyapp') }; }; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); load_app 'TestApp', settings => { foo => 'testapp', onlyapp => '43', }; } response_content_is_deeply [ GET => '/root_action' ], { onlyroot => 42, foo => 'root', onlyapp => undef, }; response_content_is_deeply [ GET => '/test_app_setting' ], { onlyroot => 42, foo => 'testapp', onlyapp => 43, }; libdancer-perl-1.3120+dfsg.orig/t/17_apps/000_create_fake_env.t0000644000175000017500000000052412233013020023200 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/17_apps/02_load_app.t0000644000175000017500000000227412233013710021612 0ustar gregoagregoause Test::More tests => 12, import => ['!pass']; use strict; use warnings; use Dancer::Test; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); { use Dancer; load_app 'TestApp'; load_app 'Forum', prefix => '/forum'; get '/' => sub { "home" }; } my $apps = [ Dancer::App->applications ]; is scalar(@$apps), 3, "3 applications exist"; my $main = Dancer::App->get('main'); my $test_app = Dancer::App->get('TestApp'); my $forum = Dancer::App->get('Forum'); ok defined($main), "app 'main' is defined"; ok defined($test_app), "app 'TestApp' is defined"; ok defined($forum), "app 'Forum' is defined"; is @{ $main->registry->routes->{'get'} }, 1, "one route is defined in main app"; is @{ $test_app->registry->routes->{'get'} }, 15, "15 routes are defined in test app"; is @{ $forum->registry->routes->{'get'} }, 5, "5 routes are defined in forum app"; response_content_is [GET => "/forum/index"], "forum index"; response_content_is [GET => "/forum/admin/index"], "admin index"; response_content_is [GET => "/forum/users/list"], "users list"; response_content_is [GET => "/forum/users/mods/list"], "mods list"; response_content_is [GET => "/forum/"], "root"; libdancer-perl-1.3120+dfsg.orig/t/12_response/0000755000175000017500000000000012256332256020244 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/12_response/05_api.t0000644000175000017500000000123412233013020021462 0ustar gregoagregoause strict; use warnings; use Test::More; use Dancer::Response; plan tests => 10; ok my $response = Dancer::Response->new(); is $response->status, 200; isa_ok $response->{headers}, 'HTTP::Headers'; $response->header('Content-Type' => 'text/html'); is $response->header('Content-Type'), 'text/html'; $response->status(500); is $response->status, 500; $response->content("this is my content"); is $response->content, "this is my content"; ok $response->exists; $response->pass(1); ok $response->has_passed; $response->pass(0); ok !$response->has_passed; my $psgi_headers = $response->headers_to_array(); is_deeply $psgi_headers, ['Content-Type', 'text/html']; libdancer-perl-1.3120+dfsg.orig/t/12_response/06_filter_halt_status.t0000644000175000017500000000170312233013710024621 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass'];; plan skip_all => "JSON is needed to run this tests" unless Dancer::ModuleLoader->load('JSON'); # make sure we keep the status when halt is used { package SomeApp; use Dancer; set serializer => 'JSON'; set environment => 'production'; hook before => sub { if (params->{'troll'}) { status 401; return halt({error => "Go away you troll!"}) } }; get '/' => sub { "root" }; } use Dancer::Test; my @tests = ( ['/', {}, 200, 'root'], ['/', {troll => 1}, 401, '{"error":"Go away you troll!"}'], ); plan tests => scalar(@tests) * 2; for my $t (@tests) { my ($path, $params, $status, $content) = @{ $t }; my $resp = dancer_response(GET => $path, { params => $params }); is $resp->{status}, $status, "status is $status"; is $resp->{content}, $content, "content is $content"; } libdancer-perl-1.3120+dfsg.orig/t/12_response/03_charset.t0000644000175000017500000000500512233013020022340 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer; use Dancer::ModuleLoader; use Encode; plan tests => 16; set environment => 'production'; my $res = Dancer::Response->new(headers => [ 'Content-Type' => 'text/html' ], content_type => 'text/html'); my $psgi_res = Dancer::Handler->render_response($res); is(@$psgi_res, 3); is($psgi_res->[0], 200, 'default status'); is_deeply($psgi_res->[1], [ 'Content-Length', 0, 'Content-Type' => 'text/html' ], 'default headers'); is_deeply($psgi_res->[2], [''], 'default content'); ok $res->content_type('text/plain'); ok $res->content('123'); is_deeply(Dancer::Handler->render_response($res), [ 200, [ 'Content-Length', 0, 'Content-Type', 'text/plain' ], [ '123' ], ], ); setting charset => 'utf-8'; is_deeply(Dancer::Handler->render_response($res), [ 200, [ 'Content-Length', 0, 'Content-Type', 'text/plain; charset=utf-8' ], [ '123' ], ], ); ok $res->content("\x{0429}"); # cyrillic shcha -- way beyond latin1 is_deeply(Dancer::Handler->render_response(Dancer::Serializer->process_response($res)), [ 200, [ 'Content-Length', 0, 'Content-Type', 'text/plain; charset=utf-8' ], [ Encode::encode('utf-8', "\x{0429}") ], ], ); SKIP: { skip "JSON is needed for this test" , 3 unless Dancer::ModuleLoader->load('JSON'); setting serializer => 'JSON'; ok $res->content_type('application/json'); ok $res->content({ key => 'value'}); is_deeply(Dancer::Handler->render_response(Dancer::Serializer->process_response($res)), [ 200, [ 'Content-Length', 0, 'Content-Type', 'application/json; charset=utf-8' ], [ JSON::to_json({ key => 'value' }) ], ], ); } SKIP: { skip "XML::Simple is needed for this test" , 3 unless Dancer::ModuleLoader->load('XML::Simple'); skip "XML::Parser or XML::SAX are needed to run this test", 3 unless Dancer::ModuleLoader->load('XML::Parser') or Dancer::ModuleLoader->load('XML::SAX'); setting serializer => 'XML'; ok $res->content_type('text/xml'); ok $res->content({ key => "\x{0429}" }); is_deeply(Dancer::Handler->render_response(Dancer::Serializer->process_response($res)), [ 200, [ 'Content-Length', 0, 'Content-Type', 'text/xml; charset=utf-8' ], [ Encode::encode('utf-8', XML::Simple::XMLout( { key => "\x{0429}" }, RootName => 'data' )) ], ], ); } libdancer-perl-1.3120+dfsg.orig/t/12_response/09_headers_to_array.t0000644000175000017500000000163712233013710024245 0ustar gregoagregoapackage main; use strict; use warnings; use Test::More tests => 3, import => ['!pass']; { use Dancer; get '/' => sub { push_header A => 1; push_header A => 2; push_header B => 3; }; } use Dancer::Test; response_headers_include [GET => '/'] => [ 'Content-Type' => 'text/html', 'A' => 1, 'A' => 2, 'B' => 3 ]; # Dancer::Test::dancer_response does accept an HTTP::Headers object now (issue 755) use HTTP::Headers; my $res1 = dancer_response(GET => '/', { headers => HTTP::Headers->new('Content-Type' => 'text/ascii', 'XY' => 'Z')}); is($res1->header('Content-Type'), 'text/html', "Content-Type looks good for dancer_response accepting HTTP::Headers"); my $res2 = dancer_response(GET => '/', { headers => ['Content-Type' => 'text/ascii', 'XY' => 'Z']}); is_deeply($res1->headers_to_array, $res2->headers_to_array, "Headers look good for dancer_response accepting HTTP::Headers"); 1; libdancer-perl-1.3120+dfsg.orig/t/12_response/02_headers.t0000644000175000017500000000423412233013710022332 0ustar gregoagregoa# # I really suck ass at tests, pardon my French :) - damog # use Dancer ':tests'; use Test::More; use Dancer::Test; get '/header', sub { header 'X-Foo' => 'xfoo'; }; get '/headers', sub { headers 'X-A' => 'a', 'X-B' => 'b'; }; get '/headers/more', sub { headers 'X-Foo' => 'bar'; header 'X-Bar' => 'schmuk', 'X-XXX' => 'porn'; header 'Content-Type', 'text/css'; # this gets overriden }; get '/headers/content_type', sub { content_type 'text/xml'; headers 'Content-Type' => 'text/css'; }; get '/headers/multiple' => sub { headers 'foo' => 1, 'foo' => 2, 'bar' => 3, 'foo' => 4; }; plan tests => 11; # /header my $res = dancer_response(GET => '/header'); is($res->header('X-Foo'), 'xfoo', "X-Foo looks good for /header"); # /headers $res = dancer_response(GET => '/headers'); is($res->header('X-A'), 'a', "X-A looks good for /headers"); is($res->header('X-B'), 'b', 'X-B looks good for /headers'); # /headers/more $res = dancer_response(GET => '/headers/more'); is($res->header('X-Foo'), 'bar', "X-Foo looks good for /headers/more"); is($res->header('X-Bar'), 'schmuk', "X-Bar looks good for /headers/more"); is($res->header('X-XXX'), 'porn', "X-XXX looks good for /headers/more"); is($res->header('Content-Type'), 'text/css', "Content-Type looks good for /headers/more"); # /headers/content_type $res = dancer_response(GET => '/headers/content_type'); is($res->header('Content-Type'), 'text/css', "Content-Type looks good for /headers/content_type"); # /headers/multiple response_headers_include [ GET => '/headers/multiple'] => [ 'Content-Type' => 'text/html', Bar => 3, Foo => 1, Foo => 2, Foo => 4, ], 'multiple headers are kept'; my $response = dancer_response(GET => '/headers/multiple'); response_headers_include $response => [ 'Content-Type' => 'text/html', Bar => 3, Foo => 1, Foo => 2, Foo => 4, ], '... even if we pass a response object to response_headers_include()'; # Dancer::Response header's API $res = Dancer::Response->new( status => 200, headers => [ 'Content-type', 'application/json' ], content => "ok" ); my $ct = $res->header('CONTENT-TYPE'); is $ct, 'application/json'; libdancer-perl-1.3120+dfsg.orig/t/12_response/07_cookies.t0000644000175000017500000000150512233013020022350 0ustar gregoagregoapackage main; use strict; use warnings; use Test::More tests => 4, import => ['!pass']; { use Dancer; get '/set_one_cookie' => sub { set_cookie "a" => "b"; }; get '/set_two_cookies' => sub { set_cookie "a" => "b", http_only => 0; set_cookie "c" => "d"; }; } use Dancer::Test; { note "Testing one cookie"; my $req = [GET => '/set_one_cookie']; route_exists $req; response_headers_include $req => [ 'Content-Type' => 'text/html', 'Set-Cookie' => 'a=b; path=/; HttpOnly' ]; } { note "Testing two cookies"; my $req = [GET => '/set_two_cookies']; route_exists $req; response_headers_include $req => [ 'Content-Type' => 'text/html', 'Set-Cookie' => 'a=b; path=/', 'Set-Cookie' => 'c=d; path=/; HttpOnly', ]; } 1; libdancer-perl-1.3120+dfsg.orig/t/12_response/000_create_fake_env.t0000644000175000017500000000052412233013020024066 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/12_response/01_CRLF_injection.t0000644000175000017500000000136412233013020023501 0ustar gregoagregoa use Test::More tests => 2; use strict; use warnings; use Dancer::Response; use Dancer::Handler::Standalone; my $r = Dancer::Response->new( headers => [ 'Location' => "http://good.com\nLocation: http://evil.com" ], ); my $res = Dancer::Handler::Standalone->render_response($r); is_deeply( $res->[1], [ 'Location' => "http://good.com\r\n Location: http://evil.com", 'Content-Length' => 0,], "CRLF injections are not allowed... a space is added to make the second line an RFC-compliant continuation line." ); $r = Dancer::Response->new( headers => [ 'Content-Length' => 0, a => "foo\nevil body", ] ); $res = Dancer::Handler::Standalone->render_response($r); is $res->[1]->[3], "foo\r\n evil body"; libdancer-perl-1.3120+dfsg.orig/t/12_response/11_CVE-2012-5572.t0000644000175000017500000000145512233013710022320 0ustar gregoagregoapackage main; use strict; use warnings; use Test::More tests => 2, import => ['!pass']; { use Dancer; get '/CVE-2012-5572-cookie' => sub { cookie "test\r\nX-Evil-Header: " => "evil"; }; } use Dancer::Test; { note "Testing CVE-2012-5572 (CRLF in response headers)"; my $req = [GET => '/CVE-2012-5572-cookie']; route_exists $req; my $response = Dancer::Test::_req_to_response($req); my $CRLF = "\r\n"; my $tb = Test::Builder->new; my %headers = @{$response->headers_to_array}; my $foundCRLF = 0; while (my($name, $value) = each %headers) { index($value, $CRLF) == -1 && index($name, $CRLF) == -1 && next; $foundCRLF = 1; last; } $tb->ok(!$foundCRLF, 'Headers do not contain CRLF (CVE-2012-5572)'); } 1; libdancer-perl-1.3120+dfsg.orig/t/12_response/08_drop_content.t0000644000175000017500000000234512233013710023424 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use LWP::UserAgent; BEGIN { use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); } plan tests => 4; use Dancer ':syntax'; use Dancer::Test; test(); sub test { Test::TCP::test_tcp( client => sub { my $port = shift; my $url = "http://127.0.0.1:$port/"; my $ua = LWP::UserAgent->new; for (qw/204 304/) { my $req = HTTP::Request->new( GET => $url . $_ ); my $res = $ua->request($req); ok !$res->content, 'no content for '.$_; ok !$res->header('Content-Length'), 'no content-length for '.$_; } }, server => sub { my $port = shift; set port => $port, startup_info => 0; get '/204' => sub { status 204; return 'foo' }; get '/304' => sub { status 304; return 'foo' }; Dancer->dance(); }, ); } libdancer-perl-1.3120+dfsg.orig/t/12_response/04_charset_server.t0000644000175000017500000000325012233013710023735 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer::ModuleLoader; use Dancer; use Encode; # Ensure a recent version of HTTP::Headers my $min_hh = 5.827; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); plan skip_all => "HTTP::Headers $min_hh required (use of content_type_charset)" unless Dancer::ModuleLoader->load( 'HTTP::Headers', $min_hh ); plan skip_all => "HTTP::Request::Common is needed for this test" unless Dancer::ModuleLoader->load('HTTP::Request::Common'); use LWP::UserAgent; plan tests => 6; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $req = HTTP::Request::Common::POST("http://127.0.0.1:$port/name", [ name => 'vasya' ]); my $res = $ua->request($req); is $res->content_type, 'text/html'; ok $res->content_type_charset; # we always have charset if the setting is set is $res->content, 'Your name: vasya'; $req = HTTP::Request::Common::GET("http://127.0.0.1:$port/unicode"); $res = $ua->request($req); is $res->content_type, 'text/html'; is $res->content_type_charset, 'UTF-8'; is $res->content, Encode::encode('utf-8', "cyrillic shcha \x{0429}"); }, server => sub { my $port = shift; use lib "t/lib"; use TestApp; Dancer::Config->load; set( charset => 'utf-8', environment => 'production', port => $port, startup_info => 0 ); Dancer->dance(); }, ); libdancer-perl-1.3120+dfsg.orig/t/12_response/10_error_dumper.t0000644000175000017500000000137012233013710023421 0ustar gregoagregoause strict; use warnings; use Test::More; use Dancer::Error; use Dancer::ModuleLoader; plan skip_all => 'Clone is required for this test' unless Dancer::ModuleLoader->load('Clone'); plan tests => 4; my $error_obj = Dancer::Error->new( code => '404', pass => 'secret', ); isa_ok( $error_obj, 'Dancer::Error' ); my $censored = $error_obj->dumper; like( $censored, qr/\QNote: Values of 1 sensitive-looking key hidden\E/, 'Data was censored in the output', ); is( $error_obj->{'pass'}, 'secret', 'Original data was not overwritten', ); my %recursive; $recursive{foo}{bar}{baz} = 1; $recursive{foo}{bar}{oops} = $recursive{foo}; $censored = Dancer::Error::_censor( \%recursive ); pass "recursive censored hash"; 1; libdancer-perl-1.3120+dfsg.orig/t/25_exceptions/0000755000175000017500000000000012256332256020573 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/25_exceptions/views/0000755000175000017500000000000012256332256021730 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/25_exceptions/views/index.tt0000644000175000017500000000002112233013710023363 0ustar gregoagregoafoo => <% foo %> libdancer-perl-1.3120+dfsg.orig/t/25_exceptions/views/layouts/0000755000175000017500000000000012256332256023430 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/25_exceptions/views/layouts/main.tt0000644000175000017500000000004312233013710024704 0ustar gregoagregoastart <% time %> <% content %>stop libdancer-perl-1.3120+dfsg.orig/t/25_exceptions/views/error.tt0000644000175000017500000000010512233013710023410 0ustar gregoagregoaTITLE: <% title %> MESSAGE: <% message %> EXCEPTION: <% exception %> libdancer-perl-1.3120+dfsg.orig/t/25_exceptions/02_exceptions.t0000644000175000017500000000707312233013710023433 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Exception qw(:all); ok(1, "load ok"); # test try/catch/continuation { my $v1 = 0; eval { try { $v1 = 1 }; }; ok(! $@); is($v1, 1); } { my $v1 = 0; eval { try { $v1 = 1 } catch { $v1 = 2; }; }; ok(! $@); is($v1, 1); } { my $v1 = 0; eval { try { $v1 = 1; die "plop"; } catch { $v1 = 2; }; }; ok(! $@); is($v1, 2); } { my $v1 = 0; eval { try { $v1 = 1; die bless {}, 'Dancer::Continuation'; } catch { $v1 = 2; }; }; my $e = $@; ok(defined $e); is($v1, 1); ok($e->isa('Dancer::Continuation')); } { my $v1 = 0; eval { try { $v1 = 1; die bless {}, 'Dancer::Continuation'; } catch { $v1 = 2; } continuation { $v1 = 3; }; }; ok(! $@); is($v1, 3); } { my $v1 = 0; eval { try { $v1 = 1; die bless {}, 'Dancer::Continuation'; } continuation { $v1 = 3; } catch { $v1 = 2; }; }; ok(! $@); is($v1, 3); } { my $v1 = 0; eval { try { $v1 = 1; die bless {}, 'plop'; } continuation { $v1 = 3; } catch { $v1 = 2; }; }; ok(! $@); is($v1, 2); } { my $v1 = 0; eval { try { $v1 = 1; die "plop"; } continuation { $v1 = 3; } catch { $v1 = 2; }; }; ok(! $@); is($v1, 2); } { my $registered = [ registered_exceptions ]; is_deeply($registered, [ qw( Base Core Core::App Core::Config Core::Deprecation Core::Engine Core::Factory Core::Factory::Hook Core::Fileutils Core::Handler Core::Handler::PSGI Core::Hook Core::Plugin Core::Renderer Core::Request Core::Route Core::Serializer Core::Session Core::Template ) ]); } register_exception ('Test', message_pattern => "test - %s", ); register_exception ('InvalidCredentials', message_pattern => "invalid credentials : %s", ); register_exception ('InvalidPassword', composed_from => [qw(Test InvalidCredentials)], message_pattern => "wrong password", ); register_exception ('InvalidLogin', composed_from => [qw(Test InvalidCredentials)], message_pattern => "wrong login (login was %s)", ); register_exception ('HarmlessInvalidLogin', composed_from => [qw(InvalidLogin)], message_pattern => "ignored invalid login", ); { my $registered = [ registered_exceptions ]; is_deeply($registered, [ qw( Base Core Core::App Core::Config Core::Deprecation Core::Engine Core::Factory Core::Factory::Hook Core::Fileutils Core::Handler Core::Handler::PSGI Core::Hook Core::Plugin Core::Renderer Core::Request Core::Route Core::Serializer Core::Session Core::Template HarmlessInvalidLogin InvalidCredentials InvalidLogin InvalidPassword Test ) ]); } { my $v1 = 0; my $e; eval { try { $v1 = 1; raise InvalidLogin => 'douglas' } continuation { $v1 = 3; } catch { $e = shift; $v1 = 2; }; }; ok(! $@); like($e, qr/^wrong login \(login was douglas\)/); # check stringification works in other cases ok($e =~ /^wrong login \(login was douglas\)/); ok($e->does('InvalidLogin')); ok($e->does('Test')); ok($e->does('Base')); is($v1, 2); } { eval { raise HarmlessInvalidLogin => 'plop' }; my $exception = $@; is_deeply([ sort { $a cmp $b } $exception->get_composition], [ qw(Base HarmlessInvalidLogin InvalidCredentials InvalidLogin Test) ]); } done_testing; libdancer-perl-1.3120+dfsg.orig/t/25_exceptions/03_exceptions.t0000644000175000017500000000176112233013710023432 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; BEGIN { use_ok('Dancer::Exception', ':all'); } set views => path( 't', '25_exceptions', 'views' ); { # raise in hook but catch it from route my $flag = 0; my $properly_caught_error = 0; hook before_template_render => sub { $flag++ or raise Generic => 'foo5'; }; get '/raise_in_hook' => sub { try { # should raise template 'index', { foo => 'baz5' }; } catch { $properly_caught_error = 1; # won't raise, flag is > 0 template 'index', { foo => 'baz5' }; } }; route_exists [ GET => '/raise_in_hook' ]; $flag = 0; response_status_is( [ GET => '/raise_in_hook' ], 200 => "route didn't error"); is $properly_caught_error, 1, 'properly caught exception'; $flag = 0; response_content_like( [ GET => '/raise_in_hook' ], qr|foo => baz5| ); } done_testing(); libdancer-perl-1.3120+dfsg.orig/t/25_exceptions/04_exceptions_warn.t0000644000175000017500000000240212233013710024453 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Logger::File; use Dancer ':syntax'; use Dancer::Test; use Dancer::Exception ':all'; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $logfile= "$dir/logs/test.log"; set warnings => 1; # we want to test fatal warnings set log => 'fatal'; set logger => 'null'; # we'll monkeypatch later set views => path( 't', '25_exceptions', 'views' ); use vars qw(@log_messages); { no warnings 'redefine'; local *Dancer::Logger::Null::_log = sub { shift; push @log_messages, $_[1] }; # raise a (now fatal) warning in the route handler get '/raise_in_hook' => sub { warn "Boom"; template 'index', { foo => 'baz5' }; }; route_exists [ GET => '/raise_in_hook' ]; response_status_is( [ GET => '/raise_in_hook' ], 500 => "Internal error due to warning"); response_content_like( [ GET => '/raise_in_hook' ], qr|Error 500| ); # Now, check that we find the error in the log my @error= grep {m!request to GET /raise_in_hook crashed!} @log_messages; is 0+@error, 2, "We logged the fatal warning to the logger (two calls)"; } done_testing(); libdancer-perl-1.3120+dfsg.orig/t/25_exceptions/01_exceptions.t0000644000175000017500000000735012233013710023430 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; BEGIN { use_ok('Dancer::Exception', ':all'); } set views => path( 't', '25_exceptions', 'views' ); { # halt in route my $v = 0; get '/halt_in_route' => sub { halt ({ error => 'plop' }); $v = 1; }; response_content_like( [ GET => '/halt_in_route' ], qr|Unable to process your query| ); response_status_is( [ GET => '/halt_in_route' ], 500 => "We get a 500 status" ); is ($v, 0, 'halt broke the workflow as intended'); } { # halt in hook my $flag = 0; my $v = 0; hook before_template_render => sub { if ( 0 || ! $flag++ ) { status 500; halt ({ error => 'plop2' }); $v = 1; } }; get '/halt_in_hook' => sub { template 'index'; }; response_content_like( [ GET => '/halt_in_hook' ], qr|Unable to process your query| ); is ($v, 0, 'halt broke the workflow as intended'); $flag = 0; response_status_is( [ GET => '/halt_in_hook' ], 500 => "We get a 500 status" ); } set error_template => "error.tt"; { # die in route get '/die_in_route' => sub { die "die in route"; }; response_content_like( [ GET => '/die_in_route' ], qr|MESSAGE:

runtime error

die in route| );
    response_content_like( [ GET => '/die_in_route' ], qr|EXCEPTION: die in route| );
    response_status_is( [ GET => '/die_in_route' ], 500 => "We get a 500 status" );
}

register_exception ('Test',
                    message_pattern => "test - %s",
                   );

{
    my $route_hook_executed = 0;
    my $handler_hook_executed = 0;

    # raise in route
    get '/raise_in_route' => sub {
        raise Test => 'plop';
    };

    hook on_route_exception => sub {
        my ($exception) = @_;
        $exception->isa('Dancer::Exception::Test');
        $route_hook_executed++;
    };

    hook on_handler_exception => sub {
        my ($exception) = @_;
        $exception->isa('Dancer::Exception::Test');
        $handler_hook_executed++;
    };

    response_content_like( [ GET => '/raise_in_route' ], qr|MESSAGE: 

runtime error

| ); my $e = "test - plop"; response_content_like( [ GET => '/raise_in_route' ], qr|EXCEPTION: $e| ); response_status_is( [ GET => '/raise_in_route' ], 500 => "We get a 500 status" ); is($route_hook_executed, 3,"exception route hook has been called"); is($handler_hook_executed, 3,"exception handler hook has been called"); } { # die in hook my $flag = 0; hook after_template_render => sub { $flag++ or die "die in hook"; }; get '/die_in_hook' => sub { template 'index', { foo => 'baz' }; }; $flag = 0; response_content_like( [ GET => '/die_in_hook' ], qr|MESSAGE:

runtime error

| ); $flag = 0; response_content_like( [ GET => '/die_in_hook' ], qr|EXCEPTION: die in hook| ); $flag = 0; response_status_is( [ GET => '/die_in_hook' ], 500 => "We get a 500 status" ); } register_exception ('Generic', message_pattern => "test message : %s", ); { # raise in hook my $flag = 0; hook before_template_render => sub { $flag++ or raise Generic => 'foo'; }; get '/raise_in_hook' => sub { template 'index', { foo => 'baz' }; }; route_exists [ GET => '/raise_in_hook' ]; $flag = 0; response_content_like( [ GET => '/raise_in_hook' ], qr|MESSAGE:

runtime error

| ); $flag = 0; response_content_like( [ GET => '/raise_in_hook' ], qr|EXCEPTION: test message : foo| ); $flag = 0; response_status_is( [ GET => '/raise_in_hook' ], 500 => "We get a 500 status" ); } done_testing(); libdancer-perl-1.3120+dfsg.orig/t/06_helpers/0000755000175000017500000000000012256332256020053 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/06_helpers/05_send_error.t0000644000175000017500000000063112233013707022676 0ustar gregoagregoause Test::More tests => 2, import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; set show_errors => 1; get '/error' => sub { send_error "FAIL"; # The next line is not executed, as 'send_error' breaks the route workflow die; }; response_status_is [GET => '/error'] => 500, "status is 500 on send_error"; response_content_like [GET => '/error'] => qr/FAIL/, "content of error is kept"; libdancer-perl-1.3120+dfsg.orig/t/06_helpers/public/0000755000175000017500000000000012256332256021331 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/06_helpers/public/file.txt0000644000175000017500000000000611506417160023000 0ustar gregoagregoa1 2 3 libdancer-perl-1.3120+dfsg.orig/t/06_helpers/routes.pl0000644000175000017500000000004511506417160021723 0ustar gregoagregoaget '/foo' => sub { 'foo loaded' }; libdancer-perl-1.3120+dfsg.orig/t/06_helpers/000_create_fake_env.t0000644000175000017500000000052412233013020023675 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/06_helpers/02_http_status.t0000644000175000017500000000216712233013707023121 0ustar gregoagregoause Test::More import => ['!pass']; use Dancer::HTTP; my @tests = ( {status => 'ok', expected => 200 }, {status => '200', expected => 200 }, {status => 'created', expected => 201 }, {status => '201', expected => 201 }, {status => 'accepted', expected => 202 }, {status => '202', expected => 202 }, {status => 'no_content', expected => 204 }, {status => '204', expected => 204 }, {status => 'reset_content', expected => 205 }, {status => '205', expected => 205 }, {status => '302', expected => 302 }, {status => 'bad_request', expected => 400 }, {status => '400', expected => 400 }, {status => 'forbidden', expected => 403 }, {status => 'not_found', expected => 404 }, {status => 'Not Found', expected => 404 }, {status => '404', expected => 404 }, {status => 'internal_server_error', expected => 500 }, # additional aliases {status => 'error', expected => 500 }, ); plan tests => scalar(@tests); foreach my $test (@tests) { is(Dancer::HTTP->status($test->{status}), $test->{expected}, "status header looks good for ".$test->{status}); } libdancer-perl-1.3120+dfsg.orig/t/06_helpers/01_send_file.t0000644000175000017500000001122012233015466022460 0ustar gregoagregoause Test::More import => ['!pass']; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestUtils; use Dancer ':syntax'; use Dancer::FileUtils 'read_glob_content'; use Dancer::Test; use File::Temp; use MIME::Types; set public => path(dirname(__FILE__), 'public'); plan tests => 25; get '/cat/:file' => sub { send_file(params->{file}); # The next line is not executed, as 'send_error' breaks the route workflow die; }; get '/catheader/:file' => sub { header 'FooHeader' => 42; send_file(params->{file}, filename => 'header.foo'); }; get '/scalar/file' => sub { my $data = 'FOObar'; send_file( \$data, content_type => 'text/plain', filename => 'foo.bar'); }; get '/as_png/:file' => sub { send_file(params->{file}, content_type => 'png'); }; get '/absolute/:file' => sub { send_file(path(dirname(__FILE__), "routes.pl"), system_path => 1); }; get '/absolute/content_type/:file' => sub { send_file(path(dirname(__FILE__), "routes.pl"), system_path => 1, content_type => 'text/plain'); }; get '/custom_status' => sub { status 'not_found'; send_file('file.txt'); }; get '/ioscalar' => sub { send_file(IO::Scalar->new(\ "IO::Scalar content"), filename => 'ioscalar'); }; my ($temp_fh, $temp_filename) = File::Temp::tempfile('dancer-tests-XXXX', TMPDIR => 1, UNLINK => 1); $temp_fh->print("hello world\n"); $temp_fh->close; get '/404_with_filename' => sub { send_file($temp_filename, filename => 'foo.bar'); }; my $resp = dancer_response(GET => '/cat/file.txt'); ok(defined($resp), "route handler found for /cat/file.txt"); my %headers = @{$resp->headers_to_array}; is($headers{'Content-Type'}, 'text/plain', 'mime_type is kept'); is(ref($resp->{content}), 'GLOB', "content is a File handle"); my $content = read_glob_content($resp->{content}); $content =~ s/\r//g; is_deeply( [split(/\n/, $content)], [1,2,3], 'send_file worked as expected'); # now make sure we keep headers $resp = dancer_response(GET => '/catheader/file.txt'); %headers = @{$resp->headers_to_array}; is $headers{FooHeader}, 42, 'FooHeader is kept'; is( $headers{'Content-Disposition'}, 'attachment; filename="header.foo"', 'Content-Disposition header contains expected filename' ); my $png = dancer_response(GET => '/as_png/file.txt'); ok(defined($png), "route handler found for /as_png/file.txt"); my %png_headers = @{$png->headers_to_array}; is($png_headers{'Content-Type'}, 'image/png', 'mime_type can be forced'); $resp = undef; # just to be sure $resp = dancer_response(GET => '/absolute/file.txt'); ok(defined($resp), "route handler found for /absolute/file.txt"); %headers = @{$resp->headers_to_array}; # With hash randomization, .pl can be either text/perl or # application/perl. This is determined by MIME::Types. my $perl_mime = MIME::Types->new->mimeTypeOf('pl'); is($headers{'Content-Type'}, $perl_mime, 'mime_type is ok'); is(ref($resp->{content}), 'GLOB', "content is a File handle"); $content = read_glob_content($resp->{content}); like($content, qr/'foo loaded'/, "content is ok"); $resp = undef; # just to be sure $resp = dancer_response(GET => '/absolute/content_type/file.txt'); %headers = @{$resp->headers_to_array}; is($headers{'Content-Type'}, 'text/plain', 'mime_type is ok'); $resp = undef; # just to be sure $resp = dancer_response(GET => '/scalar/file'); ok(defined($resp), "route handler found for /scalar/file"); %headers = @{$resp->headers_to_array}; is($headers{'Content-Type'}, 'text/plain', 'mime_type is ok'); is( $headers{'Content-Disposition'}, 'attachment; filename="foo.bar"', 'Content-Disposition hedaer contains expected filename' ); $content = $resp->{content}; like($content, qr/FOObar/, "content is ok"); $resp = undef; # just to be sure $resp = dancer_response(GET => '/custom_status'); ok(defined($resp), "route handler found for /custom_status"); is( $resp->{status}, 404, "Status 404 for /custom_status"); is(ref($resp->{content}), 'GLOB', "content is a filehandle"); $content = read_glob_content($resp->{content}); $content =~ s/\r//g; is_deeply( [split(/\n/, $content)], [1,2,3], 'send_file worked as expected'); SKIP: { skip "Need IO::Scalar", 2 unless Dancer::ModuleLoader->load('IO::Scalar'); $resp = undef; # just to be sure $resp = dancer_response(GET => '/ioscalar'); ok(defined($resp), "/ioscalar gave us a response"); is($resp->{content}, "IO::Scalar content", "Got correct content from IO::Scalar"); } # This snippet fixes #912 $resp = undef; $resp = dancer_response(GET => '/404_with_filename'); ok(defined($resp), "route handler found for /404_with_filename"); is($resp->{status}, 404, "Status 404 for /404_with_filename"); libdancer-perl-1.3120+dfsg.orig/t/06_helpers/03_content_type.t0000644000175000017500000000141012233013020023225 0ustar gregoagregoause Dancer ':tests'; use Test::More; use Dancer::Test; get '/' => sub { "hello" }; get '/text' => sub { content_type 'text/plain'; "text"; }; get '/svg' => sub { content_type 'svg'; ""; }; get '/png' => sub { content_type 'png'; "blergh"; }; my @tests = ( { path => '/', expected => setting('content_type')}, { path => '/text', expected => 'text/plain'}, { path => '/', expected => setting('content_type')}, { path => '/text', expected => 'text/plain'}, { path => '/svg', expected => 'image/svg+xml'}, { path => '/png', expected => 'image/png'}, ); plan tests => scalar(@tests); foreach my $test (@tests) { response_headers_include [GET => $test->{path}], ['Content-Type' => $test->{expected}]; } libdancer-perl-1.3120+dfsg.orig/t/06_helpers/06_load.t0000644000175000017500000000036012233013020021437 0ustar gregoagregoause Test::More 'no_plan', import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; my $routes = path('t', '06_helpers', 'routes.pl'); ok( -f $routes, "file routes is found"); load $routes; response_status_is [GET => '/foo'] => 200; libdancer-perl-1.3120+dfsg.orig/t/06_helpers/04_status.t0000644000175000017500000000072612233013020022047 0ustar gregoagregoause Dancer ':tests'; use Test::More; use Dancer::Test; get '/' => sub { "hello" }; get '/not_found' => sub { status 'not_found'; "not here"; }; get '/500' => sub { status 500 }; my @tests = ( { path => '/', expected => 200}, { path => '/not_found', expected => 404}, { path => '/500' => expected => 500 }, ); plan tests => scalar(@tests); foreach my $test (@tests) { response_status_is [ GET => $test->{path} ] => $test->{expected}; } libdancer-perl-1.3120+dfsg.orig/t/14_serializer/0000755000175000017500000000000012256332256020561 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/14_serializer/01_helpers.t0000644000175000017500000001412112233013710022671 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; plan tests => 53; my $struct = {eris => 23}; { # test an unknown serializer eval { setting serializer => 'FooBar'; }; like $@, qr/unable to load serializer engine 'FooBar'/, "Foobar is not a valid serializer"; } SKIP: { skip 'YAML is needed to run this test', 10 unless Dancer::ModuleLoader->load('YAML'); # helpers syntax ok my $test = to_yaml($struct), 'to yaml'; ok my $final_struct = from_yaml($test), 'from yaml'; is_deeply $final_struct, $struct, 'from => to works'; # OO API setting('serializer' => 'YAML'); my $s = Dancer::Serializer->engine; isa_ok( $s, $_ ) for qw( Dancer::Engine Dancer::Serializer::Abstract Dancer::Serializer::YAML); can_ok $s, qw(serialize deserialize); my $yaml = $s->serialize($struct); like $yaml, qr/eris: 23/, "data is correctly serialized"; my $data = $s->deserialize($yaml); is_deeply $struct, $data, "data is correctly deserialized"; is $s->content_type, 'text/x-yaml', "content_type is ok"; } SKIP: { skip 'JSON is needed to run this test', 14 unless Dancer::ModuleLoader->load_with_params('JSON', '-support_by_pp'); # helpers syntax ok my $test = to_json($struct), 'to json'; ok my $final_struct = from_json($test), 'from json'; is_deeply $final_struct, $struct, 'from => to works'; # OO API setting( 'serializer' => 'JSON' ); my $s = Dancer::Serializer->engine; isa_ok( $s, $_ ) for qw( Dancer::Engine Dancer::Serializer::Abstract Dancer::Serializer::JSON); can_ok $s, qw(serialize deserialize); my $json = $s->serialize( $struct, { pretty => 0 } ); is $json, '{"eris":23}', "data is correctly serialized"; my $data = $s->deserialize($json); is_deeply $data, $struct, "data is correctly deserialized"; # with options $data = { foo => { bar => { baz => [qw/23 42/] } } }; $json = to_json( $data, { pretty => 1 } ); like $json, qr/"foo" : \{/, "data is pretty!"; my $data2 = from_json($json); is_deeply( $data2, $data, "data is correctly deserialized" ); # configure JSON parser my $config = { engines => { JSON => { allow_blessed => 1, convert_blessed => 1, pretty => 0, escape_slash => 1 } } }; ok $s = Dancer::Serializer->init( 'JSON', $config ), 'JSON serializer with custom config'; $data = { foo => '/bar' }; my $res = $s->serialize($data); is_deeply( $data, JSON::decode_json($res), 'data is correctly serialized' ); ok($res =~m|\\/|, 'JSON serializer obeys config options to init'); # # XXX tests for deprecation # my $warn; # local $SIG{__WARN__} = sub { $warn = $_[0] }; # $s->_options_as_hashref( foo => 'bar' ); # ok $warn, 'deprecation warning'; # undef $warn; # $s->_options_as_hashref( { foo => 'bar' } ); # ok !$warn, 'no deprecation warning'; # to_json( { foo => 'bar' }, { indent => 0 } ); # ok $warn, 'deprecation warning'; } SKIP: { skip 'XML::Simple is needed to run this test', 13 unless Dancer::ModuleLoader->load('XML::Simple'); skip 'XML::Parser or XML::SAX are needed to run this test', 13 unless Dancer::ModuleLoader->load('XML::Parser') or Dancer::ModuleLoader->load('XML::SAX'); # helpers ok my $test = to_xml($struct), 'to xml'; ok my $final_struct = from_xml($test), 'from xml'; is_deeply $final_struct, $struct, 'from => to works'; my $xml = to_xml($struct, RootName => undef); like $xml, qr/23<\/eris>/, "data is correctly serialized"; my $data = from_xml($xml); is $data, 23, "data is correctly deserialized"; $data = { task => { type => "files", continue => 1, action => 123, content => '46210660-b78f-11df-8d81-0800200c9a66', files => { file => [2131231231] } }, }; $xml = to_xml($data, RootName => undef, AttrIndent => 1); like $xml, qr/\n\s+\w+="\w+">46210660-b78f-11df-8d81-0800200c9a66/, 'xml attributes are indented'; # OO API setting( 'serializer' => 'XML' ); my $s = Dancer::Serializer->engine; isa_ok( $s, $_ ) for qw( Dancer::Engine Dancer::Serializer::Abstract Dancer::Serializer::XML); can_ok $s, qw(serialize deserialize); $xml = $s->serialize($struct); like $xml, qr/eris="23"/, "data is correctly serialized"; $data = $s->deserialize($xml); is_deeply $struct, $data, "data is correctly deserialized"; is $s->content_type, 'text/xml', 'content type is ok'; } SKIP: { skip 'YAML is needed to run this test', 7 unless Dancer::ModuleLoader->load('YAML'); skip 'JSON is needed to run this test', 7 unless Dancer::ModuleLoader->load('JSON'); setting( 'serializer' => 'Mutable' ); my $s = Dancer::Serializer->engine; isa_ok( $s, $_ ) for qw( Dancer::Engine Dancer::Serializer::Abstract Dancer::Serializer::Mutable); can_ok $s, qw(serialize deserialize); ok !defined $s->content_type, 'no content_type defined'; ok $s->support_content_type('application/json'), 'application/json is a supported content_type'; ok !$s->support_content_type('foo/bar'), 'foo/bar is not a supported content_type'; } { setting( 'serializer' => 'Dumper' ); my $s = Dancer::Serializer->engine; isa_ok( $s, $_ ) for qw( Dancer::Engine Dancer::Serializer::Abstract Dancer::Serializer::Dumper); can_ok $s, qw(serialize deserialize); my $dumper = $s->serialize($struct); like $dumper, qr/'eris' => 23/, "data is correctly serialized by \$s"; like to_dumper($struct), qr/'eris' => 23/, "data is correctly serialized by to_dumper()"; my $data = $s->deserialize($dumper); is_deeply $data, $struct, "data is correctly deserialized by \$s"; is $s->content_type, 'text/x-data-dumper', "content_type is text/x-data-dumper"; } libdancer-perl-1.3120+dfsg.orig/t/14_serializer/06_api.t0000644000175000017500000000721412233013710022012 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Request; use Dancer::Serializer; use Dancer::Serializer::Abstract; plan tests => 16; SKIP: { skip 'JSON is needed to run this test', 3 unless Dancer::ModuleLoader->load('JSON'); ok my $s = Dancer::Serializer->init(); my $ct = $s->support_content_type(); ok !defined $ct; $ct = $s->content_type(); is $ct, 'application/json'; } { eval { Dancer::Serializer::Abstract->serialize() }; like $@, qr{must be implemented}, "serialize is a virtual method"; eval { Dancer::Serializer::Abstract->deserialize() }; like $@, qr{must be implemented}, "deserialize is a virtual method"; is( Dancer::Serializer::Abstract->loaded, 0, "loaded is 0" ); is( Dancer::Serializer::Abstract->content_type, "text/plain", "content_type is text/plain" ); ok( Dancer::Serializer::Abstract->support_content_type('text/plain'), "text/plain is supported" ); ok( Dancer::Serializer::Abstract->support_content_type( 'text/plain; charset=utf8'), "text/plain; charset=utf8 is supported" ); ok( !Dancer::Serializer::Abstract->support_content_type('application/json'), "application/json is not supported" ); } SKIP: { skip 'JSON is needed to run this test', 3 unless Dancer::ModuleLoader->load('JSON'); skip 'YAML is needed to run this test', 3 unless Dancer::ModuleLoader->load('YAML'); set serializer => 'Mutable'; my $s = Dancer::Serializer->engine; # Ensure the temp directory is resolved before we destroy the environment # (since it needs the environment to do so, and caches after the first time) File::Spec->tmpdir; %ENV = ( 'REQUEST_METHOD' => 'GET', 'HTTP_CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'text/xml', 'HTTP_ACCEPT_TYPE' => 'text/x-yaml', 'PATH_INFO' => '/', ); my $req = Dancer::Request->new( env => \%ENV ); Dancer::SharedData->request($req); my $ct = Dancer::Serializer::Mutable::_find_content_type($req); is_deeply $ct, [ 'text/xml', 'text/x-yaml', 'application/json' ]; %ENV = ( 'REQUEST_METHOD' => 'PUT', 'PATH_INFO' => '/', ); $req = Dancer::Request->new( env => \%ENV ); Dancer::SharedData->request($req); $ct = Dancer::Serializer::Mutable::_find_content_type($req); is_deeply $ct, ['application/json']; %ENV = ( 'REQUEST_METHOD' => 'PUT', 'PATH_INFO' => '/', 'HTTP_ACCEPT' => 'text/xml', 'CONTENT_TYPE' => 'application/json', ); $req = Dancer::Request->new( env => \%ENV ); Dancer::SharedData->request($req); $ct = Dancer::Serializer::Mutable::_find_content_type($req); is_deeply $ct, [ 'application/json', 'text/xml' ]; } # handler helper SKIP: { skip 'JSON is needed to run this test', 3 unless Dancer::ModuleLoader->load('JSON'); my $body = '{"foo":42}'; open my $in, '<', \$body; my $env = { CONTENT_LENGTH => length($body), CONTENT_TYPE => Dancer::Serializer::JSON->content_type, REQUEST_METHOD => 'PUT', SCRIPT_NAME => '/', 'psgi.input' => $in, }; my $expected_params = { foo => '42', }; # --- my $req = Dancer::Request->new( env => $env); is $req->body, $body, "body is untouched"; my $processed_req = Dancer::Serializer->process_request($req); is_deeply( scalar( $processed_req->params('body') ), $expected_params, "body request has been deserialized" ); is $processed_req->params->{'foo'}, 42, "params have been updated"; } libdancer-perl-1.3120+dfsg.orig/t/14_serializer/17_clear_serializer.t0000644000175000017500000000275012233013710024562 0ustar gregoagregoause Dancer ':tests'; use Dancer::Test; use Test::More; use Dancer::ModuleLoader; use LWP::UserAgent; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => 'JSON is needed to run this test' unless Dancer::ModuleLoader->load('JSON'); plan tests => 4; set serializer => 'JSON'; my $data = { foo => 'bar' }; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $request = HTTP::Request->new( GET => "http://127.0.0.1:$port/" ); my $res; $res = $ua->request($request); ok( $res->is_success, 'Successful response from server' ); like( $res->content, qr/"foo" \s \: \s "bar"/x, 'Correct content', ); # new request, no serializer $res = $ua->request($request); ok( $res->is_success, 'Successful response from server' ); like($res->content, qr/HASH\(0x.+\)/, 'Serializer undef, response not serialised'); }, server => sub { my $port = shift; use Dancer ':tests'; set( apphandler => 'Standalone', port => $port, show_errors => 1, startup_info => 0 ); get '/' => sub { $data }; hook after => sub { set serializer => undef }; Dancer->dance(); }, ); libdancer-perl-1.3120+dfsg.orig/t/14_serializer/05_request_mutable.t0000644000175000017500000000202612233013710024435 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Test; BEGIN { plan skip_all => 'YAML is needed to run this test' unless Dancer::ModuleLoader->load('YAML'); plan skip_all => 'JSON is needed to run this test' unless Dancer::ModuleLoader->load('JSON'); } plan tests => 6; set serializer => 'mutable'; get '/' => sub { { foo => 1 } }; post '/' => sub { request->params }; for my $ct (qw/Accept Accept-Type/) { my $res = dancer_response( GET => '/', { headers => [ $ct => 'application/json' ] } ); is_deeply( from_json( $res->content ), { foo => 1 } ); is $res->header('Content-Type'), 'application/json'; } my $res = dancer_response( POST => '/', { params => { foo => 42 }, headers => [ 'Content-Type' => 'text/x-yaml', 'Accept-Type' => 'application/json' ] } ); is_deeply(from_yaml($res->content), {foo => 42}); is $res->header('Content-Type'), 'text/x-yaml'; libdancer-perl-1.3120+dfsg.orig/t/14_serializer/99_bugs.t0000644000175000017500000000603712233013020022211 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Test; use HTTP::Request; plan tests => 13; # issue 57829 SKIP: { skip 'JSON is needed to run this test', 2 unless Dancer::ModuleLoader->load('JSON'); setting( 'serializer' => 'JSON' ); get '/' => sub { header 'X-Test' => 'ok'; { body => 'ok' } }; my $res = dancer_response( GET => '/' ); is $res->header('Content-Type'), 'application/json'; is $res->header('X-Test'), 'ok'; } # issue gh-106 SKIP: { skip 'JSON is needed to run this test', 1 unless Dancer::ModuleLoader->load('JSON'); setting( 'serializer' => 'JSON' ); setting engines => { JSON => { allow_blessed => 1, convert_blessed => 1 } }; get '/blessed' => sub { my $r = HTTP::Request->new( GET => 'http://localhost' ); { request => $r }; }; my $res = dancer_response( GET => '/blessed', {headers => ['Content-Type' => 'application/json']}); is_deeply( from_json( $res->content ), { request => undef } ); } # issue gh-299 SKIP: { skip 'JSON is needed to run this test', 5 unless Dancer::ModuleLoader->load('JSON'); get '/hash' => sub {{a => 1, b => 2, c => 3}}; foreach my $method (qw/HEAD GET/){ my $res = dancer_response($method => '/hash'); is $res->status, 200; is $res->header('Content-Type'), 'application/json'; } my $res = dancer_response(HEAD => '/hash'); ok !$res->content; } # RT #57805 # https://rt.cpan.org/Ticket/Display.html?id=57805 # # Serializer issue: params hash not populated when the Content-Type is a # supported media type with additional parameters SKIP: { skip 'JSON is needed to run this test', 3 unless Dancer::ModuleLoader->load('JSON'); post '/test' => sub { return { test_value => params->{test_value} }; }; my $data = { foo => 42 }; for my $ct ( 'application/json', 'APPLICATION/JSON', 'application/json; charset=UTF-8' ) { my $res = dancer_response( POST => '/test', { body => to_json( { test_value => $data } ), headers => [ 'Content-Type' => $ct ] } ); is_deeply( from_json( $res->content ), { test_value => $data }, "correctly deserialized when Content-Type is set to '$ct'" ); } } # show errors SKIP: { skip 'JSON is needed to run this test', 2 unless Dancer::ModuleLoader->load('JSON'); set environment => 'production'; get '/with_errors' => sub { setting show_errors => 1; # bam! UnknownPackage->method(); }; get '/without_errors' => sub { setting show_errors => 0; # bam! UnknownPackage->method(); }; my $res = dancer_response(GET => '/with_errors'); like($res->content, qr{"error":"Can't locate object method \\"method\\" via package \\"UnknownPackage\\"}); $res = dancer_response(GET => '/without_errors'); like($res->content, qr{An internal error occured}); } libdancer-perl-1.3120+dfsg.orig/t/14_serializer/04_request_xml.t0000644000175000017500000000320212233013710023600 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Test; plan tests => 10; SKIP: { skip 'XML::Simple is needed to run this test', 10 unless Dancer::ModuleLoader->load('XML::Simple'); skip 'XML::Parser or XML::SAX are needed to run this test', 10 unless Dancer::ModuleLoader->load('XML::Parser') or Dancer::ModuleLoader->load('XML::SAX'); set serializer => 'XML', show_errors => 1; get '/' => sub { { foo => 'bar' } }; post '/' => sub { request->params }; get '/error' => sub { send_error( { foo => 42 }, 401 ) }; get '/error_bis' => sub { send_error( 42, 402 ) }; get '/xml' => sub { content_type('text/xml'); to_xml( { foo => 'bar' } ) }; for my $route ( '/', '/xml' ) { my $res = dancer_response( GET => $route ); is $res->header('Content-Type'), 'text/xml'; like $res->content, qr//; } my $res = dancer_response( POST => '/', { params => { foo => 1 }, headers => [ 'Content-Type' => 'text/xml' ] } ); is_deeply( from_xml( $res->content ), { foo => 1 }, "data is correctly deserialized" ); is $res->header('Content-Type'), 'text/xml', 'goodcontent type set in response'; $res = dancer_response( GET => '/error' ); is $res->status, 401; is_deeply( from_xml($res->content ), { foo => 42 } ); $res = dancer_response( GET => '/error_bis' ); is $res->status, 402; is_deeply( from_xml( $res->content ), { error => 42 } ); } libdancer-perl-1.3120+dfsg.orig/t/14_serializer/03_request_yaml.t0000644000175000017500000000270212233013710023745 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Test; plan tests => 10; SKIP: { skip 'YAML is needed to run this test', 10 unless Dancer::ModuleLoader->load('YAML'); set serializer => 'YAML', show_errors => 1; get '/' => sub { { foo => 'bar' } }; post '/' => sub { request->params }; get '/error' => sub { send_error( { foo => 42 }, 401 ) }; get '/error_bis' => sub { send_error( 42, 402 ) }; get '/yaml' => sub { content_type('text/x-yaml'); to_yaml( { foo => 'bar' } ); }; for my $route ( '/', '/yaml' ) { my $res = dancer_response( GET => $route ); is $res->header('Content-Type'), 'text/x-yaml'; like $res->content, qr/foo: bar/; } my $res = dancer_response( POST => '/', { params => { foo => 1 }, headers => [ 'Content-Type' => 'text/x-yaml' ] } ); is_deeply( from_yaml( $res->content ), { foo => 1 }, "data is correctly deserialized" ); is $res->header('Content-Type'), 'text/x-yaml', 'goodcontent type set in response'; $res = dancer_response( GET => '/error' ); is $res->status, 401; is_deeply( from_yaml( $res->content ), { foo => 42 } ); $res = dancer_response( GET => '/error_bis' ); is $res->status, 402; is_deeply( from_yaml( $res->content ), { error => 42 } ); } libdancer-perl-1.3120+dfsg.orig/t/14_serializer/02_request_json.t0000644000175000017500000000320212233013710023747 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Test; BEGIN { plan skip_all => "need JSON" unless Dancer::ModuleLoader->load('JSON'); plan tests => 11; } set 'serializer' => 'JSON', 'show_errors' => 1; get '/' => sub { { foo => 'bar' } }; post '/' => sub { params }; put '/' => sub { param("id") }; get '/error' => sub { send_error( { foo => 42 }, 401 ) }; get '/error_bis' => sub { send_error( 42, 402 ) }; get '/json' => sub { content_type('application/json'); to_json( { foo => 'bar' } ) }; response_content_is [ PUT => '/', { body => '{"id": "foo"}' , headers => [ 'Content-Type' => 'application/json' ], } ] => 'foo'; for my $route ( '/', '/json' ) { my $res = dancer_response( GET => $route ); is $res->header('Content-Type'), 'application/json'; like $res->content, qr/"foo" : "bar"/; } my $res = dancer_response ( POST => '/', { params => { foo => 1 }, headers => [ 'Content-Type' => 'application/json' ] } ); is_deeply( from_json( $res->content ), { foo => 1 }, "data is correctly deserialized" ); is $res->header('Content-Type'), 'application/json', 'goodcontent type set in response'; $res = dancer_response( GET => '/error' ); is $res->status, 401; is_deeply( from_json( $res->content ), { foo => 42 } ); $res = dancer_response( GET => '/error_bis' ); is $res->status, 402; is_deeply( from_json( $res->content ), { error => 42 } ); libdancer-perl-1.3120+dfsg.orig/t/05_views/0000755000175000017500000000000012256332256017545 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/05_views/views/0000755000175000017500000000000012256332256020702 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/05_views/views/index.tt0000644000175000017500000000005711506417160022357 0ustar gregoagregoain view index.tt: number="<% params.number %>" libdancer-perl-1.3120+dfsg.orig/t/05_views/views/vars.tt0000644000175000017500000000001712233013020022200 0ustar gregoagregoa<% vars.foo %> libdancer-perl-1.3120+dfsg.orig/t/05_views/views/layouts/0000755000175000017500000000000012256332256022402 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/05_views/views/layouts/main.tt0000644000175000017500000000003011506417160023663 0ustar gregoagregoastart <% content %>stop libdancer-perl-1.3120+dfsg.orig/t/05_views/views/layouts/custom.tt0000644000175000017500000000004412233013020024237 0ustar gregoagregoacustomstart <% content %>customstop libdancer-perl-1.3120+dfsg.orig/t/05_views/views/t03.tt0000644000175000017500000000000511506417160021647 0ustar gregoagregoaview libdancer-perl-1.3120+dfsg.orig/t/05_views/views/clock.tt0000644000175000017500000000001311506417160022333 0ustar gregoagregoa<% time %> libdancer-perl-1.3120+dfsg.orig/t/05_views/views/request.tt0000644000175000017500000000003011506417160022727 0ustar gregoagregoa<% request.path_info %> libdancer-perl-1.3120+dfsg.orig/t/05_views/03_layout.t0000644000175000017500000000524612233013707021550 0ustar gregoagregoaBEGIN { use Dancer ':tests'; use Test::More; use Dancer::ModuleLoader; plan skip_all => "Template is needed to run this tests" unless Dancer::ModuleLoader->load('Template'); plan skip_all => "YAML needed to run this tests" unless Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestUtils; }; use Dancer::Test; set views => path(dirname(__FILE__), 'views'); my @tests = ( { path => '/solo', expected => "view\n" }, { path => '/full', expected => "start\nview\nstop\n" }, { path => '/layoutdisabled', expected => "view\n" }, { path => '/layoutchanged', expected => "customstart\nview\ncustomstop\n" }, { path => '/render_layout_only/default_layout', expected => "start\ncontent\nstop\n" }, { path => '/render_layout_only/no_layout', expected => "content\n" }, { path => '/render_layout_only/custom_layout', expected => "customstart\ncontent\ncustomstop\n" }, ); plan tests => scalar(@tests) + 4; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir; my $envdir = File::Spec->catdir($dir, 'environments'); mkdir $envdir; my $conffile = Dancer::Config->conffile; ok(defined($conffile), 'Default conffile is defined' ); ok(Dancer::Config->load, 'Config load works without conffile'); # create the conffile my $conf = ' layout: main '; write_file( $conffile => $conf ); ok( Dancer::Config->load, 'Config load works with a conffile' ); is( setting('layout'), 'main', 'Correct layout setting from config' ); Template->import; get '/solo' => sub { setting layout => undef; template 't03'; }; get '/full' => sub { set layout => 'main'; template 't03'; }; get '/layoutdisabled' => sub { set layout => 'main'; template 't03', {}, { layout => undef }; }; get '/layoutchanged' => sub { template 't03', {}, { layout => 'custom' }; }; get '/render_layout_only/default_layout' => sub { engine('template')->apply_layout("content\n"); }; # Yes, apply_layout without a layout is kind of pointless, but let's # be thorough :) get '/render_layout_only/no_layout' => sub { engine('template')->apply_layout("content\n", {}, { layout => undef }); }; get '/render_layout_only/custom_layout' => sub { engine('template')->apply_layout("content\n", {}, { layout => 'custom' }); }; foreach my $test (@tests) { my $path = $test->{path}; my $expected = $test->{expected}; response_content_is [ GET => $path ] => $expected; } unlink $conffile; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/05_views/002_view_rendering.t0000644000175000017500000000250512233013020023300 0ustar gregoagregoause Dancer ':tests'; use Test::More; use Dancer::Test; my $views = path(dirname(__FILE__), 'views'); set views => $views; my $time = time(); set show_errors => 1; my @tests = ( { path => '/', expected => "in view index.tt: number=\"\"\n" }, { path => '/number/42', expected => "in view index.tt: number=\"42\"\n" }, { path => '/clock', expected => "$time\n"}, { path => '/request', expected => "/request\n" }, { path => '/vars', expected => "bar\n" }, ); plan tests => 2 + scalar(@tests); # 1. Check setting variables { is setting("views") => $views, "Views setting was correctly set"; ok !defined(setting("layout")), 'layout is not defined'; } # 2. Check views # test simple rendering get '/' => sub { template 'index'; }; get '/with_fh' => sub { my $fh; die "TODO"; }; # test params.foo in view get '/number/:number' => sub { template 'index' }; # test token interpolation get '/clock' => sub { template clock => { time => $time }; }; # test request.foo in view get '/request' => sub { template 'request'; }; # test vars in view get '/vars' => sub { var foo => 'bar'; template 'vars'; }; foreach my $test (@tests) { my $path = $test->{path}; my $expected = $test->{expected}; response_content_is [GET => $path] => $expected; } libdancer-perl-1.3120+dfsg.orig/t/pod.t0000644000175000017500000000052412233013710017036 0ustar gregoagregoa#!perl -T use strict; use warnings; use Test::More; unless ( $ENV{RELEASE_TESTING} ) { plan( skip_all => "Author tests not required for installation" ); } # Ensure a recent version of Test::Pod my $min_tp = 1.44; eval "use Test::Pod $min_tp"; plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; all_pod_files_ok(); libdancer-perl-1.3120+dfsg.orig/t/10_template/0000755000175000017500000000000012256332256020217 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/10_template/views/0000755000175000017500000000000012256332256021354 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/10_template/views/index.tt0000644000175000017500000000002112233013020023001 0ustar gregoagregoafoo => <% foo %> libdancer-perl-1.3120+dfsg.orig/t/10_template/views/layouts/0000755000175000017500000000000012256332256023054 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/10_template/views/layouts/main.tt0000644000175000017500000000004612233013020024325 0ustar gregoagregoalayout:<%foo%> content:<% content %> libdancer-perl-1.3120+dfsg.orig/t/10_template/views/layouts/main.ts0000644000175000017500000000004612233013020024324 0ustar gregoagregoalayout:<%foo%> content:<% content %> libdancer-perl-1.3120+dfsg.orig/t/10_template/views/index.ts0000644000175000017500000000002112233013020023000 0ustar gregoagregoabar => <% bar %> libdancer-perl-1.3120+dfsg.orig/t/10_template/template.t0000644000175000017500000000066112233013710022204 0ustar gregoagregoause Test::More import => ['!pass']; plan tests => 2; use strict; use warnings; { use Dancer; setting views => path('t', '10_template', 'views'); get '/' => sub { template 'index', {foo => 42}; }; get '/nonexisting' => sub { template 'none', { error => 'yes' }; }; } use Dancer::Test; response_content_is [GET => '/'], "foo => 42\n"; response_status_is [GET => '/nonexisting'] => 500; libdancer-perl-1.3120+dfsg.orig/t/10_template/extension.t0000644000175000017500000000115312233013020022374 0ustar gregoagregoause Test::More import => ['!pass']; plan tests => 1; use strict; use warnings; { use Dancer; use Dancer::Template; my $config = { engines => { simple => { extension => 'ts', }, }, }; setting views => path('t', '10_template', 'views'); Dancer::Template->init("simple", $config); get '/' => sub { template 'index', { bar => 42}; }; } use Dancer::Test; response_content_is [GET => '/'], "bar => 42\n"; libdancer-perl-1.3120+dfsg.orig/t/10_template/05_template_toolkit.t0000644000175000017500000000370712233013020024253 0ustar gregoagregoause Test::More; use strict; use warnings; use Dancer::ModuleLoader; use Dancer::FileUtils 'path'; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; BEGIN { plan skip_all => "need Template to run this test" unless Dancer::ModuleLoader->load('Template'); plan tests => 7; use_ok 'Dancer::Template::TemplateToolkit'; }; my $mock = { 'Template' => 0 }; mock 'Dancer::ModuleLoader' => method 'load' => should sub { $mock->{ $_[1] } }; mock 'Template' => method 'can' => should sub { 0 }; my $engine; eval { $engine = Dancer::Template::TemplateToolkit->new }; like $@, qr/Template is needed by Dancer::Template::TemplateToolkit/, "Template dependency caught at init time"; $mock->{Template} = 1; eval { $engine = Dancer::Template::TemplateToolkit->new }; is $@, '', "Template dependency is not triggered if Template is there"; # as a file path my $template = path('t', '10_template', 'index.txt'); my $result = $engine->render( $template, { var1 => 1, var2 => 2, foo => 'one', bar => 'two', baz => 'three'}); $result =~ s/\r//g; my $expected = 'this is var1="1" and var2=2'."\n\nanother line\n\n one two three\n\n1/1\n"; is $result, $expected, "processed a template given as a file name"; # as a filehandle my $fh; open $fh, '<', $template or die "cannot open file $template: $!"; $result = $engine->render( $fh, { var1 => 1, var2 => 2, foo => 'one', bar => 'two', baz => 'three'}); is $result, $expected, "processed a template given as a file handle"; $expected = "one=1, two=2, three=3"; $template = "one=<% one %>, two=<% two %>, three=<% three %>"; eval { $engine->render($template, { one => 1, two => 2, three => 3}) }; like $@, qr/doesn't exist or not a regular file/, "prorotype failure detected"; $result = $engine->render(\$template, { one => 1, two => 2, three => 3}); is $result, $expected, "processed a template given as a scalar ref"; libdancer-perl-1.3120+dfsg.orig/t/10_template/02_abstract_class.t0000644000175000017500000000075412233013710023665 0ustar gregoagregoause Test::More tests => 4, import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::Template::Abstract; my $a = Dancer::Template::Abstract->new; eval { $a->render }; like $@, qr/render not implemented/, "cannot call abstract method render"; is $a->init, 1, "default init returns 1"; is $a->default_tmpl_ext, "tt"; $a = Dancer::Template::Abstract->new; $a->config->{extension} = 'foo'; my @views = $a->_template_name('bar'); is_deeply \@views, ["bar", "bar.foo" ]; libdancer-perl-1.3120+dfsg.orig/t/10_template/000_create_fake_env.t0000644000175000017500000000052412233013020024041 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/10_template/index.txt0000644000175000017500000000015712233013020022046 0ustar gregoagregoathis is var1="<% var1 %>" and var2=<% var2 %> another line <% foo%> <%bar %> <%baz%> <% var1 %>/<% var1 %> libdancer-perl-1.3120+dfsg.orig/t/10_template/03_simple.t0000644000175000017500000000523312233013020022156 0ustar gregoagregoause Test::More tests => 9; use strict; use warnings; use Dancer::FileUtils 'path'; use Dancer::Template::Simple; { package Foo; use base 'Dancer::Object'; Foo->attributes('x', 'y'); sub method { "yeah" } } # variable interpolation, with file-based template my $engine = Dancer::Template::Simple->new; my $template = path('t', '10_template', 'index.txt'); my $result = $engine->render( $template, { var1 => "xxx", var2 => "yyy", foo => 'one', bar => 'two', baz => 'three'}); my $expected = 'this is var1="xxx" and var2=yyy'."\n\nanother line\n\n one two three\n\nxxx/xxx\n"; is $result, $expected, "template got processed successfully"; # variable interpolation, with scalar-based template $expected = "one=1, two=2, three=3 - 77"; $template = "one=<% one %>, two=<% two %>, three=<% three %> - <% hash.key %>"; eval { $engine->render($template, { one => 1, two => 2, three => 3}) }; like $@, qr/is not a regular file/, "prorotype failure detected"; $result = $engine->render(\$template, { one => 1, two => 2, three => 3, hash => { key => 77 }, }); is $result, $expected, "processed a template given as a scalar ref"; # complex variable interpolation (object, coderef and hash) my $foo = Foo->new; $foo->x(42); $template = 'foo->x == <% foo.x %> foo.method == <% foo.method %> foo.dumb=\'<% foo.dumb %>\''; $expected = 'foo->x == 42 foo.method == yeah foo.dumb=\'\''; $result = $engine->render(\$template, { foo => $foo }); is $result, $expected, 'object are interpolated in templates'; $template = 'code = <% code %>, code <% hash.code %>'; $expected = 'code = 42, code 42'; $result = $engine->render(\$template, { code => sub { 42 }, hash => { code => sub { 42 } } }); is $result, $expected, 'code ref are interpolated in templates'; $template = 'array: <% array %>, hash.array: <% hash.array %>'; $expected = 'array: 1 2 3 4 5, hash.array: 6 7 8'; $result = $engine->render(\$template, { array => [1, 2, 3, 4, 5], hash => { array => [6, 7, 8] }}); is $result, $expected, "arrayref are interpolated in templates"; # if-then-else $template = '<% if want %>hello<% else %>goodbye<% end %> world'; $result = $engine->render(\$template, {want => 1}); is $result, 'hello world', "true boolean condition matched"; $result = $engine->render(\$template, {want => 0}); is $result, 'goodbye world', "false boolean condition matched"; $template = 'one: 1 two: <% two %> three : <% three %>'; $result = $engine->render(\$template, {two => 2, three => 3 }); is $result, 'one: 1 two: 2 three : 3', "multiline template processed"; libdancer-perl-1.3120+dfsg.orig/t/10_template/01_factory.t0000644000175000017500000000137012233013710022336 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer::ModuleLoader; use Dancer; plan skip_all => "Template needed" unless Dancer::ModuleLoader->load('Template'); plan tests => 6; use_ok 'Dancer::Template'; ok(Dancer::Template->init, "template init with undef setting"); eval { setting template => 'FOOOBAR' }; like $@, qr/unable to load template engine/, "cannot load unknown template engine"; setting template => 'simple'; ok(Dancer::Template->init, "template init with 'simple' setting"); is(ref(Dancer::Template->engine), 'Dancer::Template::Simple', "template engine is Simple"); set template => 'template_toolkit'; is(ref(Dancer::Template->engine), 'Dancer::Template::TemplateToolkit', "template engine is TT"); libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/0000755000175000017500000000000012256332256020713 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/02_apache2_plack.t0000644000175000017500000000607712233013020024044 0ustar gregoagregoa# simulate an Apache2 + Plack environment use strict; use warnings; use Test::More import => ['!pass']; plan skip_all => "Plack is needed for this test" unless Dancer::ModuleLoader->load('Plack::Request'); plan tests => 2; use Dancer::Handler::PSGI; use File::Spec; use Dancer::Request; my $request = {}; my $env = {}; my $document_root = File::Spec->rel2abs('.'); my $server_name = 'localhost.localdomain'; my $remote_addr = '127.0.0.1'; my $server_admin = 'admin@domain.com'; my $server_addr = '127.0.0.1'; my $host_name = 'app.localdomain.com'; # a / request $request->{'/'} = Dancer::Request->new_for_request(GET => '/'); $env->{'/'} = { 'psgi.multiprocess' => 1, 'SCRIPT_NAME' => '/', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'REQUEST_METHOD' => 'GET', 'psgi.multithread' => '', 'SCRIPT_FILENAME' => '/srv/twitter-karma.sukria.net/public/', 'SERVER_SOFTWARE' => 'Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny3 with Suhosin-Patch mod_python/3.3.1 Python/2.5.2 Phusion_Passenger/2.0.3 mod_perl/2.0.4 Perl/v5.10.0', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.0.13) Gecko/2009080315 Ubuntu/9.04 (jaunty) Firefox/3.0.13', 'REMOTE_PORT' => '33677', 'QUERY_STRING' => '', 'SERVER_SIGNATURE' => '
Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny3 with Suhosin-Patch mod_python/3.3.1 Python/2.5.2 Phusion_Passenger/2.0.3 mod_perl/2.0.4 Perl/v5.10.0 Server at k.sukria.net Port 80
', 'HTTP_CACHE_CONTROL' => 'max-age=0', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,fr;q=0.8,fr-fr;q=0.5,en;q=0.3', 'HTTP_KEEP_ALIVE' => '300', 'MOD_PERL_API_VERSION' => '2', 'PATH' => '/usr/local/bin:/usr/bin:/bin', 'GATEWAY_INTERFACE' => 'CGI/1.1', 'psgi.version' => [ 1, 0 ], 'DOCUMENT_ROOT' => $document_root, 'psgi.run_once' => '', 'SERVER_NAME' => $server_name, 'SERVER_ADMIN' => $server_admin, 'HTTP_ACCEPT_ENCODING' => 'gzip,deflate', 'HTTP_CONNECTION' => 'keep-alive', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'SERVER_PORT' => '80', 'REMOTE_ADDR' => $remote_addr, 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_URI' => '/', 'psgi.errors' => *::STDERR, 'SERVER_ADDR' => $server_addr, 'psgi.url_scheme' => 'http', 'HTTP_HOST' => $host_name, }; use Dancer; set apphandler => 'PSGI', logger => 'file'; Dancer::Config->load; get '/' => sub { '/' }; get '/foo' => sub { '/foo' }; my $req = $request->{'/'}; my $handler = Dancer::Handler::PSGI->new; my $resp = $handler->handle_request($req); ok(defined($resp), 'handle_request responded'); is($resp->[0], 200, 'status is 200 OK'); libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/01_base.t0000644000175000017500000000160612233013020022271 0ustar gregoagregoause Test::More import => ['!pass']; plan skip_all => "Plack is needed for this test" unless Dancer::ModuleLoader->load('Plack::Request'); plan tests => 6; use Dancer ':syntax'; is(setting('apphandler'), 'Standalone', 'default apphandler is standalone'); my $app = Dancer::Handler->get_handler; is(ref($app), 'Dancer::Handler::Standalone', 'got expected handler'); set apphandler => 'PSGI'; is(setting('apphandler'), 'PSGI', 'PSGI is set'); $app = Dancer::Handler->get_handler; is(ref($app), 'Dancer::Handler::PSGI', 'got expected handler'); $ENV{'PLACK_ENV'} = 1; set apphandler => 'Standalone'; $app = Dancer::Handler->get_handler; is(ref($app), 'Dancer::Handler::PSGI', 'got expected handler'); delete $ENV{'PLACK_ENV'}; set apphandler => 'Null'; eval { Dancer::Handler->get_handler }; like $@, qr{Unable to load app handler `Dancer::Handler::Null}, "invalid apphandler is detected"; libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/05_psgi_api.t0000644000175000017500000000200312233013020023146 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; BEGIN { use Dancer::ModuleLoader; plan skip_all => "Plack is needed to run this test" unless Dancer::ModuleLoader->load('Plack::Request'); use Dancer ':syntax'; } plan tests => 7; Dancer::ModuleLoader->require('Dancer::Handler::PSGI'); my $handler = Dancer::Handler::PSGI->new(); my %ENV = ( REQUEST_METHOD => 'GET', PATH_INFO => '/', HTTP_ACCEPT => 'text/html', HTTP_USER_AGENT => 'test::more', ); $handler->init_request_headers( \%ENV ); my $app = sub { my $env = shift; my $request = Dancer::Request->new( env => \%ENV ); $handler->handle_request($request); }; set 'plack_middlewares' => [['Runtime']], 'public' => '.'; ok $app = $handler->apply_plack_middlewares($app); my $res = $app->( \%ENV ); is $res->[0], 404; ok grep { /X-Runtime/ } @{ $res->[1] }; ok $handler = Dancer::Handler::PSGI->new(); ok $app = $handler->dance; $res = $app->(\%ENV); is $res->[0], 404; is ref $app, 'CODE'; libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/04_standalone_app.t0000644000175000017500000000317612233013707024372 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Plack::Loader"); use LWP::UserAgent; plan tests => 6; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $res = $ua->get("http://127.0.0.1:$port/env"); like $res->content, qr/PATH_INFO/, 'path info is found in response'; $res = $ua->get("http://127.0.0.1:$port/name/bar"); like $res->content, qr/Your name: bar/, 'name is found on a GET'; $res = $ua->get("http://127.0.0.1:$port/name/baz"); like $res->content, qr/Your name: baz/, 'name is found on a GET'; $res = $ua->post("http://127.0.0.1:$port/name", { name => "xxx" }); like $res->content, qr/Your name: xxx/, 'name is found on a POST'; # we are already skipping under MSWin32 (check plan above) $res = $ua->get("http://127.0.0.1:$port/issues/499/true"); is $res->content, "OK"; $res = $ua->get("http://127.0.0.1:$port/issues/499/false"); is $res->content, "OK"; }, server => sub { my $port = shift; use Dancer; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestApp; Dancer::Config->load; set( port => $port, startup_info => 0 ); Dancer->dance(); }, ); libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/000_create_fake_env.t0000644000175000017500000000052412233013020024535 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/07_middleware_map.t0000644000175000017500000000321312233013707024347 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; use LWP::UserAgent; use File::Spec; use lib File::Spec->catdir('t','lib'); plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); plan skip_all => "Plack is needed to run this test" unless Dancer::ModuleLoader->load('Plack::Request'); Dancer::ModuleLoader->load('Plack::Loader'); my $confs = { '/hash' => [['Runtime']], }; my @tests = ( { path => '/', runtime => 0 }, { path => '/hash', runtime => 1 } ); plan tests => (2 * scalar @tests); Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; foreach my $test (@tests) { my $req = HTTP::Request->new( GET => "http://localhost:$port" . $test->{path} ); my $res = $ua->request($req); ok $res; if ( $test->{runtime} ) { ok $res->header('X-Runtime'); } else { ok !$res->header('X-Runtime'); } } }, server => sub { my $port = shift; use TestApp; Dancer::Config->load; set( environment => 'production', apphandler => 'PSGI', port => $port, startup_info => 0, plack_middlewares_map => $confs ); my $app = Dancer::Handler->get_handler()->dance; Plack::Loader->auto( port => $port )->run($app); }, ); libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/05_middlewares.t0000644000175000017500000000264312233013707023701 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; use LWP::UserAgent; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); plan skip_all => "Plack is needed to run this test" unless Dancer::ModuleLoader->load('Plack::Request'); Dancer::ModuleLoader->load('Plack::Loader'); my $confs = [ [ [ ['Runtime'] ] ] ]; plan tests => (2 * scalar @$confs); foreach my $c (@$confs) { Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new( GET => "http://localhost:$port/" ); my $res = $ua->request($req); ok $res; ok $res->header('X-Runtime'); }, server => sub { my $port = shift; use TestApp; Dancer::Config->load; set( environment => 'production', apphandler => 'PSGI', port => $port, startup_info => 0, plack_middlewares => $c->[0] ); my $app = Dancer::Handler->get_handler()->dance; Plack::Loader->auto( port => $port )->run($app); }, ); } libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/03_psgi_app.t0000644000175000017500000000260312233013707023175 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed to run this test" unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => "Plack is needed to run this test" unless Dancer::ModuleLoader->load('Plack::Request'); use LWP::UserAgent; Dancer::ModuleLoader->load('Plack::Loader'); my $app = Dancer::Handler->psgi_app; plan tests => 3; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $res = $ua->get("http://127.0.0.1:$port/env"); like $res->content, qr/psgi\.version/, 'content looks good for /env'; $res = $ua->get("http://127.0.0.1:$port/name/bar"); like $res->content, qr/Your name: bar/, 'content looks good for /name/bar'; $res = $ua->get("http://127.0.0.1:$port/name/baz"); like $res->content, qr/Your name: baz/, 'content looks good for /name/baz'; }, server => sub { my $port = shift; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestApp; use Dancer; set apphandler => 'PSGI', environment => 'production'; Dancer::Config->load; Plack::Loader->auto(port => $port)->run($app); }, ); libdancer-perl-1.3120+dfsg.orig/t/07_apphandlers/06_debug.t0000644000175000017500000000115012233013020022444 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::ModuleLoader; plan skip_all => "Test::Output is needed for this test" unless Dancer::ModuleLoader->load("Test::Output"); plan tests => 3; use Dancer; set startup_info => false, apphandler => 'Debug'; get '/' => sub { 42 }; my $handler = Dancer::Handler->get_handler; isa_ok $handler, 'Dancer::Handler::Debug'; @ARGV = (GET => '/', 'foo=42'); my $psgi; Test::Output::stdout_like ( sub { $psgi = Dancer->start }, qr{X-Powered-By: Perl Dancer.*42}sm, "output looks good" ); is $psgi->[0], 200, "psgi response is ok"; libdancer-perl-1.3120+dfsg.orig/t/08_session/0000755000175000017500000000000012256332256020076 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/08_session/04_api.t0000644000175000017500000000204512233013020021314 0ustar gregoagregoause Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Session::YAML; plan tests => '4'; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; my $fake_session = bless { foo => 42 }, 'Dancer::Session::YAML'; mock 'Dancer::Session' => method 'get_current_session' => should sub { $fake_session }; mock 'Dancer::Session::YAML' => method 'init' => should sub { 1 }; mock 'Dancer::Session::YAML' => method 'create' => should sub { $fake_session }; mock 'Dancer::Session::YAML' => method 'retrieve' => should sub { $fake_session }; mock 'Dancer::Session::YAML' => method 'flush' => should sub { $fake_session }; mock 'Dancer::Session::YAML' => method 'destroy' => should sub { $fake_session }; ok(set(session => 'YAML'), "set session engine to 'YAML'"); is session('foo'), 42, 'session reader works'; ok session('foo' => 54), 'session writer works'; my $expected = bless { foo => 54 }, 'Dancer::Session::YAML'; is_deeply session(), $expected, "session object is returned when no args is given"; libdancer-perl-1.3120+dfsg.orig/t/08_session/08_simple.t0000644000175000017500000000135112233013020022037 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; plan tests => 6; use Dancer::Session::Simple; my $session = Dancer::Session::Simple->create; isa_ok $session, 'Dancer::Session::Simple'; ok( defined( $session->id ), 'ID is defined' ); is( Dancer::Session::Simple->retrieve('XXX'), undef, "unknown session is not found" ); my $s = Dancer::Session::Simple->retrieve( $session->id ); is_deeply $s, $session, "session is retrieved"; $session->{foo} = 42; $session->flush; $s = Dancer::Session::Simple->retrieve( $s->id ); is_deeply $s, $session, "session is changed on flush"; my $id = $s->id; $s->destroy; $session = Dancer::Session::Simple->retrieve($id); is $session, undef, 'session is destroyed'; libdancer-perl-1.3120+dfsg.orig/t/08_session/01_load.t0000644000175000017500000000007712154122351021474 0ustar gregoagregoause Test::More tests => 1; BEGIN { use_ok 'Dancer::Session' } libdancer-perl-1.3120+dfsg.orig/t/08_session/06_abstract.t0000644000175000017500000000161312233013020022350 0ustar gregoagregoause Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Session::Abstract; plan tests => 8; eval { Dancer::Session::Abstract->retrieve }; like $@, qr{not implemented}, "retrieve is a virtual method"; eval { Dancer::Session::Abstract->create }; like $@, qr{not implemented}, "create is a virtual method"; eval { Dancer::Session::Abstract->flush }; like $@, qr{not implemented}, "flush is a virtual method"; eval { Dancer::Session::Abstract->destroy }; like $@, qr{not implemented}, "destroy is a virtual method"; my $s = Dancer::Session::Abstract->new; isa_ok $s, 'Dancer::Session::Abstract'; ok(defined($s->id), "id is defined"); is $s->session_name, 'dancer.session', "default name is dancer.session"; setting session_name => "foo_session"; $s = Dancer::Session::Abstract->new; is $s->session_name, 'foo_session', 'setting session_name is used'; libdancer-perl-1.3120+dfsg.orig/t/08_session/09_session.t0000644000175000017500000000042312233013020022231 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Session; plan tests => 3; my $session = Dancer::Session->init('Simple', {}); ok $session; is_deeply($session, Dancer::Session->engine); ok my $session_desc = Dancer::Session->get_current_session; libdancer-perl-1.3120+dfsg.orig/t/08_session/14_session_domain.t0000644000175000017500000000134712233013710023570 0ustar gregoagregoa#!/usr/bin/env perl use strict; use warnings; use Dancer ':syntax', ':tests'; use Dancer::Session::Simple; use Test::More tests => 2; my $Session_Name = Dancer::Session::Simple->session_name; note "session_domain off"; { set session => "simple"; session foo => "bar"; my $session_cookie = Dancer::Cookies->cookies->{ $Session_Name }; ok !$session_cookie->domain; } note "session_domain on"; { delete Dancer::Cookies->cookies->{ $Session_Name }; my $test_domain = '.test-domain.com'; set session => "simple"; set session_domain => $test_domain; session up => "down"; my $session_cookie = Dancer::Cookies->cookies->{ $Session_Name }; is $session_cookie->domain => $test_domain; } libdancer-perl-1.3120+dfsg.orig/t/08_session/000_create_fake_env.t0000644000175000017500000000052412233013020023720 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/08_session/13_session_httponly.t0000644000175000017500000000377412233013710024207 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::ModuleLoader; use Dancer; use Dancer::Cookie; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); plan skip_all => "YAML is needed for this test" unless Dancer::ModuleLoader->load("YAML"); plan tests => 3 * 3; use LWP::UserAgent; use File::Path 'rmtree'; use Dancer::Config; my $session_dir = path( Dancer::Config::settings->{appdir}, "sessions_$$" ); set session_dir => $session_dir; for my $setting ("default", "on", "off") { Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(GET => "http://127.0.0.1:$port/set_session/test_13"); my $res = $ua->request($req); ok $res->is_success, 'req is success'; my $cookie = $res->header('Set-Cookie'); ok $cookie, 'cookie is set'; if ($setting eq "on" || $setting eq "default") { my ($httponly) = ($cookie =~ /HttpOnly/); ok $httponly, 'httponly is present in cookie'; } else { my ($httponly) = ($cookie =~ /HttpOnly/); ok !$httponly, 'httponly is not present in cookie'; } }, server => sub { my $port = shift; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestApp; Dancer::Config->load; setting session => 'YAML'; if ($setting eq "on") { setting session_is_http_only => 1; } elsif ($setting eq "off") { setting session_is_http_only => 0; } set( environment => 'production', port => $port, startup_info => 0 ); Dancer->dance(); }, ); } # clean up after ourselves rmtree($session_dir); libdancer-perl-1.3120+dfsg.orig/t/08_session/12_session_name.t0000644000175000017500000000152412233013020023226 0ustar gregoagregoa#!/usr/bin/env perl use strict; use warnings; use Test::More tests => 7; use Dancer ':syntax', ':tests'; set session => "simple"; note "changing session name"; { my $orig_name = setting("session_name"); session foo => "bar"; is session("foo"), "bar"; set session_name => "something.else"; is setting("session_name"), "something.else", "session_name changed"; isnt session("foo"), "bar", "other session's values not seen"; session up => "down"; is session("up"), "down", "storing our values"; set session_name => $orig_name; is setting("session_name"), $orig_name, "set back to the original name"; isnt session("up"), "down", "other session's values not seen"; is session("foo"), "bar", "original value restored"; } libdancer-perl-1.3120+dfsg.orig/t/08_session/10_filter.t0000644000175000017500000000061712233013710022036 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass'], tests => 2; use Dancer ':syntax'; use Dancer::Test; hook before => sub { my $data = session; #warn "on a $data"; #redirect '/nonexistent' #unless session || request->path =~ m{/login}sxm; }; get '/login' => sub { '/login'; }; route_exists [ GET => '/login' ]; response_status_is [ GET => '/login' ] => 200, libdancer-perl-1.3120+dfsg.orig/t/08_session/03_http_requests.t0000644000175000017500000000422312233013710023462 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; BEGIN { use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => 'YAML is needed to run this test' unless Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); } use LWP::UserAgent; use File::Spec; my $tempdir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); use Dancer; use Dancer::Logger; my @clients = qw(one two three); my @engines = qw(YAML); if ($ENV{DANCER_TEST_COOKIE}) { push @engines, "cookie"; setting(session_cookie_key => "secret/foo*@!"); } plan tests => 3 * scalar(@clients) * scalar(@engines) + (scalar(@engines)); foreach my $engine (@engines) { Test::TCP::test_tcp( client => sub { my $port = shift; foreach my $client (@clients) { my $ua = LWP::UserAgent->new; $ua->cookie_jar({ file => "$tempdir/.cookies.txt" }); my $res = $ua->get("http://127.0.0.1:$port/read_session"); like $res->content, qr/name=''/, "empty session for client $client"; $res = $ua->get("http://127.0.0.1:$port/set_session/$client"); ok($res->is_success, "set_session for client $client"); $res = $ua->get("http://127.0.0.1:$port/read_session"); like $res->content, qr/name='$client'/, "session looks good for client $client"; } File::Temp::cleanup(); }, server => sub { my $port = shift; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestApp; Dancer::Config->load; setting appdir => $tempdir; Dancer::Logger->init('File'); ok(setting(session => $engine), "using engine $engine"); set( show_errors => 1, startup_info => 0, environment => 'production', port => $port ); Dancer->dance(); }, ); } libdancer-perl-1.3120+dfsg.orig/t/08_session/02_dependency_check.t0000644000175000017500000000252112233013710024021 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 5; use Dancer ':syntax'; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; { # checking that EasyMocker works mock 'My::SuperModule' => method 'method' => should sub { ok( 1, 'EasyMocker mocked a method' ) }; mock 'My::SuperModule' => method 'new_method' => should sub { 'blech' }; eval { My::SuperModule->method }; if ( !$@ ) { is( My::SuperModule->new_method, 'blech', 'Mocked method is good' ); } else { ok( 0, 'Method mocking failed' ); } } my $mock_loads = { }; mock 'Dancer::ModuleLoader' => method 'load' => should sub { $mock_loads->{ $_[1] } }; mock 'Dancer::Session::YAML' => method 'new' => should sub {1}; # when YAML is not here... $mock_loads->{'Dancer::Session::YAML'} = 0; eval { set(session => 'YAML') }; like($@, qr/unable to load session engine 'YAML'/, "the YAML session engine depends on YAML"); # when present, I CAN HAZ $mock_loads->{'Dancer::Session::YAML'} = 1; eval { set(session => 'YAML') }; is($@, '', "the session engine can be set with CGI::Session"); # load an unknown session engine eval { set(session => 'galactica') }; like $@, qr/unable to load session engine 'galactica'/, "Unknown session engine is refused"; libdancer-perl-1.3120+dfsg.orig/t/08_session/11_session_secure.t0000644000175000017500000000124112233013020023567 0ustar gregoagregoa#!/usr/bin/env perl use strict; use warnings; use Dancer ':syntax', ':tests'; use Dancer::Session::Simple; use Test::More tests => 2; my $Session_Name = Dancer::Session::Simple->session_name; note "session_secure off"; { set session => "simple"; session foo => "bar"; my $session_cookie = Dancer::Cookies->cookies->{ $Session_Name }; ok !$session_cookie->secure; } note "session_secure on"; { delete Dancer::Cookies->cookies->{ $Session_Name }; set session => "simple"; set session_secure => 1; session up => "down"; my $session_cookie = Dancer::Cookies->cookies->{ $Session_Name }; ok $session_cookie->secure; } libdancer-perl-1.3120+dfsg.orig/t/08_session/05_yaml.t0000644000175000017500000000347012233013710021517 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; use Dancer::Logger; use File::Path qw(mkpath rmtree); # use t::lib::TestUtils; # use t::lib::EasyMocker; BEGIN { plan skip_all => "need YAML" unless Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 12; use_ok 'Dancer::Session::YAML' } my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir; my $session_dir = path($dir, "sessions_$$"); set session_dir => $session_dir; my $session = Dancer::Session::YAML->create(); isa_ok $session, 'Dancer::Session::YAML'; ok( defined( $session->id ), 'ID is defined' ); is( Dancer::Session::YAML->retrieve('XXX'), undef, "unknown session is not found" ); my $s = Dancer::Session::YAML->retrieve( $session->id ); is_deeply $s, $session, "session is retrieved"; is_deeply( Dancer::Session::YAML->retrieve( $session->id ), $session->retrieve( $session->id ) ); my $yaml_file = $session->yaml_file; like $yaml_file, qr/\.yml$/, 'session file have valid name'; $session->{foo} = 42; $session->flush; $s = Dancer::Session::YAML->retrieve( $s->id ); is_deeply $s, $session, "session is changed on flush"; my $id = $s->id; $s->destroy; $session = Dancer::Session::YAML->retrieve($id); is $session, undef, 'session is destroyed'; ok( -d $session_dir, "session dir was created"); rmtree($session_dir); eval { $session = Dancer::Session::YAML->create() }; my $error = $@; like( $@, qr{Error in tempfile\(\) using .* Parent directory .* does not exist at.*}, 'session dir was not recreated', ); Dancer::Session::YAML->reset(); $session = Dancer::Session::YAML->create(); ok( -d $session_dir, "session dir was recreated"); libdancer-perl-1.3120+dfsg.orig/t/08_session/07_session_expires.t0000644000175000017500000000420312233013710023774 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; # Freeze time! Now we can precalculate expiration times. # This has to come before Dancer loads. my $Time = 1302483506; BEGIN { *CORE::GLOBAL::time = sub () { return $Time }; } use Dancer::ModuleLoader; use Dancer; use Dancer::Cookie; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); plan skip_all => "YAML is needed for this test" unless Dancer::ModuleLoader->load("YAML"); plan tests => 8; use LWP::UserAgent; use File::Path 'rmtree'; use Dancer::Config; my %tests = ( 42 => 'Mon, 11-Apr-2011 00:59:08 GMT', "+36h" => 'Tue, 12-Apr-2011 12:58:26 GMT', ); my $session_dir = path( Dancer::Config::settings->{appdir}, "sessions_$$" ); set session_dir => $session_dir; for my $session_expires (keys %tests) { my $cookie_expires = $tests{$session_expires}; note "Translate from $session_expires"; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(GET => "http://127.0.0.1:$port/set_session/test"); my $res = $ua->request($req); ok $res->is_success, 'req is success'; my $cookie = $res->header('Set-Cookie'); ok $cookie, 'cookie is set'; my ($expires) = ($cookie =~ /expires=(.*?);/); ok $expires, 'expires is present in cookie'; is $expires, $cookie_expires, 'expire date is correct'; }, server => sub { my $port = shift; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestApp; Dancer::Config->load; set( session => 'YAML', session_expires => $session_expires, environment => 'production', port => $port, startup_info => 0 ); Dancer->dance(); }, ); } # clean up after ourselves rmtree($session_dir); libdancer-perl-1.3120+dfsg.orig/t/manifest.t0000644000175000017500000000040512233013020020052 0ustar gregoagregoause strict; use warnings; use Test::More; unless ( $ENV{RELEASE_TESTING} ) { plan( skip_all => "Author tests not required for installation" ); } eval "use Test::CheckManifest 0.9"; plan skip_all => "Test::CheckManifest 0.9 required" if $@; ok_manifest(); libdancer-perl-1.3120+dfsg.orig/t/22_hooks/0000755000175000017500000000000012256332256017532 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/22_hooks/05_layout.t0000644000175000017500000000120412233013020021511 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; plan tests => 6; my $time = localtime(); ok( hook before_layout_render => sub { my $tokens = shift; $tokens->{time} = $time; } ); ok( hook after_layout_render => sub { my $full_content = shift; like $$full_content, qr/start/; like $$full_content, qr/stop/; } ); set views => path( 't', '22_hooks', 'views' ); set layout => 'main'; get '/' => sub { template 'index', { foo => 'baz' }; }; route_exists [ GET => '/' ]; response_content_like( [ GET => '/' ], qr/start $time/ ); libdancer-perl-1.3120+dfsg.orig/t/22_hooks/views/0000755000175000017500000000000012256332256020667 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/22_hooks/views/index.tt0000644000175000017500000000002112233013020022314 0ustar gregoagregoafoo => <% foo %> libdancer-perl-1.3120+dfsg.orig/t/22_hooks/views/layouts/0000755000175000017500000000000012256332256022367 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/22_hooks/views/layouts/main.tt0000644000175000017500000000004312233013020023635 0ustar gregoagregoastart <% time %> <% content %>stop libdancer-perl-1.3120+dfsg.orig/t/22_hooks/11_error_in_hook.t0000644000175000017500000000237712233013710023052 0ustar gregoagregoause strict; use warnings; use Test::More tests => 10, import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; hook before_template => sub { status 500; halt({error => "This is some error"}); }; set views => path( 't', '22_hooks', 'views' ); get '/' => sub { template 'index', { foo => 'baz' }; }; route_exists [ GET => '/' ]; response_content_like( [ GET => '/' ], qr/Unable to process your query/ ); response_status_is( [ GET => '/' ], 500 => "We get a 500 status" ); my $var = 5; ok( hook ( after => sub { $var = 42; } ), 'after hook is defined' ); get '/error' => sub { send_error "FAIL"; # should not be executed fail("This code should not be executed (1)"); }; route_exists [ GET => '/error' ]; response_status_is( [ GET => '/error' ], 500 => "We get a 500 status" ); is ($var, 42, "The after hook were called even after a send error"); get '/halt_me' => sub { halt({error => "This is some error"}); # should not be executed fail("This code should not be executed (2)"); }; $var = 5; route_exists [ GET => '/halt_me' ]; response_status_is( [ GET => '/halt_me' ], 500 => "We get a 200 status" ); is ($var, 5, "The after hook is bypassed if in a 'halt' state, as it was before version 1.3080"); libdancer-perl-1.3120+dfsg.orig/t/22_hooks/10_error_in_hook.t0000644000175000017500000000067712233013710023052 0ustar gregoagregoause strict; use warnings; use Test::More tests => 3, import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; hook before_template => sub { die "plop"; }; set views => path( 't', '22_hooks', 'views' ); get '/' => sub { template 'index', { foo => 'baz' }; }; route_exists [ GET => '/' ]; response_content_like( [ GET => '/' ], qr/Unable to process your query/ ); response_status_is( [ GET => '/' ], 500 => "We get a 500 status" ); libdancer-perl-1.3120+dfsg.orig/t/22_hooks/09_before_error_init.t0000644000175000017500000000067212233013710023714 0ustar gregoagregoause strict; use warnings; use lib '../../lib'; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; plan tests => 3; get '/' => sub { die 'ouch!'; }; route_exists [ GET => '/' ]; response_status_is( [ GET => '/' ], 500 ); hook before_error_init => sub { my $error = shift; $error->{code} = 555; $error->{title} = 'foo'; $error->{message} = 'bar'; }; response_status_is( [ GET => '/' ], 555 ); libdancer-perl-1.3120+dfsg.orig/t/22_hooks/02_before.t0000644000175000017500000000300112233013710021436 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; plan tests => 15; my $i = 0; ok( hook (before => sub { content_type('text/xhtml'); } ) ); ok( hook(before=> sub { if ( request->path_info eq '/redirect_from' ) { redirect('/redirect_to'); } else { params->{number} = 42; var notice => "I am here"; request->path_info('/'); } } ), 'before filter is defined' ); get( '/' => sub { is( params->{number}, 42, "params->{number} is set" ); is( "I am here", vars->{notice}, "vars->{notice} is set" ); return 'index'; } ); get( '/redirect_from' => sub { $i++; } ); route_exists [ GET => '/' ]; response_status_is [ GET => '/' ] => 200; my $path = '/somewhere'; my $request = [ GET => $path ]; route_doesnt_exist $request, "there is no route handler for $path..."; response_status_is $request => 200, "...but a response is returned though"; response_content_is $request, 'index', "which is the result of a redirection to /"; response_headers_are_deeply [ GET => '/redirect_from' ], [ 'Location' => 'http://localhost/redirect_to', 'Content-Type' => 'text/xhtml', 'Server' => "Perl Dancer ${Dancer::VERSION}", 'X-Powered-By' => "Perl Dancer ${Dancer::VERSION}", ]; is $i, 0, 'never gone to redirect_from'; libdancer-perl-1.3120+dfsg.orig/t/22_hooks/07_file.t0000644000175000017500000000173412233013710021133 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; use Dancer::FileUtils 'read_glob_content'; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 5; my $dir = File::Temp::tempdir( CLEANUP => 1 ); setting public => $dir; open my $fh, '>', File::Spec->catfile( $dir, 'test.txt' ); print $fh "this is content"; close $fh; ok( hook 'before_file_render' => sub { my $file_path = shift; $file_path =~ s/foo/test.txt/; } ); ok( hook 'after_file_render' => sub { my $response = shift; is $response->header('Content-Type'), 'text/plain'; $response->header( 'Content-Type' => 'text/tests' ); } ); get '/' => sub { send_file('test.txt') }; my $response = dancer_response( GET => '/' ); is read_glob_content( $response->content ), 'this is content'; is $response->header('Content-Type'), 'text/tests'; libdancer-perl-1.3120+dfsg.orig/t/22_hooks/04_template.t0000644000175000017500000000140612233013710022020 0ustar gregoagregoause strict; use warnings; use Test::More tests => 7, import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; use Time::HiRes qw/gettimeofday tv_interval/; my ($t0, $elapsed); ok( hook before_template => sub { my $tokens = shift; $tokens->{foo} = 'bar'; $t0 = [gettimeofday]; } ); ok( hook after_template_render => sub { my $full_content = shift; like $$full_content, qr/foo => bar/; my ( undef, $end ) = gettimeofday(); $elapsed = tv_interval($t0); } ); setting views => path( 't', '22_hooks', 'views' ); get '/' => sub { template 'index', { foo => 'baz' }; }; route_exists [ GET => '/' ]; response_content_like( [ GET => '/' ], qr/foo => bar/ ); ok $elapsed; cmp_ok $elapsed, '>', 0; libdancer-perl-1.3120+dfsg.orig/t/22_hooks/01_api.t0000644000175000017500000000227412233013020020751 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; plan tests => 10; my $cpt = 0; ok( hook( 'before' => sub { $cpt += shift || 1 }), 'add a before filter'); my $app = Dancer::App->current->name; is scalar @{ Dancer::Factory::Hook->instance->get_hooks_for('before') }, 1, 'got one before filter'; my $hooks = Dancer::Factory::Hook->instance->get_hooks_for('before'); is scalar @$hooks, 1, 'got one before filter'; Dancer::Factory::Hook->instance->execute_hooks('before'); is $cpt, 1, 'execute hooks without args'; Dancer::Factory::Hook->instance->execute_hooks( 'before', 2 ); is $cpt, 3, 'execute hooks with one arg'; sub exception (&) { eval { $_[0]->() }; return $@ } ok( hook('before' => sub { $cpt += 2; undef $_ }), 'add a bad filter that manipulates $_' ); $cpt = 0; is(exception { Dancer::Factory::Hook->instance->execute_hooks('before', 5) }, '', 'execute_hooks() lives with bad hooks'); is($cpt, 7, 'execute hooks with one arg, ok result'); $cpt = 0; is(exception { Dancer::Factory::Hook->instance->execute_hooks('before', 8) }, '', 'execute_hooks() lives second time with bad hooks'); is($cpt, 10, 'execute hooks with one arg, ok result'); libdancer-perl-1.3120+dfsg.orig/t/22_hooks/06_serializer.t0000644000175000017500000000330012233013020022345 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; use Time::HiRes qw/gettimeofday/; plan skip_all => "JSON is needed to run this tests" unless Dancer::ModuleLoader->load('JSON'); set serializer => 'JSON'; plan tests => 11; my $body = '{"foo":"bar"}'; ok( hook( before_deserializer => sub { my $request = Dancer::SharedData->request; if ($request->is_put){ like $request->body, qr/foo/, 'content from PUT is valid'; } } ), 'hook for before_serializer', ); ok( hook( after_deserializer => sub { my $request = Dancer::SharedData->request; if ( $request->is_put ) { is $request->params->{foo}, 'bar', 'content from request is ok'; } } ), 'hook for after_deserializer' ); ok( hook( before_serializer => sub { my $response = shift; my ( undef, $start ) = gettimeofday; $response->content->{start_time} = $start; } ), 'hook for before_serializer' ); ok( hook( after_serializer => sub { my $response = shift; like $response->content, qr/\"start_time\" :/, 'content is ok inside hook'; } ), 'hook for after_serializer' ); get '/' => sub { { foo => 1 } }; put '/' => sub { { foo => 1 } }; route_exists [ GET => '/' ], 'route exists'; response_content_like( [ GET => '/' ], qr/start_time/, 'content is ok' ); my $response = dancer_response( PUT => '/', { body => $body, headers => [ 'Content-Type' => 'application/json' ] } ); like $response->content, qr/start_time/, 'content is ok'; libdancer-perl-1.3120+dfsg.orig/t/22_hooks/00_syntax.t0000644000175000017500000000105612233013710021530 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; plan tests => 4; ok( hook(before => sub { 'block before' } ), 'add a before filter' ); ok( hook(after => sub { 'block after' } ), 'add an after filter' ); ok( hook(before_template=> sub { 'block before_template' } ), 'add a before_template filter' ); eval { hook( 'before', 'This is not a CodeRef' ), }; like($@, qr/the code argument passed to hook construction was not a CodeRef. Value was : 'This is not a CodeRef' at/, 'a non coderef is properly caught'); libdancer-perl-1.3120+dfsg.orig/t/22_hooks/08_error.t0000644000175000017500000000076712233013020021345 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; plan tests => 5; my $i = 0; ok( hook 'before_error_render' => sub { my $error = shift; is $error->code, 404; $i++; } ); ok( hook 'after_error_render' => sub { my $response = shift; is $response->status, 404; $i++; } ); get '/' => sub { send_error("fake error", 404); }; my $response = dancer_response( GET => '/' ); is $i, 2; libdancer-perl-1.3120+dfsg.orig/t/22_hooks/03_after.t0000644000175000017500000000065012233013710021305 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; plan tests => 3; ok( hook(after => sub { my $response = shift; $response->content('not index!'); } ), 'after hook is defined' ); get( '/' => sub { return 'index'; } ); route_exists [ GET => '/' ]; response_content_is( [ GET => '/' ], 'not index!' ); libdancer-perl-1.3120+dfsg.orig/t/21_dependents/0000755000175000017500000000000012256332256020537 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/21_dependents/Dancer-Session-Cookie.t0000755000175000017500000000414412233013710024740 0ustar gregoagregoa#!/usr/bin/env perl use strict; use warnings; use Dancer::ModuleLoader; use Test::More import => ['!pass']; plan skip_all => "Dancer::Session::Cookie 0.14 required" unless Dancer::ModuleLoader->load( 'Dancer::Session::Cookie', '0.14' ); plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP required" unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); Test::TCP->import; plan skip_all => "HTTP::Cookies required" unless Dancer::ModuleLoader->load('HTTP::Cookies'); HTTP::Cookies->import; plan tests=> 7; test_tcp( client => sub { my $port = shift; require LWP::UserAgent; require HTTP::Cookies; my $ua = LWP::UserAgent->new; # Simulate two different browsers with two different jars my @jars = (HTTP::Cookies->new, HTTP::Cookies->new); for my $jar (@jars) { $ua->cookie_jar( $jar ); my $res = $ua->get("http://0.0:$port/foo"); is $res->content, "hits: 0, last_hit: "; $res = $ua->get("http://0.0:$port/bar"); is $res->content, "hits: 1, last_hit: foo"; $res = $ua->get("http://0.0:$port/baz"); is $res->content, "hits: 2, last_hit: bar"; } $ua->cookie_jar($jars[0]); my $res = $ua->get("http://0.0:$port/wibble"); is $res->content, "hits: 3, last_hit: baz", "session not overwritten"; }, server => sub { my $port = shift; use Dancer ':tests'; set( port => $port, appdir => '', # quiet warnings not having an appdir startup_info => 0, # quiet startup banner session_cookie_key => "John has a long mustache", session => "cookie" ); get "/*" => sub { my $hits = session("hit_counter") || 0; my $last = session("last_hit") || ''; session hit_counter => $hits + 1; session last_hit => (splat)[0]; return "hits: $hits, last_hit: $last"; }; dance; } ); libdancer-perl-1.3120+dfsg.orig/t/13_engines/0000755000175000017500000000000012256332256020037 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/13_engines/02_template_init.t0000644000175000017500000000112212233013020023333 0ustar gregoagregoause Test::More tests => 6; use strict; use warnings; use Dancer::Template; my $config = { engines => { simple => { start_tag => '[%', stop_tag => '%]', }, }, }; my $e; eval { $e = Dancer::Template->init() }; is $@, '', 'init a template without agrs'; is $e->name, 'simple', 'name is read'; is_deeply $e->config, {}, 'default settings are set'; $e = Dancer::Template->init('simple', $config); is $e->name, 'simple', 'name is read'; is $e->config->{start_tag}, '[%', 'start_tag is read'; is $e->config->{stop_tag}, '%]', 'stop_tag is read'; libdancer-perl-1.3120+dfsg.orig/t/13_engines/00_load.t0000644000175000017500000000020612233013020021414 0ustar gregoagregoause Test::More tests => 3; use_ok 'Dancer::Engine'; eval { Dancer::Engine->build(); }; ok $@; like $@, qr/cannot build engine/; libdancer-perl-1.3120+dfsg.orig/t/09_cookies/0000755000175000017500000000000012256332256020050 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/09_cookies/04_secure.t0000644000175000017500000000115512233013020022004 0ustar gregoagregoa#!/usr/bin/env perl use strict; use warnings; use Test::More tests => 5; my $CLASS = 'Dancer::Cookie'; use_ok $CLASS; note "not secure"; { my $cookie = $CLASS->new( name => "foo", value => "bar", ); ok !$cookie->secure; my @headers = split /;\s+/, $cookie->to_header; ok !grep { lc $_ eq lc "secure" } @headers; } note "secure cookie"; { my $cookie = $CLASS->new( name => "foo", value => "bar", secure => 1 ); ok $cookie->secure; my @headers = split /;\s+/, $cookie->to_header; ok grep { lc $_ eq lc "secure" } @headers; } libdancer-perl-1.3120+dfsg.orig/t/09_cookies/03_persistence.t0000644000175000017500000000322612233013710023050 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; BEGIN { use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); }; use LWP::UserAgent; use Dancer; use File::Spec; my $tempdir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); plan tests => 9; Test::TCP::test_tcp( client => sub { my $port = shift; foreach my $client (qw(one two three)) { my $ua = LWP::UserAgent->new; $ua->cookie_jar({ file => "$tempdir/.cookies.txt" }); my $res = $ua->get("http://127.0.0.1:$port/cookies"); like $res->content, qr/\$VAR1 = \{\}/, "no cookies found for the client $client"; $res = $ua->get("http://127.0.0.1:$port/set_cookie/$client/42"); # use YAML::Syck; warn Dump $res; ok($res->is_success, "set_cookie for client $client"); $res = $ua->get("http://127.0.0.1:$port/cookies"); like $res->content, qr/'name' => '$client'/, "cookie looks good for client $client"; } File::Temp::cleanup(); }, server => sub { my $port = shift; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestApp; Dancer::Config->load; set( startup_info => 0, environment => 'production', port => $port ); Dancer->dance(); }, ); libdancer-perl-1.3120+dfsg.orig/t/09_cookies/05_api.t0000644000175000017500000000530512233013710021277 0ustar gregoagregoause Test::More import => ['!pass']; use Dancer ':syntax'; my @tests = ( { name => 'foo', value => 42 , opts => {}}, { name => 'foo', value => 42 , opts => { http_only => 1 } }, { name => 'msg', value => 'hello; world', opts => {} }, { name => 'msg', value => 'hello; world', opts => { http_only => 0 } }, ); plan tests => scalar (@tests * 5) + 12; is_deeply(cookies, {}, "cookies() return a hashref"); foreach my $test (@tests) { ok(set_cookie($test->{name} => $test->{value}, %{$test->{opts}}), "set_cookie"); my $c = cookies->{$test->{name}}; ok defined($c), "cookie found"; is $c->name, $test->{name}, "name is ".$test->{value}; is $c->value, $test->{value}, "value is ".$test->{value}; is $c->http_only, (exists($test->{opts}{http_only}) ? $test->{opts}{http_only} : undef), "HttpOnly is correctly set"; } { my $values = { token => 'foo', token_secret => 'bar' }; ok my $c = Dancer::Cookie->new( name => 'complex', value => $values, ); subtest "cookie header" => sub { plan tests => 2; ok $c->to_header =~ /^complex=([^;]+);/, "cookie name"; my %cookie_values = split '&', $1; is_deeply \%cookie_values => $values, "cookie values"; }; } my $env = { REQUEST_METHOD => 'GET', SCRIPT_NAME => '/', COOKIE => 'complex=token&foo&token_secret&bar', }; my $request = Dancer::Request->new(env => $env); Dancer::SharedData->request($request); ok(Dancer::Cookies->init, "Dancer::Cookies->init"); my $cookies = Dancer::Cookies->cookies; my %values = $cookies->{complex}->value; is $values{token}, 'foo'; is $values{token_secret}, 'bar'; is cookie(answer => 42, path => 'dtc'), 42, "cookie set"; is cookie('answer'), 42, "cookie get"; is cookies->{answer}->path, 'dtc', "cookie option correctly set"; is cookie('zorglub'), undef, "unknown cookie"; ### test for im0 $env = { REQUEST_METHOD => 'GET', SCRIPT_NAME => '/', HTTP_COOKIE => 'dancer.session=1209039; fbs_102="access_token=xxxxxxxxxx%7Cffffff"', }; $request = Dancer::Request->new(env => $env); Dancer::SharedData->request($request); Dancer::Cookies->init; $cookies = Dancer::Cookies->cookies; like $cookies->{fbs_102}->value, qr/access_token\=/; # Test for undef cookie values from technically invalid cookies issue #782 eval { use warnings FATAL => qw( all ); $env = { REQUEST_METHOD => 'GET', SCRIPT_NAME => '/', HTTP_COOKIE => 'invalid_cookie=1,2,3', }; $request = Dancer::Request->new(env => $env); Dancer::SharedData->request($request); Dancer::Cookies->init; }; unlike($@, qr/Use of uninitialized value in string/, 'undef or invalid cookies are quietly ignored'); libdancer-perl-1.3120+dfsg.orig/t/09_cookies/01_use.t0000644000175000017500000000007612154122352021323 0ustar gregoagregoause Test::More tests => 1; BEGIN { use_ok 'Dancer::Cookie' } libdancer-perl-1.3120+dfsg.orig/t/09_cookies/000_create_fake_env.t0000644000175000017500000000052412233013020023672 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/09_cookies/02_cookie_object.t0000644000175000017500000000216512233013020023315 0ustar gregoagregoause strict; use warnings; use Test::More tests => 6; use Dancer::Cookie; my $c = Dancer::Cookie->new( name => 'dancer.slot', value => 42 ); is(ref($c), 'Dancer::Cookie', "object of class Dancer::Cookie"); is($c->to_header, 'dancer.slot=42; path=/; HttpOnly', "simple cookie header looks good"); $c = Dancer::Cookie->new( name => 'dancer.slot', value => 42, domain => 'http://foo.com', ); is( $c->to_header, 'dancer.slot=42; path=/; domain=http://foo.com; HttpOnly', "header with domain looks good" ); $c = Dancer::Cookie->new( name => 'dancer.slot', value => 42, expires => 'test', ); is( $c->to_header, 'dancer.slot=42; path=/; expires=test; HttpOnly', "header with invalid expires looks good", ); $c = Dancer::Cookie->new( name => 'msg', value => 'hello; world', ); is( $c->to_header, 'msg=hello%3B%20world; path=/; HttpOnly', "headers are uri encoded" ); $c = Dancer::Cookie->new( name => 'msg', value => 'hello; world', http_only => 0, ); is( $c->to_header, 'msg=hello%3B%20world; path=/', "headers are uri encoded" ); libdancer-perl-1.3120+dfsg.orig/t/09_cookies/06_expires.t0000644000175000017500000000344412233013020022202 0ustar gregoagregoause strict; use warnings; use Test::More; BEGIN { # Freeze time at Tue, 15-Jun-2010 00:00:00 GMT *CORE::GLOBAL::time = sub { return 1276560000 } } use Dancer::Cookie; my $min = 60; my $hour = 60 * $min; my $day = 24 * $hour; my $week = 7 * $day; my $mon = 30 * $day; my $year = 365 * $day; note "expiration times"; { my %times = ( "+2h" => "Tue, 15-Jun-2010 02:00:00 GMT", "-2h" => "Mon, 14-Jun-2010 22:00:00 GMT", "1 hour" => "Tue, 15-Jun-2010 01:00:00 GMT", "3 weeks 4 days 2 hours 99 min 0 secs" => "Sat, 10-Jul-2010 03:39:00 GMT", "2 months" => "Sat, 14-Aug-2010 00:00:00 GMT", "12 years" => "Sun, 12-Jun-2022 00:00:00 GMT", 1288817656 => "Wed, 03-Nov-2010 20:54:16 GMT", 1288731256 => "Tue, 02-Nov-2010 20:54:16 GMT", 1288644856 => "Mon, 01-Nov-2010 20:54:16 GMT", 1288558456 => "Sun, 31-Oct-2010 20:54:16 GMT", 1288472056 => "Sat, 30-Oct-2010 20:54:16 GMT", 1288385656 => "Fri, 29-Oct-2010 20:54:16 GMT", 1288299256 => "Thu, 28-Oct-2010 20:54:16 GMT", 1288212856 => "Wed, 27-Oct-2010 20:54:16 GMT", # Anything not understood is passed through "basset hounds got long ears" => "basset hounds got long ears", ); for my $exp (keys %times) { my $want = $times{$exp}; note $want; my $cookie = Dancer::Cookie->new( name => "shut.up.and.dance", value => "FMV", expires => $exp ); is($cookie->to_header, "shut.up.and.dance=FMV; path=/; expires=$want; HttpOnly", "header with expires"); is $cookie->expires, $want, "expires"; } } done_testing; libdancer-perl-1.3120+dfsg.orig/t/24_deployment/0000755000175000017500000000000012256332256020571 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/24_deployment/01_multi_webapp.t0000644000175000017500000000341612233013710023734 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; BEGIN { use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed to run this test" unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => "Plack is needed to run this test" unless Dancer::ModuleLoader->load('Plack::Builder'); } use Dancer; use Plack::Builder; use LWP::UserAgent; use HTTP::Server::Simple::PSGI; plan tests => 100; Test::TCP::test_tcp( client => sub { my $port = shift; my @apps = (qw/app1 app2/); my $ua = LWP::UserAgent->new(); for(1..100){ my $app = $apps[int(rand(scalar @apps - 1))]; my $req = HTTP::Request->new(GET => "http://127.0.0.1:$port/$app"); my $res = $ua->request($req); like $res->content, qr/Hello $app/; } }, server => sub { my $port = shift; my $app1 = sub { my $env = shift; Dancer::App->set_running_app('APP1'); get "/" => sub { return "Hello app1"; }; my $request = Dancer::Request->new(env => $env); Dancer->dance($request); }; my $app2 = sub { my $env = shift; Dancer::App->set_running_app('APP2'); get "/" => sub { return "Hello app2"; }; my $request = Dancer::Request->new(env => $env); Dancer->dance($request); }; my $app = builder { mount "/app1" => builder {$app1}; mount "/app2" => builder {$app2}; }; my $server = HTTP::Server::Simple::PSGI->new($port); $server->host("127.0.0.1"); $server->app($app); $server->run; }, ); libdancer-perl-1.3120+dfsg.orig/t/lib/0000755000175000017500000000000012256332256016652 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/lib/TestApp.pm0000644000175000017500000000310412233013710020550 0ustar gregoagregoapackage TestApp; use Dancer; use Data::Dumper; use LinkBlocker; block_links_from "www.foo.com"; get '/' => sub { "Hello, this is the home" }; get '/hash' => sub { { a => 1, b => 2, c => 3} }; get '/with_headers' => sub { header 'X-Foo-Dancer' => 42; 1; }; get '/headers_again' => sub { request->header('X-Foo-Dancer') }; get '/test_app_setting' => sub { return { onlyroot => setting('onlyroot'), foo => setting('foo'), onlyapp => setting('onlyapp') }; }; get '/name/:name' => sub { "Your name: ".params->{name} }; post '/params/:var' => sub { Dumper({ params => scalar(params), route => { params('route') }, query => { params('query') }, body => { params('body') } }); }; post '/name' => sub { "Your name: ".params->{name} }; get '/env' => sub { Dumper(Dancer::SharedData->request) }; get '/cookies' => sub { Dumper(cookies()) }; get '/set_cookie/*/*' => sub { my ($name, $value) = splat; set_cookie $name => $value; }; get '/set_session/*' => sub { my ($name) = splat; session name => $name; }; get '/read_session' => sub { my $name = session('name') || ''; "name='$name'" }; put '/jsondata' => sub { request->body; }; post '/form' => sub { params->{foo}; }; get '/unicode' => sub { "cyrillic shcha \x{0429}", }; get '/forward_to_unavailable_route' => sub { forward "/some_route_that_does_not_exist" }; get '/issues/499/true' => sub { "OK" if system('true') == 0 }; get '/issues/499/false' => sub { "OK" if system('false') != 0 }; true; libdancer-perl-1.3120+dfsg.orig/t/lib/TestPlugin2.pm0000644000175000017500000000030412233013020021341 0ustar gregoagregoapackage TestPlugin2; use strict; use warnings; use Dancer ':syntax'; use Dancer::Plugin; use base qw(Data::Dumper); register some_other_plugin_keyword => sub { 42; }; register_plugin; 1; libdancer-perl-1.3120+dfsg.orig/t/lib/LinkBlocker.pm0000644000175000017500000000076112233013710021375 0ustar gregoagregoapackage LinkBlocker; use Dancer ':syntax'; use Dancer::Plugin; register block_links_from => sub { my ($host) = @_; hook before => sub { if (request->referer && request->referer =~ /http:\/\/$host/) { status 403; } }; }; add_hook( 'after', sub { my $response = shift; if ( request->path eq '/test' ) { $response->{content} = 'no content'; $response->{status} = 202; } } ); register_plugin; 1; libdancer-perl-1.3120+dfsg.orig/t/lib/Hookee.pm0000644000175000017500000000035012233013710020402 0ustar gregoagregoapackage t::lib::Hookee; use Dancer::Plugin; register_hook 'start_hookee', 'stop_hookee'; register_hook 'third_hook'; register some_keyword => sub { execute_hook('start_hookee'); }; register_plugin for_versions => [ 2 ]; 1; libdancer-perl-1.3120+dfsg.orig/t/lib/TestUtils.pm0000644000175000017500000000150412233013020021124 0ustar gregoagregoapackage TestUtils; use base 'Exporter'; use vars '@EXPORT'; use File::Path qw(mkpath rmtree); use Dancer::Request; @EXPORT = qw(http_request write_file clean_tmp_files); sub http_request { my ($port, $method, $path) = @_; my $url = "http://localhost:${port}${path}"; my $lwp = LWP::UserAgent->new; my $req = HTTP::Request->new($method => $url); return $lwp->request($req); } sub write_file { my ($file, $content) = @_; open CONF, '>', $file or die "cannot write file $file : $!"; print CONF $content; close CONF; } sub clean_tmp_files { my $appdir = setting('appdir') || File::Spec->tmpdir(); my $logs_dir = File::Spec->catdir($appdir, 'logs'); rmtree($logs_dir) if -d $logs_dir; my $sessions = setting session_dir; rmtree($sessions) if $sessions && -d $sessions; } 1; libdancer-perl-1.3120+dfsg.orig/t/lib/Forum.pm0000644000175000017500000000047512233013710020270 0ustar gregoagregoapackage Forum; use Dancer ':syntax'; use TestPlugin; get '/' => sub { "root" }; get '/index' => sub { 'forum index' }; prefix '/admin'; get '/index' => sub { 'admin index' }; prefix '/users' => sub { get '/list' => sub { 'users list' }; prefix '/mods'; get '/list' => sub { 'mods list' }; }; 1; libdancer-perl-1.3120+dfsg.orig/t/lib/EasyMocker.pm0000644000175000017500000000126612233013020021233 0ustar gregoagregoapackage EasyMocker; # I want an easy to use mocker, with pretty explicit syntax use strict; use warnings; use vars qw(@EXPORT); use base 'Exporter'; @EXPORT = qw(mock should method); # syntax: # use t::lib::EasyMocker; # mock 'My::Class::method' => with sub { }; # or even # mock 'My::Class', 'method' => with sub { }; sub method { @_ } sub should { @_ } my $MOCKS = {}; sub mock { { no strict 'refs'; no warnings 'redefine', 'prototype'; if (@_ == 3) { my ($class, $method, $sub) = @_; *{"${class}::${method}"} = $sub; } else { my ($method, $sub) = @_; *$method = $sub; } } } 1; libdancer-perl-1.3120+dfsg.orig/t/lib/TestAppUnicode.pm0000644000175000017500000000120012233013020022044 0ustar gregoagregoapackage TestAppUnicode; use Dancer; get '/string' => sub { "\x{1A9}"; }; get '/other/string' => sub { forward '/string'; }; get '/param/:param' => sub { params('route')->{'param'}; }; get '/view' => sub { template 'unicode', { pure_token => 'Ʃ', param_token => params->{'string1'}, }; }; get '/form' => sub { debug "params: ".to_json({params()}); debug "utf8 : é-\x{1AC}"; template('unicode', { char => "é-\x{E9}", string1 => params->{'string1'}, token => to_json { 'params' => { request->params} } })."\x{E9} - string1: ".params->{'string1'} }; 1; libdancer-perl-1.3120+dfsg.orig/t/lib/TestPlugin.pm0000644000175000017500000000024112233013020021257 0ustar gregoagregoapackage TestPlugin; use strict; use warnings; use Dancer ':syntax'; use Dancer::Plugin; register some_plugin_keyword => sub { 42; }; register_plugin; 1; libdancer-perl-1.3120+dfsg.orig/t/20_deprecation/0000755000175000017500000000000012256332256020702 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/20_deprecation/01_api.t0000644000175000017500000000301412233013020022112 0ustar gregoagregoause strict; use warnings; use Test::More tests => 5; { package test::dancer::deprecated; use base 'Dancer::Object'; use Dancer::Deprecation; sub foo { Dancer::Deprecation->deprecated( feature => 'foo', version => '0.1', message => 'calling foo is deprecated, you should use bar', ); } sub bar { Dancer::Deprecation->deprecated( 'calling bar is also deprecated, you should use baz'); } sub baz { Dancer::Deprecation->deprecated(); } sub foo_bar_baz { Dancer::Deprecation->deprecated( version => '0.1', feature => 'foo_bar_baz', ); } sub fatal { Dancer::Deprecation->deprecated( message => 'this should die', fatal => 1, ); } } my $warn; local $SIG{__WARN__} = sub { $warn = $_[0] }; my $t = test::dancer::deprecated->new(); $t->foo(); like $warn, qr/calling foo is deprecated, you should use bar since version 0.1/, 'deprecation with feature, message and version'; $warn = undef; $t->bar(); like $warn, qr/test::dancer::deprecated::bar has been deprecated/, 'deprecation with only message'; $warn = undef; $t->baz(); like $warn, qr/test::dancer::deprecated::baz has been deprecated/, 'deprecation with default message'; $warn = undef; $t->foo_bar_baz(); like $warn, qr/foo_bar_baz has been deprecated since version 0.1/, 'deprecation with feature and version'; eval {$t->fatal}; like $@, qr/this should die/; libdancer-perl-1.3120+dfsg.orig/t/11_logger/0000755000175000017500000000000012256332256017664 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/11_logger/08_serialize.t0000644000175000017500000000201012233013710022322 0ustar gregoagregoa# this test makes sure the "console" logger send log messages to STDERR use strict; use warnings; use Test::More import => ['!pass']; plan skip_all => "Test::Output is needed for this test" unless Dancer::ModuleLoader->load('Test::Output'); plan tests => 4; use Dancer ':syntax'; set logger => 'Console'; Test::Output::stderr_like( sub { Dancer::Logger::warning(['a']) }, qr/\[\d+\] warn @.+> \['a'\] in/, 'Arrayref correctly serialized', ); Test::Output::stderr_like( sub { Dancer::Logger::warning( { this => 'that' } ) }, qr/\[\d+\] warn @.+> \{'this' => 'that'\} in/, 'Hashref correctly serialized', ); Test::Output::stderr_like( sub { Dancer::Logger::warning( qw/hello world/ ) }, qr/\[\d+\] warn @.+> helloworld in/, 'Multiple arguments are okay', ); Test::Output::stderr_like( sub { Dancer::Logger::warning( { b => 1, a => 2, e => 3, d => 4, c => 5}) }, qr/\[\d+\] warn @.+> \{'a' => 2,'b' => 1,'c' => 5,'d' => 4,'e' => 3\}/, 'Hash keys are sorted okay', ); libdancer-perl-1.3120+dfsg.orig/t/11_logger/11_runtime_file.t0000644000175000017500000000144412233013710023021 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer; use Dancer::FileUtils; use Dancer::Test; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 3; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $logfile = Dancer::FileUtils::path($dir, "logs", "development.log"); set(environment => 'development', appdir => $dir, log => 'debug', logger => 'file'); get '/' => sub { die "Dieing in route handler - arrggghh!"; }; response_status_is [GET => '/'], 500 => "We get a 500 answer"; ok -f $logfile => "Log file got created"; my $logcontents = Dancer::FileUtils::read_file_content($logfile); like $logcontents => qr/arrggghh!/ => "Log file includes die message"; libdancer-perl-1.3120+dfsg.orig/t/11_logger/10_note.t0000644000175000017500000000117112233013710021300 0ustar gregoagregoause Test::More tests => 6, import => ['!pass']; use strict; use warnings; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; use_ok 'Dancer::Logger::Note'; my $l = Dancer::Logger::Note->new; ok defined($l), 'Dancer::Logger::Note object'; isa_ok $l, 'Dancer::Logger::Note'; can_ok $l, qw(init _log debug warning error info); my $format = $l->format_message('debug', 'test'); like $format, qr/\[\d+\] debug @.+> test in/, "format looks good"; my $noted = 0; mock 'Test::More::note' => sub { $noted++ }; $l->_log( debug => 'Perl Dancer test message' ); ok( $noted, 'Reached note() of Test::More' ); libdancer-perl-1.3120+dfsg.orig/t/11_logger/06_null.t0000644000175000017500000000105512233013710021313 0ustar gregoagregoause Test::More tests => 6, import => ['!pass']; use strict; use warnings; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; use_ok 'Dancer::Logger::Null'; my $l = Dancer::Logger::Null->new; ok defined($l), 'Dancer::Logger::Null object'; isa_ok $l, 'Dancer::Logger::Null'; can_ok $l, qw(_log debug warning error info); my $format = $l->format_message('debug', 'test'); like $format, qr/\[\d+\] debug @.+> test in/, "format looks good"; ok( $l->_log( debug => 'Perl Dancer test message' ), 'Logged msg to Null', ); libdancer-perl-1.3120+dfsg.orig/t/11_logger/04_console.t0000644000175000017500000000211412233013710021776 0ustar gregoagregoa# this test makes sure the "console" logger send log messages to STDERR use strict; use warnings; use Test::More import => ['!pass']; use Dancer::ModuleLoader; use Dancer; plan skip_all => "Test::Output is needed for this test" unless Dancer::ModuleLoader->load('Test::Output'); plan tests => 8; use_ok 'Dancer::Logger::Console'; my $l = Dancer::Logger::Console->new; ok(defined($l), "logger is defined"); isa_ok($l, 'Dancer::Logger::Abstract'); isa_ok($l, 'Dancer::Logger::Console'); Test::Output::stderr_like( sub { $l->debug("debug message") }, qr/\[\d+\] debug @.+> debug message in/, "debug output is sent to STDERR"); Test::Output::stderr_like( sub { $l->warning("warning message") }, qr/\[\d+\] warn @.+> warning message in/, "warning log output is sent to STDERR"); Test::Output::stderr_like( sub { $l->error("error message") }, qr/\[\d+\] error @.+> error message in/, "error output is sent to STDERR"); Test::Output::stderr_like( sub { $l->info("info message") }, qr/\[\d+\] info @.+> info message in/, "info output is sent to STDERR"); libdancer-perl-1.3120+dfsg.orig/t/11_logger/01_abstract.t0000644000175000017500000000131212233013710022133 0ustar gregoagregoause Test::More tests => 28, import => ['!pass']; use strict; use warnings; use Dancer; use Dancer::Logger::Abstract; my @log_levels = qw(core debug info warning error); my $l = Dancer::Logger::Abstract->new; isa_ok $l, 'Dancer::Logger::Abstract'; can_ok $l, (qw(_log _should), @log_levels); eval { $l->_log }; like $@, qr/_log not implemented/, "_log is a virtual method"; my @implemented; for my $level (0 .. $#log_levels) { set log => $log_levels[0]; for my $levels (@log_levels) { eval { $l->$levels("foo") }; like $@ => qr/not implemented/; } for my $levels (@implemented) { is($l->$levels("foo"), ""); } push @implemented => shift @log_levels; } libdancer-perl-1.3120+dfsg.orig/t/11_logger/02_factory.t0000644000175000017500000000153312233013710022005 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use t::lib::TestUtils; use Dancer ':syntax'; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 8; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); setting appdir => $dir; use_ok 'Dancer::Logger'; my $engine = Dancer::Logger->logger; ok !defined($engine), "engine not defined"; eval { Dancer::Logger->init('foo') }; like $@, qr/unable to load logger engine 'foo'/, 'unknown logger engine detected'; ok(Dancer::Logger->init('file'), 'logger file initialized'); $engine = Dancer::Logger->logger; isa_ok $engine, 'Dancer::Logger::File'; foreach my $method (qw(debug warning error)) { ok(Dancer::Logger->$method("test"), "$method works"); } Dancer::Logger::logger->{fh}->close; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/11_logger/07_diag.t0000644000175000017500000000117712233013710021253 0ustar gregoagregoause Test::More tests => 6, import => ['!pass']; use strict; use warnings; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; use_ok 'Dancer::Logger::Diag'; my $l = Dancer::Logger::Diag->new; ok defined($l), 'Dancer::Logger::Diag object'; isa_ok $l, 'Dancer::Logger::Diag'; can_ok $l, qw(init _log debug warning error info); my $format = $l->format_message('debug', 'test'); like $format, qr/\[\d+\] debug @.+> test in/, "format looks good"; my $diagged = 0; mock 'Test::More::diag' => sub { $diagged++ }; $l->_log( debug => 'Perl Dancer test message' ); ok( $diagged, 'Reached diag() of Test::More' ); libdancer-perl-1.3120+dfsg.orig/t/11_logger/000_create_fake_env.t0000644000175000017500000000052412233013020023506 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/11_logger/03_file.t0000644000175000017500000000332112233013710021253 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use t::lib::TestUtils; use Dancer; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 18; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir, environment => 'test'; use_ok 'Dancer::Logger::File'; my $l = Dancer::Logger::File->new; ok defined($l), 'Dancer::Logger::File object'; isa_ok $l, 'Dancer::Logger::File'; can_ok $l, qw(init _log debug warning error); my $format = $l->format_message('debug', 'test'); like $format, qr/\[\d+\] debug @.+> test in/, "format looks good"; ok($l->_log(debug => "Perl Dancer test message"), "_log works"); ok($l->debug("Perl Dancer test message 2/5"), "debug works"); ok($l->warning("Perl Dancer test message 3/5"), "warning works"); ok($l->error("Perl Dancer test message 4/5"), "error works"); ok($l->info("Perl Dancer test message 5/5"), "info works"); ok(-f path($dir,'logs','test.log'), "Log file exists"); #Create a new tmp directory to test log_path option my $dir2 = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set log_path => $dir2, log_file => "foo.bar"; is(Dancer::Logger::File->logdir, $dir2, "logdir is ok"); ok($l->_log(debug => "Perl Dancer test message with log_path setting"), "_log works"); ok($l->debug("Perl Dancer test message with log_path setting 2/5"), "debug works"); ok($l->warning("Perl Dancer test message with log_path setting 3/5"), "warning works"); ok($l->error("Perl Dancer test message with log_path setting 4/5"), "error works"); ok($l->info("Perl Dancer test message with log_path setting 5/5"), "info works"); ok(-f path($dir2,'foo.bar'), "Log file foo.bar exists"); $l->{fh}->close; libdancer-perl-1.3120+dfsg.orig/t/11_logger/09_capture.t0000644000175000017500000000106712233013020022004 0ustar gregoagregoa#!/usr/bin/env perl use Test::More import => ['!pass'], tests => 3; use strict; use warnings; use Dancer; my $CLASS = "Dancer::Logger::Capture"; use_ok $CLASS; note "basic capture"; { my $logger = $CLASS->new; $logger->warning("Danger! Warning! Danger!"); $logger->debug("I like pie."); my $trap = $CLASS->trap; is_deeply $trap->read, [ { level => "warning", message => "Danger! Warning! Danger!" }, { level => "debug", message => "I like pie.", } ]; is_deeply $trap->read, [], "read clears the trap"; } libdancer-perl-1.3120+dfsg.orig/t/11_logger/05_format.t0000644000175000017500000000356212233013710021635 0ustar gregoagregoause strict; use warnings; use Test::More; use Dancer::Config qw/setting/; use Dancer::Logger::File; use Dancer::Request; plan tests => 9; setting logger_format => '(%L) %m'; my $l = Dancer::Logger::File->new; ok my $str = $l->format_message( 'debug', 'this is debug' ); is $str, "(debug) this is debug\n"; # custom format my $fmt = $l->_log_format(); is $fmt, '(%L) %m'; # no log format defined setting logger_format => undef; $fmt = $l->_log_format(); is $fmt, '[%P] %L @%D> %i%m in %f l. %l'; # log format from preset setting logger_format => 'simple'; $fmt = $l->_log_format(); is $fmt, '[%P] %L @%D> %i%m in %f l. %l'; setting logger_format => '%m %{%H:%M}t'; $str = $l->format_message('debug', 'this is debug'); like $str, qr/this is debug \[\d\d:\d\d\]/; setting charset => 'UTF-8', logger_format => '%h %t %T'; $str = $l->format_message('debug', 'this is debug'); like $str, qr{- \s \d+/[^/]+/\d+ \s \d+:\d+:\d+ \s \d+-\d+-\d+ \s \d+:\d+:\d+ }xi; my $env = { 'psgi.url_scheme' => 'http', REQUEST_METHOD => 'GET', SCRIPT_NAME => '/foo', PATH_INFO => '/bar/baz', REQUEST_URI => '/foo/bar/baz', QUERY_STRING => '', SERVER_NAME => 'localhost', SERVER_PORT => 5000, SERVER_PROTOCOL => 'HTTP/1.1', HTTP_ACCEPT_TYPE => 'text/html', }; my $headers = HTTP::Headers->new(); $headers->header('Accept-Type' => 'text/html'); my $request = Dancer::Request->new(env => $env); $request->{headers} = $headers; Dancer::SharedData->request($request); setting logger_format => '[%{accept_type}h] %m'; $str = $l->format_message('debug', 'this is debug'); like $str, qr/\[text\/html\] this is debug/; my $warn; do { local $SIG{__WARN__} = sub { $warn = $_[0] }; setting logger_format => '%y'; $str = $l->format_message('debug', 'this is sparta'); }; like $warn, qr/%y not supported/; libdancer-perl-1.3120+dfsg.orig/t/15_plugins/0000755000175000017500000000000012256332256020072 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/15_plugins/03_namespace.t0000644000175000017500000000065312233013710022503 0ustar gregoagregoa# issue #72 # https://github.com/PerlDancer/Dancer/issues#issue/72 use Test::More tests => 2, import => ['!pass']; { use Dancer; use lib 't'; use TestPlugin; use TestAppExt; is(test_plugin_symbol(), "test_plugin_symbol", "plugin symbol is exported in current namespace"); is(TestAppExt::test_app_func(), "test_plugin_symbol", "external module has also plugin's symbol"); } libdancer-perl-1.3120+dfsg.orig/t/15_plugins/02_config.t0000644000175000017500000000353412233013710022014 0ustar gregoagregoause strict; use warnings; use Dancer::ModuleLoader; use Test::More import => ['!pass']; plan skip_all => "YAML is needed for this test" unless Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 9; use Dancer ':syntax'; use Dancer::Config; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestUtils; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir, confdir => $dir; mkdir File::Spec->catdir( $dir, 'environments' ); set environment => 'test'; my $conffile = Dancer::Config->conffile; write_file( $conffile => << 'CONF' ); logger: Null plugins: Test: foo: bar My::Other::Plugin: path: / CONF my $envfile = Dancer::Config->environment_file; write_file( $envfile => << 'CONF' ); plugins: Test: foo: baz CONF ok( Dancer::Config->load, 'Config load works with a conffile' ); { package Dancer::Plugin::Test; use Dancer::Plugin; sub conf { plugin_setting; } } { package My::Other::Plugin; use Dancer::Plugin; sub conf { plugin_setting; } } { package Yet::Another::Plugin; use Dancer::Plugin; sub conf { plugin_setting; } } ok my $plugin_conf = Dancer::Plugin::Test::conf(), 'got config for plugin'; is_deeply $plugin_conf, { foo => 'baz' }, 'config is valid'; ok $plugin_conf = My::Other::Plugin::conf(), 'got config for plugin'; is_deeply $plugin_conf, { path => '/' }, 'config is valid'; ok $plugin_conf = Yet::Another::Plugin::conf(), 'got config for plugin'; is_deeply $plugin_conf, { }, 'config is valid'; $plugin_conf->{zlonk} = 'bam'; ok $plugin_conf = Yet::Another::Plugin::conf(), 'got config for plugin'; is_deeply $plugin_conf, { zlonk => 'bam' }, 'config is valid (modified)'; unlink $conffile; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/15_plugins/07_ajax_plack_builder.t0000644000175000017500000000404712233013710024357 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Plugin::Ajax; # GH #671 BEGIN { use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed to run this test" unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => "Plack is needed to run this test" unless Dancer::ModuleLoader->load('Plack::Builder'); } use HTTP::Request; use LWP::UserAgent; use Plack::Builder; use HTTP::Server::Simple::PSGI; plan tests => 6; my $js_content = q[ ]; Test::TCP::test_tcp( client => sub { my $port = shift; my $url = "http://127.0.0.1:$port/"; my $req = HTTP::Request->new(GET => $url); my $ua = LWP::UserAgent->new(); ok my $res = $ua->request($req), 'Got GET result'; ok $res->is_success, 'Successful'; is $res->content, $js_content, 'Correct JS content'; $req = HTTP::Request->new( POST => "${url}foo" ); $req->header( 'X-Requested-With' => 'XMLHttpRequest' ); ok( $res = $ua->request($req), 'Got POST result' ); ok( $res->is_success, 'Successful' ); is( $res->content, 'bar', 'Correct content' ); }, server => sub { my $port = shift; my $handler = sub { use Dancer; set port => $port, apphandler => 'PSGI', startup_info => 0; get '/' => sub {$js_content}; ajax '/foo' => sub {'bar'}; my $env = shift; my $request = Dancer::Request->new( env => $env ); Dancer->dance($request); }; my $app = builder { mount "/" => $handler; }; my $server = HTTP::Server::Simple::PSGI->new($port); $server->host("127.0.0.1"); $server->app($app); $server->run; }, ); libdancer-perl-1.3120+dfsg.orig/t/15_plugins/000_create_fake_env.t0000644000175000017500000000052412233013020023714 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/15_plugins/05_keywords.t0000644000175000017500000000104012233013020022401 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 6; use Dancer ':syntax'; use Dancer::Plugin; eval {register dance => sub {1};}; ok $@; like $@, qr/You can't use 'dance', this is a reserved keyword/; { local @Dancer::EXPORT = (@Dancer::EXPORT, '&frobnicator'); eval {register 'frobnicator' => sub {1};}; ok $@; like $@, qr/You can't use 'frobnicator', this is a reserved keyword/; } eval {register '1function' => sub {1};}; ok $@; like $@, qr/You can't use '1function', it is an invalid name/; libdancer-perl-1.3120+dfsg.orig/t/15_plugins/01_register.t0000644000175000017500000000060312233013020022356 0ustar gregoagregoause strict; use warnings; use Test::More 'import' => ['!pass'], tests => 2; use File::Spec; use Dancer::Test; use lib File::Spec->catdir( 't', 'lib' ); use TestApp; $ENV{HTTP_REFERER} = 'http://www.google.com'; response_status_is [GET => '/'] => 200, "referer is not blocked"; $ENV{HTTP_REFERER} = 'http://www.foo.com'; response_status_is [GET => '/'] => 403, "referer is blocked"; libdancer-perl-1.3120+dfsg.orig/t/15_plugins/04_apps_and_plugins.t0000644000175000017500000000044012233013020024062 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 1; { use Dancer ':syntax'; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestPlugin; load_app 'Forum'; is(some_plugin_keyword(), 42, 'plugin keyword is exported'); } libdancer-perl-1.3120+dfsg.orig/t/15_plugins/06_hook.t0000644000175000017500000000150112233013710021503 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; use lib 't/lib'; plan tests => 6; use LinkBlocker; ok( get( '/test' => sub { return 'index'; } ), 'index route is defined' ); route_exists [ GET => '/test' ]; response_content_is( [ GET => '/test' ], 'no content' ); response_status_is( [ GET => '/test' ], 202 ); # home-made hooks (test taken from Dancer 2) my $counter = 0; { use Dancer; use t::lib::Hookee; hook 'start_hookee' => sub { 'hook for plugin'; }; get '/hooks_plugin' => sub { $counter++; some_keyword(); }; } is $counter, 0, "the hook has not been executed"; my $r = dancer_response(GET => '/hooks_plugin'); is $counter, 1, "the hook has been executed exactly once"; libdancer-perl-1.3120+dfsg.orig/t/15_plugins/05_plugins_and_OO.t0000644000175000017500000000106112233013020023435 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 2; { use Dancer ':syntax'; # This plugin already inherits from Data::Dumper use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use TestPlugin2; load_app 'Forum'; # Make sure the keyword is well registerd is(some_other_plugin_keyword(), 42, 'plugin keyword is exported'); # Make sure the plugin is still a Data::Dumper child my $d = TestPlugin2->new( [ 1, 2 ], [ qw(foo bar) ] ); is($d->Dump(), "\$foo = 1;\n\$bar = 2;\n"); } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/0000755000175000017500000000000012256332256021241 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/03_route_handler/04_routes_matching.t0000644000175000017500000001215012233013020025077 0ustar gregoagregoause Dancer ':syntax'; use Dancer::Test; use Test::More tests => 47, import => ['!pass']; # regexps { get qr{/hello/([\w]+)} => sub { [splat] }; get qr{/show/([\d]+)} => sub { [splat] }; get qr{/post/([\w\d\-\.]+)/#comment([\d]+)} => sub { [splat] }; my @tests = ( { path => '/hello/sukria', expected => ['sukria'] }, { path => '/show/245', expected => ['245'] }, { path => '/post/this-how-to-write-smart-webapp/#comment412', expected => [ 'this-how-to-write-smart-webapp', '412' ] }, ); foreach my $test (@tests) { my $handle; my $path = $test->{path}; my $expected = $test->{expected}; my $request = [ GET => $path ]; response_status_is $request => 200, "route handler found for path `$path'"; response_content_is_deeply $request => $expected, "match data for path `$path' looks good"; } response_status_is [GET => '/no/hello/bar'] => 404; } # passing { get '/say/:char' => sub { pass and return false if length( params->{char} ) > 1; "char: " . params->{char}; }; get '/say/:number' => sub { pass and return false if params->{number} !~ /^\d+$/; "number: " . params->{number}; }; get qr{/say/_(.*)} => sub { "underscore: " . params->{splat}[0]; }; get '/say/:word' => sub { pass and return false if params->{word} =~ /trash/; "word: " . params->{word}; }; get '/say/*' => sub { "trash: " . params->{splat}[0]; }; get '/foo/' => sub { pass }; my @tests = ( { path => '/say/A', expected => 'char: A' }, { path => '/say/24', expected => 'number: 24' }, { path => '/say/B', expected => 'char: B' }, { path => '/say/Perl', expected => 'word: Perl' }, { path => '/say/_stuff', expected => 'underscore: stuff' }, { path => '/say/go_to_trash', expected => 'trash: go_to_trash' }, ); foreach my $test (@tests) { my $path = $test->{path}; my $expected = $test->{expected}; response_status_is [ GET => $path ] => 200, "route found for path `$path'"; response_content_is_deeply [ GET => $path ] => $expected, "match data for path `$path' looks good"; } response_status_is [ GET => '/foo' ] => 404, "Pass over the last match is 404"; } # wildcards { my @paths = ( '/hi/*', '/hi/*/welcome/*', '/download/*.*', '/optional/?*?' ); my @tests = ( { path => '/hi/sukria', expected => ['sukria'] }, { path => '/hi/alexis/welcome/sukrieh', expected => [ 'alexis', 'sukrieh' ] }, { path => '/download/wolverine.pdf', expected => [ 'wolverine', 'pdf' ] }, { path => '/optional/alexis', expected => ['alexis'] }, { path => '/optional/', expected => [] }, { path => '/optional', expected => [] }, ); my $nb_tests = ( scalar(@paths) ) + ( scalar(@tests) * 2 ); get( $_ => sub { [splat] } ) for @paths; foreach my $test (@tests) { my $path = $test->{path}; my $expected = $test->{expected}; my $response = dancer_response( GET => $path ); ok( defined($response), "route handler found for path `$path'" ); is_deeply( $response->content, $expected, "match data for path `$path' looks good" ); } } # any routes handler { any [ 'get', 'delete' ] => '/any_1' => sub { "any_1"; }; any '/any_2' => sub { "any_2"; }; eval { any 'get' => '/any_1' => sub { "any_1"; }; }; like $@, qr/Syntax error, methods should be provided as an ARRAY ref/, "syntax error caught"; my @routes = ( { methods => [ 'get', 'delete' ], path => '/any_1', expected => 'any_1', }, { methods => [ 'get', 'delete', 'post', 'put' ], path => '/any_2', expected => 'any_2', } ); # making sure response are OK foreach my $route (@routes) { foreach my $method ( @{ $route->{methods} } ) { my $response = dancer_response( $method => $route->{path} ); ok( defined($response), "route handler found for method $method, path $route->{path}"); is $response->content, $route->{expected}, "response content is ok"; } } # making sure 404 are thrown for unspecified routes my @failed = ( { methods => [ 'post', 'put' ], path => '/any_1', }, ); foreach my $route (@failed) { foreach my $method ( @{ $route->{methods} } ) { my $response = dancer_response( $method => $route->{path} ); is( $response->status, 404, "route handler not found for method $method, path " . $route->{path} ); } } } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/05_unicode.t0000644000175000017500000000062712233013020023341 0ustar gregoagregoause Test::More 'tests' => 1, import => ['!pass']; use strict; use warnings; use utf8; use File::Spec; use Dancer ':syntax'; use Dancer::Test; my $file = path(dirname(__FILE__), "public", "utf8file.txt"); get "/hello" => sub { open my $f, "<:utf8", $file; chomp(my $line = <$f>); $line =~ s/ //g; close $f; $line }; response_content_is [GET => "/hello"] => "⋄⋄⋄Hello⋄⋄⋄"; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/12_response.t0000644000175000017500000000314612233013707023562 0ustar gregoagregoause Test::More tests => 23; use strict; use warnings; use Dancer::Response; my $r = Dancer::Response->new(); is $r->status => 200, "status looks good"; isa_ok $r->{headers} => 'HTTP::Headers'; $r->status(500); is $r->status => 500; Dancer::SharedData->response->status(200); is $r->status => 200; $r->content_type('text/plain'); is($r->content_type => 'text/plain'); is($r->header('Content-Type') => 'text/plain'); is(Dancer::SharedData->response->content_type => 'text/plain'); $r->headers('X-Bar' => 3); is $r->header('X-Bar') => 3; $r->header('X-Baz' => 2); is $r->header('X-Baz') => 2; $r->pass(1); ok $r->has_passed; my $headers = $r->headers_to_array; ok $headers; is ref $headers, 'ARRAY'; is_deeply $headers => [ 'Content-Type' => 'text/plain', 'X-Bar' => 3, 'X-Baz' => 2]; $r->content('foo'); ok $r->exists; is $r->content => 'foo'; Dancer::SharedData->response->content('bar'); ok(Dancer::SharedData->response->exists); is(Dancer::SharedData->response->content => 'bar'); # test for halt && halted Dancer::Response->new(content => 'this is ok'); eval { Dancer::SharedData->response->halt('this is not ok'); }; $r = Dancer::SharedData->response(); is $r->status => 200; is $r->content => 'this is not ok'; is $r->halted => 1; Dancer::Response->new(content => 'this is ok'); eval { Dancer::SharedData->response->halt(Dancer::Response->new(status => 500, content => 'this is not ok')); }; $r = Dancer::SharedData->response(); is $r->status => 500; is $r->content => 'this is not ok'; is $r->halted => 1; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/views/0000755000175000017500000000000012256332256022376 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/03_route_handler/views/foo/0000755000175000017500000000000012256332256023161 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/03_route_handler/views/foo/index.tt0000644000175000017500000000001212233013707024622 0ustar gregoagregoafoo/index libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/views/foo/bar.tt0000644000175000017500000000001012233013707024255 0ustar gregoagregoafoo/bar libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/views/hello.tt0000644000175000017500000000000612233013020024022 0ustar gregoagregoaHello libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/views/error.tt0000644000175000017500000000031412233013020024052 0ustar gregoagregoaERROR: <% title %> PERL VERSION: <% perl_version %> DANCER VERSION: <% dancer_version %> ERROR TEMPLATE: <% settings.error_template %> REQUEST METHOD: <% request.method %> PARAM VALUE: <% params.param %> libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/33_vars.t0000644000175000017500000000173212233013707022701 0ustar gregoagregoause strict; use warnings; # Test that vars are really reset between each request use Test::More; use LWP::UserAgent; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); plan tests => 10; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; for (1..10) { my $req = HTTP::Request->new( GET => "http://127.0.0.1:$port/getvarfoo" ); my $res = $ua->request($req); is $res->content, 1; } }, server => sub { my $port = shift; use Dancer ":tests"; # vars should be reset before the handler is called var foo => 42; set startup_info => 0, port => $port; get "/getvarfoo" => sub { return ++vars->{foo}; }; Dancer->dance; }, ); libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/29_redirect_immediately.t0000644000175000017500000000111012233013707026105 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Test; use Dancer ':syntax'; plan tests => 5; my $pass = 0; hook before => sub { redirect '/' unless request->path eq '/' || request->path eq ''; }; get '/' => sub { return "im home"; }; get '/false' => sub { $pass++; return "im false"; }; response_status_is [ GET => '/' ] => 200; response_content_is [ GET => '/' ] => "im home"; response_status_is [ GET => '/false' ] => 302; response_headers_include [ GET => '/false' ] => ['Location'=>'http://localhost/']; is $pass, 0; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/15_prefix.t0000644000175000017500000000476712233013707023236 0ustar gregoagregoause Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; use Dancer::Route; my @tests = ( { path => '/say/', expected => 'char: all' }, { path => '/say/A', expected => 'char: A' }, { path => '/say/24', expected => 'number: 24' }, { path => '/say/B', expected => 'char: B' }, { path => '/say/Perl', expected => 'word: Perl' }, { path => '/say/_stuff', expected => 'underscore: stuff' }, { path => '/say/any', expected => 'any' }, { path => '/go_to_trash', expected => 'trash: go_to_trash' }, { path => '/say/foo', expected => 'it worked' }, { path => '/say/foo/', expected => 'it worked' }, { path => '/lex/foo', expected => 'it worked' }, { path => '/lex/sublex/foo', expected => 'it still works' }, { path => '/lex/bar', expected => 'back to normal' }, { path => '/dura/us', expected => 'us worked' }, ); plan tests => 4 + 2*@tests; eval { prefix 'say' }; my $e = $@; like $e => qr/not a valid prefix/, 'prefix must start with a /'; ok $e->isa('Dancer::Exception::Base'), 'exception is a Dancer exception'; ok $e->does('Core'), 'exception is a Core one'; ok $e->does('Core::App'), 'exception is a Acore::App one'; { prefix '/say' => 'prefix defined'; get '/foo' => sub { 'it worked' }; get '/foo/' => sub { 'it worked' }; get '/:char' => sub { pass and return false if length( params->{char} ) > 1; "char: " . params->{char}; }; get '/:number' => sub { pass and return false if params->{number} !~ /^\d+$/; "number: " . params->{number}; }; prefix '/lex' => sub { get '/foo' => sub { 'it worked' }; prefix '/sublex' => sub { get '/foo' => sub { 'it still works' }; }; get '/bar' => sub { 'back to normal' }; }; any '/any' => sub {"any"}; get qr{/_(.*)} => sub { "underscore: " . params->{splat}[0]; }; get '/:word' => sub { pass and return false if params->{word} =~ /trash/; "word: " . params->{word}; }; get '/' => sub { "char: all"; }; prefix(undef); prefix '/dura' => sub { get '/us' => sub { 'us worked' }; }; prefix('/'); get '/*' => sub { "trash: " . params->{splat}[0]; }; } foreach my $test (@tests) { my $path = $test->{path}; my $expected = $test->{expected}; response_status_is [GET => $path] => 200; response_content_is_deeply [GET => $path] => $expected; } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/06_redirect.t0000644000175000017500000000555512233013707023536 0ustar gregoagregoause Test::More; use Dancer ':tests', ':syntax'; use Dancer::Test; plan tests => 16; # basic redirect { get '/' => sub { 'home' }; get '/bounce' => sub { redirect '/' }; get '/redirect' => sub { header 'X-Foo' => 'foo'; redirect '/'; }; get '/redirect_querystring' => sub { redirect '/login?failed=1' }; response_status_is [ GET => '/' ] => 200; response_content_is [ GET => '/' ] => "home"; response_status_is [ GET => '/bounce' ] => 302; my $expected_headers = [ 'Location' => 'http://localhost/', 'Content-Type' => 'text/html', 'X-Foo' => 'foo', ]; response_headers_include [ GET => '/redirect' ] => $expected_headers; $expected_headers = [ 'Location' => 'http://localhost/login?failed=1', 'Content-Type' => 'text/html', ]; response_headers_include [ GET => '/redirect_querystring' ] => $expected_headers; } # redirect absolute { get '/absolute_with_host' => sub { redirect "http://foo.com/somewhere"; }; get '/absolute' => sub { redirect "/absolute"; }; get '/relative' => sub { redirect "somewhere/else"; }; response_headers_include [ GET => '/absolute_with_host' ], [ Location => 'http://foo.com/somewhere' ]; response_headers_include [ GET => '/absolute' ], [ Location => 'http://localhost/absolute' ]; response_headers_include [ GET => '/relative' ], [ Location => 'http://localhost/somewhere/else' ]; } # redirect no content { my $not_redirected_content = 'gotcha'; get '/home' => sub { "home"; }; get '/cond_bounce' => sub { if ( params->{'bounce'} ) { redirect '/'; return; } $not_redirected_content; }; my $req = [ GET => '/cond_bounce', { params => { bounce => 1 } } ]; response_status_is $req => 302, 'status is 302'; response_content_is $req => '', 'content is empty when bounced'; $req = [ GET => '/cond_bounce' ]; response_status_is $req => 200, 'status is 200'; response_content_is $req => $not_redirected_content, 'content is not empty'; } # redirect behind proxy { set behind_proxy => 1; $ENV{X_FORWARDED_HOST} = "nice.host.name"; response_headers_include [GET => '/bounce'] => [Location => 'http://nice.host.name/'], "Test X_FORWARDED_HOST"; $ENV{HTTP_FORWARDED_PROTO} = "https"; response_headers_include [GET => '/bounce'] => [Location => 'https://nice.host.name/'], "Test HTTP_FORWARDED_PROTO"; $ENV{X_FORWARDED_PROTOCOL} = "ftp"; # stupid, but why not? response_headers_include [GET => '/bounce'] => [Location => 'ftp://nice.host.name/'], "Test X_FORWARDED_PROTOCOL"; $ENV{HTTP_REQUEST_BASE} = "/application-root"; response_headers_include [GET => '/bounce'] => [Location => 'ftp://nice.host.name/application-root/'], "Test HTTP_REQUEST_BASE"; } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/public/0000755000175000017500000000000012256332256022517 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/03_route_handler/public/utf8file.txt0000644000175000017500000000003612233013020024761 0ustar gregoagregoa⋄ ⋄ ⋄ Hello ⋄ ⋄ ⋄ libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/public/404.html0000644000175000017500000000002012233013020023660 0ustar gregoagregoathis is an errorlibdancer-perl-1.3120+dfsg.orig/t/03_route_handler/29_forward.t0000644000175000017500000000451112233013707023375 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Logger; use Dancer::Test; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 18; my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir; Dancer::Logger->init('File'); get '/' => sub { 'home:' . join(',', params); }; get '/bounce/' => sub { return forward '/'; }; get '/bounce/:withparams/' => sub { return forward '/'; }; get '/bounce2/adding_params/' => sub { return forward '/', { withparams => 'foo' }; }; post '/simple_post_route/' => sub { 'post:' . join(',', params); }; get '/go_to_post/' => sub { return forward '/simple_post_route/', { foo => 'bar' }, { method => 'post' }; }; get '/b' => sub { vars->{test} = 1; forward '/a'; }; get '/a' => sub { return "test is " . var('test'); }; response_status_is [ GET => '/' ] => 200; response_content_is [ GET => '/' ] => 'home:'; response_status_is [ GET => '/bounce/' ] => 200; response_content_is [ GET => '/bounce/' ] => 'home:'; response_status_is [ GET => '/bounce/thesethings/' ] => 200; response_content_is [ GET => '/bounce/thesethings/' ] => 'home:withparams,thesethings'; response_status_is [ GET => '/bounce2/adding_params/' ] => 200; response_content_is [ GET => '/bounce2/adding_params/' ] => 'home:withparams,foo'; response_status_is [ GET => '/go_to_post/' ] => 200; response_content_is [ GET => '/go_to_post/' ] => 'post:foo,bar'; response_status_is [ GET => '/b' ] => 200; response_content_is [ GET => '/b' ] => 'test is 1'; my $expected_headers = [ 'Content-Length' => 5, 'Content-Type' => 'text/html', 'Server' => "Perl Dancer ${Dancer::VERSION}", 'X-Powered-By' => "Perl Dancer ${Dancer::VERSION}", ]; response_headers_are_deeply [ GET => '/bounce/' ], $expected_headers; # checking post post '/' => sub { 'post-home' }; post '/bounce/' => sub { forward('/') }; response_status_is [ POST => '/' ] => 200; response_content_is [ POST => '/' ] => 'post-home'; response_status_is [ POST => '/bounce/' ] => 200; response_content_is [ POST => '/bounce/' ] => 'post-home'; $expected_headers->[1] = 9; response_headers_are_deeply [ POST => '/bounce/' ], $expected_headers; Dancer::Logger::logger->{fh}->close; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/23_filter_error_catching.t0000644000175000017500000000056512233013707026266 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; plan tests => 2; use Dancer ':syntax'; use Dancer::Test; set show_errors => true; { hook before => sub { FooBar->send_error; # FAIL }; get '/' => sub { "route" }; } response_status_is [GET => '/'] => 500; response_content_like [GET => '/'] => qr/FooBar->send_error/; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/05_filter.t0000644000175000017500000000441512233013707023213 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer; use Dancer::Test; plan tests => 19; # simple before filter { my $i = 0; hook before => sub { content_type('text/xhtml'); }; hook before => sub { if ( request->path_info eq '/redirect_from' ) { redirect('/redirect_to'); } elsif( request->path_info eq '/' or request->path eq '/somewhere' ){ params->{number} = 42; var notice => "I am here"; request->path_info('/'); } }; get '/' => sub { is( params->{number}, 42, "params->{number} is set" ); is( "I am here", vars->{notice}, "vars->{notice} is set" ); return 'index'; }; get '/redirect_from' => sub { $i++; }; route_exists [ GET => '/' ]; response_status_is [ GET => '/' ] => 200; my $path = '/somewhere'; my $request = [ GET => $path ]; route_doesnt_exist $request => "there is no route handler for $path..."; response_status_is $request => 200, "...but a response is returned though"; response_content_is $request => 'index', "which is the result of a redirection to /"; response_headers_include [ GET => '/redirect_from' ] => [ 'Location' => 'http://localhost/redirect_to', 'Content-Type' => 'text/xhtml', ]; is $i, 0, 'never gone to redirect_from'; } # filters and params { hook before => sub { return if request->path !~ /foo/; ok( defined( params->{'format'} ), "param format is defined in before filter" ); }; get '/foo.:format' => sub { ok( defined( params->{'format'} ), "param format is defined in route handler" ); 1; }; route_exists [ GET => '/foo.json' ]; response_content_is [ GET => '/foo.json' ], 1; } # filter and halt { hook before => sub { unless (params->{'requested'}) { return halt("stopped"); } }; hook before => sub { unless (params->{'requested'}) { halt("another halt"); } }; get '/halt' => sub { "route" }; response_content_is [GET => '/halt'], "stopped"; response_content_is [GET => '/halt', { params => {requested => 1} }], "route"; } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/01_http_methods.t0000644000175000017500000000122012233013020024377 0ustar gregoagregoause Dancer ':tests', ':syntax'; use Dancer::Test; use Test::More; my @methods = qw(get head put post delete options); plan tests => @methods * 3; get '/' => sub { 'get' }; post '/' => sub { 'post' }; put '/' => sub { 'put' }; del '/' => sub { 'delete' }; options '/' => sub { 'options' }; foreach my $m (@methods) { route_exists [ $m => '/' ], "route handler found for method $m"; response_status_is [ $m => '/' ] => 200, "response status is 200 for $m"; my $content = $m; $content = '' if $m eq 'head'; response_content_like [ $m => '/' ] => qr/$content/, "response content is OK for $m"; } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/24_multiple_params.t0000644000175000017500000000561112233013020025110 0ustar gregoagregoause strict; use warnings; use Test::More tests => 26*2, import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; { get '/' => sub { 'index' }; get '/name/:name' => sub { params->{name} }; get '/name/:name/:location' => sub { params->{name} }; get '/location/:location' => sub { params->{location} }; get '/location/:name/:location' => sub { params->{location} }; post '/name/:name' => sub { params->{name} }; post '/name/:name/:location' => sub { params->{name} }; post '/location/:location' => sub { params->{location} }; post '/location/:name/:location' => sub { params->{location} }; } my @tests = ( {method => 'GET', path => '/', expected => 'index'}, {method => 'GET', path => '/name/bob', expected => 'bob'}, {method => 'GET', path => '/name/bill', expected => 'bill'}, {method => 'GET', path => '/name/bob', expected => 'bob'}, {method => 'GET', path => '/name/bob/paris', expected => 'bob' }, {method => 'GET', path => '/name/bob/dublin', expected => 'bob' }, {method => 'GET', path => '/name/bob/paris', expected => 'bob' }, {method => 'GET', path => '/name/bill/paris', expected => 'bill' }, {method => 'GET', path => '/name/bill/dublin', expected => 'bill' }, {method => 'GET', path => '/name/bill/paris', expected => 'bill' }, {method => 'GET', path => '/name/bob/paris', expected => 'bob' }, {method => 'GET', path => '/name/bob/dublin', expected => 'bob' }, {method => 'GET', path => '/name/bill/paris', expected => 'bill' }, {method => 'GET', path => '/name/bill/dublin', expected => 'bill' }, {method => 'GET', path => '/location/paris', expected => 'paris'}, {method => 'GET', path => '/location/dublin', expected => 'dublin'}, {method => 'GET', path => '/location/paris', expected => 'paris'}, {method => 'GET', path => '/location/bob/paris', expected => 'paris' }, {method => 'GET', path => '/location/bob/dublin', expected => 'dublin' }, {method => 'GET', path => '/location/bob/paris', expected => 'paris' }, {method => 'post', path => '/name/bob', expected => 'bob'}, {method => 'post', path => '/name/bob/paris', expected => 'bob' }, {method => 'post', path => '/location/paris', expected => 'paris'}, {method => 'post', path => '/location/bob/paris', expected => 'paris' }, {method => 'post', path => '/location/bob/dublin', expected => 'dublin' }, {method => 'post', path => '/location/bob/paris', expected => 'paris' }, ); setting route_cache => 1; foreach my $test (@tests) { my $method = $test->{method}; my $path = $test->{path}; my $expected = $test->{expected}; my $request = [$method => $path]; response_status_is $request => 200; response_content_is_deeply $request, $expected, } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/03_routes_api.t0000644000175000017500000000363712233013707024103 0ustar gregoagregoause Dancer ':syntax'; use Dancer::Test; use Test::More 'tests' => 8, import => ['!pass']; use Dancer::Route; my $r = Dancer::Route->new( method => 'get', pattern => '/:var', code => sub { params->{'var'}; }, ); isa_ok $r => 'Dancer::Route'; is $r->method => 'get', "method is 'get'"; is $r->pattern => '/:var', "pattern is '/:var'"; my $req = Dancer::Request->new_for_request(GET => '/42'); my $expected_match = { var => 42 }; my $match = $r->match($req); is_deeply $match => $expected_match, "route matched GET /42"; $r->match_data($match); Dancer::SharedData->request($req); my $response = $r->run($req); is $response->{content} => 42, "response looks good"; my $r2 = Dancer::Route->new(method => 'get', pattern => '/pass/:var', code => sub { pass; # The next line is not executed, as 'pass' breaks the route workflow die }, prev => $r); my $r3 = Dancer::Route->new(method => 'get', pattern => '/other/path', code => sub { "this is r3" }, prev => $r2); my $r4 = Dancer::Route->new(method => 'get', pattern => '/pass/:var', code => sub { "this is r4" }, prev => $r3); $req = Dancer::Request->new_for_request(GET => '/pass/42'); $expected_match = { var => 42 }; $match = $r2->match($req); is_deeply $match => $expected_match, "route matched GET /42"; $r2->match_data($match); Dancer::SharedData->request($req); $r2->run($req); $response = Dancer::SharedData->response; is $response->{content} => 'this is r4', "route 2 passed, r3 skipped (dont match), r4 served the response"; setting 'public' => 't/03_route_handler/public'; my $r5 = Dancer::Route->new( method => 'get', pattern => '/error', code => sub { send_error( "no", 404 ) } ); $req = Dancer::Request->new_for_request( GET => '/error' ); my $res = $r5->run($req); is( ( grep { /Content-Type/ } @{ $res->headers_to_array } ), 1, 'only one content-type' ); libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/07_compilation_warning.t0000644000175000017500000000152612233013707025773 0ustar gregoagregoause Test::More; use Dancer ':syntax', ':tests'; use Dancer::Test; use Dancer::Logger; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); my $dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); set appdir => $dir; Dancer::Logger->init('File'); # perl <= 5.8.x won't catch the warning plan skip_all => 'Need perl >= 5.10' if $] < 5.010; set warnings => 1, show_errors => 1; get '/warning' => sub { my $bar; "$bar foo"; }; my @tests = ( { path => '/warning', expected => qr/Use of uninitialized value \$bar in concatenation/ }, ); plan tests => scalar(@tests); foreach my $test (@tests) { response_content_like [GET => $test->{path}] => $test->{expected}, "response looks good for ".$test->{path}; } Dancer::Logger::logger->{fh}->close; File::Temp::cleanup(); libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/14_options.t0000644000175000017500000000271012233013020023401 0ustar gregoagregoause Test::More; use Dancer::Test; use Dancer ':syntax', ':tests'; use Dancer::Route; plan tests => 20; { get( '/', { agent => 'foo' } => sub {'agent foo'} ); get('/', { agent => 'bar' }, sub { 'agent bar'} ); get( '/', sub {'all agents'} ); get( '/foo', { agent => 'foo' } => sub {'foo only'} ); get('/welcome', {agent => qr{Mozilla}} => sub { "hey Mozilla!" }); get('/welcome' => sub { "hello" }); } eval { get '/fail', { false_option => 42 } => sub { } }; like $@, qr/Not a valid option for route matching: `false_option'/, "only supported options are allowed"; my @tests = ( {method => 'GET', path => '/', expected => 'agent foo', agent => 'foo'}, {method => 'GET', path => '/', expected => 'agent bar', agent => 'bar'}, {method => 'GET', path => '/', expected => 'all agents'}, {method => 'GET', path => '/foo', expected => 'foo only', agent => 'foo'}, { method => 'GET', path => '/welcome', expected => 'hey Mozilla!', agent => 'Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.5)' }, {method => 'GET', path => '/welcome', expected => 'hello'}, ); foreach my $test (@tests) { $ENV{HTTP_USER_AGENT} = $test->{agent} || undef; my $req = [$test->{method} => $test->{path}]; route_exists $req; response_status_is $req => 200; response_content_is $req, $test->{expected}; } $ENV{HTTP_USER_AGENT} = 'bar'; route_doesnt_exist [GET => '/foo']; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/18_auto_page.t0000644000175000017500000000210612233013707023671 0ustar gregoagregoa# this test makes sure the auto_page feature works as expected # whenever a template matches a requested path, a default route handler # takes care of rendering it. use strict; use warnings; use Test::More import => ['!pass'], tests => 8; use Dancer::Test; { package Foo; use Dancer; hook before_template => sub { my $tokens = shift; $tokens->{title} = "Dancer"; }; set auto_page => true, views => path(dirname(__FILE__), 'views'); get '/' => sub { 1 }; } response_status_is [GET => '/hello'] => 200, "response found for /hello"; response_content_is [GET => '/hello'] => "Hello\n", "content looks good"; response_status_is [GET => '/foo/bar' ], 200, "response found for /foo/bar"; response_content_is [GET => '/foo/bar' ], "foo/bar\n", "content looks good"; response_status_is [GET => '/foo/' ], 200, "response found for /foo/"; response_content_is [GET => '/foo/' ], "foo/index\n", "content looks good"; response_status_is [GET => '/falsepage'] => 404; response_content_like [GET => '/error'] => qr/ERROR: Dancer\n/, "error page looks OK"; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/31_infinite_loop.t0000644000175000017500000000122412233013707024556 0ustar gregoagregoause strict; use warnings; use Test::More tests => 6, import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; my $i = 0; set show_errors => 1; ok(get('/:id', sub { "whatever " . params->{id} }), 'installed basic route handler'); route_exists [GET => '/:id']; response_status_is [GET => "/$i"] => 200, 'before not installed yet, response status is 200 looks good for GET /0'; response_content_is [GET => "/$i"], "whatever $i"; hook before => sub { ++$i; request->path_info("/$i"); }; response_status_is [GET => "/$i"] => 500, "Right request status"; response_content_like [GET => "/$i"] => qr{infinite loop}, "infinite loop detected"; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/99_bugs.t0000644000175000017500000000247312233013707022705 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer; use Dancer::Test; plan tests => 19; # issue gh_77 { get '/:page' => sub { my $page = params->{page}; return pass() unless $page =~ m/about|help|intro|upload/; return $page; }; get '/status' => sub { 'status' }; get '/search' => sub { 'search' }; response_content_is [GET => '/intro'], 'intro'; # this work response_content_is [GET => '/status'], 'status'; # this is a 404, shouldn't response_content_is [GET => '/status'], 'status'; # now this work response_content_is [GET => '/search'], 'search'; # we get status here instead response_content_is [GET => '/search'], 'search'; # now this works } # issue gh_190 { my $i = 0; hook before => sub { redirect '/somewhere' if request->path eq '/' }; get( '/', sub { $i++; 'Hello' } ); route_exists [ GET => '/' ]; response_headers_include [ GET => '/' ] => [ Location => 'http://localhost/somewhere' ]; response_content_is [ GET => '/' ] => ''; is $i, 0; } # issue gh_393 # Test that vars are reset between each request by Dancer::Test { var foo => 0; get '/reset' => sub { vars->{foo} += 1; vars->{foo}; }; for ( 1 .. 10 ) { response_content_is [ GET => '/reset' ] => 1, "foo is 1"; } } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/34_forward_body_post.t0000644000175000017500000000237712233013707025463 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Carp; $Carp::Verbose = 1; BEGIN { use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); } use Dancer; use LWP::UserAgent; use HTTP::Request; plan tests => 2; Test::TCP::test_tcp( client => sub { my $port = shift; my $url_base = "http://127.0.0.1:$port"; my $ua = LWP::UserAgent->new; my $res = $ua->post($url_base . "/foo", { data => 'foo'}); is($res->decoded_content, "data:foo"); $res = $ua->post($url_base . "/foz", { data => 'foo'}); is($res->decoded_content, "data:foo"); }, server => sub { my $port = shift; Dancer::Config->load; post '/foo' => sub { forward '/bar'; fail "This line should not be executed - forward should have aborted the route execution"; }; post '/bar' => sub { join(":",params) }; post '/foz' => sub { forward '/baz'; }; post '/baz' => sub { join(":",params('body')) }; set startup_info => 0, port => $port, show_errors => 1; Dancer->dance(); }, ); libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/28_plack_mount.t0000644000175000017500000000302012233013707024236 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; BEGIN { use Dancer::ModuleLoader; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed to run this test" unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => "Plack is needed to run this test" unless Dancer::ModuleLoader->load('Plack::Builder'); } use HTTP::Request; use LWP::UserAgent; use Plack::Builder; # should be loaded in BEGIN block, but it seems that it's not the case ... use HTTP::Server::Simple::PSGI; plan tests => 3; Test::TCP::test_tcp( client => sub { my $port = shift; my $url = "http://127.0.0.1:$port/mount/test/foo"; my $req = HTTP::Request->new(GET => $url); my $ua = LWP::UserAgent->new(); ok my $res = $ua->request($req); ok $res->is_success; is $res->content, '/foo'; }, server => sub { my $port = shift; my $handler = sub { use Dancer; set port => $port, apphandler => 'PSGI', startup_info => 0; get '/foo' => sub {request->path_info}; my $env = shift; my $request = Dancer::Request->new(env => $env); Dancer->dance($request); }; my $app = builder { mount "/mount/test" => $handler; }; my $server = HTTP::Server::Simple::PSGI->new($port); $server->host("127.0.0.1"); $server->app($app); $server->run; }, ); libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/08_errors.t0000644000175000017500000000337212233013020023232 0ustar gregoagregoause Test::More; use Dancer ':syntax', ':tests'; use Dancer::Test; use Dancer::Error; use Dancer::ModuleLoader; plan tests => 12; set show_errors => 1; my $error = Dancer::Error->new(code => 500); ok defined($error) => "error is defined"; ok $error->title => "title is set"; SKIP: { skip "JSON is required", 10 unless Dancer::ModuleLoader->load('JSON'); set 'serializer' => 'JSON'; my $error = Dancer::Error->new( code => 400, message => { foo => 'bar' } ); ok defined($error) => "error is defined"; my $response = $error->render(); isa_ok $response => 'Dancer::Response'; is $response->{status} => 400; like $response->{content} => qr/foo/; # FIXME: i think this is a bug where serializer cannot be set to 'undef' # without the Serializer.pm trying to load JSON as a default serializer ## Error Templates set(serializer => undef, warnings => 1, error_template => "error.tt", views => path(dirname(__FILE__), 'views')); get '/warning' => sub { my $a = undef; @$a; }; get '/warning/:param' => sub { my $a = undef; @$a; }; response_content_like [GET => '/warning'], qr/ERROR: Runtime Error/, "template is used"; response_content_like [GET => '/warning'], qr/PERL VERSION: $]/, "perl_version is available"; response_content_like [GET => '/warning'], qr/DANCER VERSION: $Dancer::VERSION/, "dancer_version is available"; response_content_like [GET => '/warning'], qr/ERROR TEMPLATE: error.tt/, "settings are available"; response_content_like [GET => '/warning'], qr/REQUEST METHOD: GET/, "request is available"; response_content_like [GET => '/warning/value'], qr/PARAM VALUE: value/, "params are available"; }; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/16_caching.t0000644000175000017500000001021312233013707023315 0ustar gregoagregoa# testing caching mechanism use strict; use warnings; use Test::More tests => 66, import => ['!pass']; use Dancer::Test; use Dancer ':syntax'; setting route_cache => 1; { # checking the size parsing use Dancer::Route::Cache; my %sizes = ( '1G' => 1073741824, '10M' => 10485760, '10K' => 10240, '300' => 300, ); while ( my ( $size, $expected ) = each %sizes ) { my $got = Dancer::Route::Cache->parse_size($size); cmp_ok( $got, '==', $expected, "Parsing $size correctly ($got)" ); } # checking we can start cache correctly my $cache = Dancer::Route::Cache->new( size_limit => '10M', path_limit => 10, ); isa_ok $cache => 'Dancer::Route::Cache'; cmp_ok( $cache->size_limit, '==', $sizes{'10M'}, 'setting size_limit' ); cmp_ok( $cache->path_limit, '==', 10, 'setting path_limit' ); } # running three routes # GET and POST with in pass to 'any' get '/:p', sub { params->{'p'} eq 'in' or pass }; post '/:p', sub { params->{'p'} eq 'in' or pass }; any '/:p', sub { 'any' }; my %reqs = ( '/' => 'GET / request', '/var' => 'GET /var request', ); foreach my $method ( qw/get post/ ) { foreach my $path ( '/in', '/out', '/err' ) { response_status_is [$method => $path] => 200; } } my $cache = Dancer::Route::Cache->get; isa_ok $cache => 'Dancer::Route::Cache'; # checking when path doesn't exist is $cache->route_from_path( get => '/wont/work') => undef, 'non-existing path'; is $cache->route_from_path( post => '/wont/work') => undef, 'non-existing path'; foreach my $method ( qw/get post/ ) { foreach my $path ( '/in', '/out', '/err' ) { my $route = $cache->route_from_path( $method, $path ); is ref($route) => 'Dancer::Route', "Got route for $path ($method)"; } } # since "/out" and "/err" aren't "/in", both GET and POST delegate to "any()" # that means that "/out" and "/err" on GET should be the same as on POST foreach my $path ( '/out', '/err' ) { my %content; # by method foreach my $method ( qw/get post/ ) { my $handler = $cache->route_from_path( $method => $path ); ok $handler, "Got handler for $method $path"; if ($handler) { $content{$method} = $handler->{'content'}; } } if ( defined $content{'get'} and defined $content{'post'} ) { is $content{'get'} => $content{'post'}, "get/post $path is the same"; } } # clean up routes $cache->{'cache'} = {}; $cache->{'cache_array'} = []; { # testing path_limit setting route_cache_path_limit => 10; $cache->path_limit(10); my @paths = 'a' .. 'z'; foreach my $path (@paths) { get "/$path" => sub {1}; } foreach my $path (@paths) { response_status_is [GET => "/$path"] => 200, "get $path request"; } # check that only 10 remained cmp_ok( $cache->route_cache_paths, '==', 10, 'Path limit to 10' ); # because we use a FIFO method, we know which ones they are my @expected_paths = map { [ 'get', "/$_", 'main' ] } 'q' .. 'z'; is_deeply( $cache->{'cache_array'}, \@expected_paths, 'Correct paths', ); } # clean up routes $cache->{'cache'} = {}; $cache->{'cache_array'} = []; SKIP: { # testing size_limit delete $cache->{'path_limit'}; # doing it manually since parse_size is only in init $cache->size_limit( $cache->parse_size('3K') ); # creating large routes my @paths = (); foreach my $iter ( 1 .. 10 ) { my $all = ''; while ( length $all < 300 ) { $all .= rand 99999; } push @paths, "/$all"; } foreach my $path (@paths) { get "/$path" => sub {1}; } foreach my $path (@paths) { response_status_is [GET => $path] => 200, 'get request'; } # check that only 10 remained cmp_ok( $cache->route_cache_paths, '==', 9, 'Only 9 paths' ); # because we use a FIFO method, we know which ones they are shift @paths; my @expected_paths = map { [ 'get', $_, 'main' ] } @paths; is_deeply( $cache->{'cache_array'}, \@expected_paths, 'Correct paths', ); } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/02_params.t0000644000175000017500000000421712233013020023172 0ustar gregoagregoause Dancer ':syntax', ':tests'; use Dancer::Test; use Test::More; plan tests => 28; # multiple token { get '/:resource/:id.:format' => sub { [ params->{'resource'}, params->{'id'}, params->{'format'} ]; }; my $response = dancer_response(GET => '/user/42.json'); ok( defined($response), "response found for '/user/42.json'" ); is_deeply( $response->content, ['user', '42', 'json'], "params are parsed as expected" ); } { ok( get( '/' => sub { 'index' } ), 'first route set' ); ok( get( '/hello/:name' => sub { param 'name' } ), 'second route set' ); ok( get( '/hello/:foo/bar' => sub { param 'foo' } ), 'third route set' ); ok( post( '/new/:stuff' => sub { param 'stuff'} ), 'post 1 route set' ); ok( post( '/allo' => sub { request->body } ), 'post 2 route set' ); get '/opt/:name?/?:lastname?' => sub { [ params->{name}, params->{lastname} ]; }; my @tests = ( { method => 'GET', path => '/', expected => 'index' }, { method => 'GET', path => '/hello/sukria', expected => 'sukria' }, { method => 'GET', path => '/hello/joe/bar', expected => 'joe' }, { method => 'POST', path => '/new/wine', expected => 'wine' }, { method => 'GET', path => '/opt/', expected => [ undef, undef ] }, { method => 'GET', path => '/opt/placeholder', expected => [ 'placeholder', undef ] }, { method => 'GET', path => '/opt/alexis/sukrieh', expected => [ "alexis", "sukrieh" ] }, ); foreach my $test (@tests) { my $req = [ $test->{method}, $test->{path} ]; route_exists $req; if ( ref( $test->{expected} ) ) { response_content_is_deeply $req => $test->{expected}; } else { response_content_is $req => $test->{expected}; } # splat should not be set ok( !exists( params->{'splat'} ), "splat not defined for " . $test->{path} ); } } libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/24_named_captures.t0000644000175000017500000000151712233013020024705 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; plan tests => 2; SKIP: { skip "Need perl >= 5.10", 2 unless $] >= 5.010; my $route_regex = "/(? user | content | post )/(? delete | find )/(? \\d+ )"; get qr{$route_regex}x => sub {captures}; for my $test ( { path => '/user/delete/234', expected => {qw/ class user action delete id 234 /} } ) { my $handle; my $path = $test->{path}; my $expected = $test->{expected}; my $request = [GET => $path]; response_status_is $request => 200; response_content_is_deeply $request => $expected; } } # perl <= 5.8.x doesn't support named captures #plan skip_all => 'Need perl >= 5.10' if $] < 5.010; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/21_ajax.t0000644000175000017500000000607412233013707022652 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); use LWP::UserAgent; plan tests => 43; ok(Dancer::App->current->registry->is_empty, "registry is empty"); ok(Dancer::Plugin::Ajax::ajax( '/', sub { "ajax" } ), "ajax helper called"); ok(!Dancer::App->current->registry->is_empty, "registry is not empty"); Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my @queries = ( { path => 'req', ajax => 1, success => 1, content => 1 }, { path => 'req', ajax => 0, success => 0 }, { path => 'foo', ajax => 1, success => 1, content => 'ajax' }, { path => 'foo', ajax => 0, success => 1, content => 'not ajax' }, { path => 'bar', ajax => 1, success => 1, content => 'ajax' }, { path => 'bar', ajax => 0, success => 1, content => 'not ajax' }, { path => 'layout', ajax => 0, success => 1, content => 'wibble' }, { path => 'die', ajax => 1, success => 0 }, { path => 'layout', ajax => 0, success => 1, content => 'wibble' }, ); foreach my $query (@queries) { ok my $request = HTTP::Request->new( GET => "http://127.0.0.1:$port/" . $query->{path} ); $request->header( 'X-Requested-With' => 'XMLHttpRequest' ) if ( $query->{ajax} == 1); ok my $res = $ua->request($request); if ( $query->{success} == 1) { ok $res->is_success; is $res->content, $query->{content}; like $res->header('Content-Type'), qr/text\/xml/ if $query->{ajax} == 1; } else { ok !$res->is_success; } } # test ajax with content_type to json ok my $request = HTTP::Request->new( GET => "http://127.0.0.1:$port/ajax.json" ); $request->header( 'X-Requested-With' => 'XMLHttpRequest' ); ok my $res = $ua->request($request); like $res->header('Content-Type'), qr/json/; }, server => sub { my $port = shift; use Dancer; use Dancer::Plugin::Ajax; set startup_info => 0, port => $port, layout => 'wibble'; ajax '/req' => sub { return 1; }; get '/foo' => sub { return 'not ajax'; }; ajax '/foo' => sub { return 'ajax'; }; get '/bar' => sub { return 'not ajax'; }; get '/bar', {ajax => 1} => sub { return 'ajax'; }; get '/ajax.json' => sub { content_type('application/json'); return '{"foo":"bar"}'; }; ajax '/die' => sub { die; }; get '/layout' => sub { return setting 'layout'; }; start(); }, ); libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/35_no_further_routes.t0000644000175000017500000000072112233013707025501 0ustar gregoagregoapackage MyTest; use strict; use warnings; use Test::More import => [ '!pass' ]; plan tests => 3; use Dancer; use Dancer::Test; get '/user/*/**' => sub { var user => (splat)[0]; pass; }; get '/user/:id/useful_method' => sub { var 'user'; }; response_status_is '/user/yanick/wacka' => 404, "route doesn't exist"; response_status_is '/user/yanick/useful_method' => 200, 'route exists'; response_content_is '/user/yanick/useful_method' => 'yanick'; libdancer-perl-1.3120+dfsg.orig/t/03_route_handler/04_wildcards_megasplat.t0000644000175000017500000000106012233013020025713 0ustar gregoagregoause Dancer ':tests'; use Test::More; use Dancer::Test; plan tests => 4; get '/foo/**' => sub { show_splat() }; response_content_is [ GET => '/foo/a/b/c' ] => '(a,b,c)'; get '/bar/*/**' => sub { show_splat() }; response_content_is [ GET => '/bar/a/b/c' ] => 'a:(b,c)'; get '/alpha/**/gamma' => sub { show_splat() }; response_content_is [ GET => '/alpha/beta/delta/gamma' ] => '(beta,delta)'; response_content_is [ GET => '/alpha/beta/gamma' ] => '(beta)'; sub show_splat { return join ':', map { ref $_ ? "(" . join( ',', @$_ ) . ")": $_ } splat; } libdancer-perl-1.3120+dfsg.orig/t/TestAppExt.pm0000644000175000017500000000022312233013020020454 0ustar gregoagregoapackage TestAppExt; use strict; use warnings; use lib 't'; use Dancer ':syntax'; use TestPlugin; sub test_app_func { test_plugin_symbol() } 1; libdancer-perl-1.3120+dfsg.orig/t/23_dancer_tests/0000755000175000017500000000000012256332256021066 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/23_dancer_tests/02_tests_functions.t0000644000175000017500000000614612233013710024777 0ustar gregoagregoause strict; use warnings; use Test::More; plan tests => 35; use Dancer qw/ :syntax :tests /; use Dancer::Test; # verify that all test helper functions are behaving the way # we want our $route = '/marco'; get $route => sub { 'polo' }; my $users = {}; my $last_id = 0; get '/user/:id' => sub { my $id = params->{'id'}; { user => $users->{$id} }; }; post '/user' => sub { my $id = ++$last_id; my $user = params('body'); $user->{id} = $id; $users->{$id} = $user; { user => $users->{$id} }; }; del '/user/:id' => sub { my $id = params->{'id'}; my $deleted = $users->{$id}; delete $users->{$id}; { user => $deleted }; }; get '/query' => sub { return join(":",params('query')); }; post '/upload' => sub { return upload('payload')->content; }; any '/headers' => sub { return request->headers; }; my $resp = dancer_response GET => '/marco'; my @req = ( [ GET => $route ], $route, $resp ); test_helping_functions( $_ ) for @req; response_status_is [ GET => '/satisfaction' ], 404, 'response_doesnt_exist'; response_status_isnt [ GET => '/marco' ], 404, 'response_exists'; sub test_helping_functions { my $req = shift; response_status_is $req => 200; response_status_isnt $req => 613; response_content_is $req => 'polo'; response_content_isnt $req => 'stuff'; response_content_is_deeply $req => 'polo'; response_content_like $req => qr/.ol/; response_content_unlike $req => qr/\d/; } ## POST my $r = dancer_response( POST => '/user', { body => { name => 'Alexis' } } ); is_deeply $r->{content}, { user => { id => 1, name => "Alexis" } }, "create user works"; $r = dancer_response( GET => '/user/1' ); is_deeply $r->{content}, { user => { id => 1, name => 'Alexis' } }, "user 1 is defined"; $r = dancer_response( DELETE => '/user/1' ); is_deeply $r->{content}, { user => { id => 1, name => 'Alexis', } }, "user 1 is deleted"; $r = dancer_response( POST => '/user', { body => { name => 'Franck Cuny' } } ); is_deeply $r->{content}, { user => { id => 2, name => "Franck Cuny" } }, "id is correctly increased"; $r = dancer_response( GET => '/query', { params => {foo => 'bar'}}); is $r->{content}, "foo:bar", 'passed fake query params'; $r = dancer_response( GET => '/query?foo=bar' ); is $r->{content}, "foo:bar", 'passed params in query'; my $data = "She sells sea shells by the sea shore"; $r = dancer_response( POST => '/upload', { files => [{name => 'payload', filename =>'test.txt', data => $data }] } ); is $r->{content}, $data, "file data uploaded"; $r = dancer_response(GET => '/headers'); isa_ok $r->content, 'HTTP::Headers', 'The request headers'; $r = dancer_response(POST => '/headers', { headers => [ 'Content_Type' => "text/plain" ] }); isa_ok $r->content, 'HTTP::Headers', 'The request headers'; is $r->content->header('Content-Type'), "text/plain", "Content-Type preserved"; $r = dancer_response(POST => '/headers', { headers => HTTP::Headers->new('Content-Type' => "text/plain" ) }); isa_ok $r->{content}, 'HTTP::Headers', 'The request headers'; is $r->content->header('Content-Type'), "text/plain", "Content-Type preserved"; libdancer-perl-1.3120+dfsg.orig/t/23_dancer_tests/01_basic.t0000644000175000017500000000405112233013710022616 0ustar gregoagregoause Test::More import => ['!pass'], tests => 20; use strict; use warnings; use Dancer ':syntax'; use Dancer::Test; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); load_app 'TestApp'; # in t::lib::TestApp, we have # get '/' => sub { "Hello, this is the home" }; my $req = [GET => '/']; my $false_req = [ GET => '/false/route' ]; route_exists $req; route_doesnt_exist $false_req; response_status_is $req => 200; response_status_is $false_req => 404; response_content_is $req => "Hello, this is the home"; response_content_isnt $req => "foo bar"; response_content_is_deeply [GET => '/hash'] => { a => 1, b => 2, c => 3}; response_content_like $req => qr{Hello}; response_content_unlike $req => qr{Goodbye}; response_headers_include [GET => '/with_headers'], [ 'Content-Type' => 'text/html' ]; response_headers_include [GET => '/with_headers'], [ 'X-Foo-Dancer' => '42' ]; my $resp = dancer_response(@$req); is $resp->{status}, 200, "response status from dancer_response looks good"; response_content_is [PUT => '/jsondata', { body => 42 }], 42, "a request with a body looks good"; response_content_is [POST => '/name', { params => {name => 'Bob'} }], "Your name: Bob", "a request with params looks good"; response_content_is [GET => '/headers_again', { headers => ['X-Foo-Dancer' => 55] }], 55, "a request with headers looks good"; response_content_is [ POST => '/form', { headers => [ 'Content-Type' => 'application/x-www-form-urlencoded' ], body => 'foo=bar' } ], 'bar', "a POST request with form urlencoded is ok"; note "capture logs"; { is setting("logger"), "capture"; is setting("log"), "debug"; warning "Danger! Warning!"; debug "I like pie."; is_deeply read_logs, [ { level => "warning", message => "Danger! Warning!" }, { level => "debug", message => "I like pie.", } ], "read_logs"; error "Put out the light."; is_deeply read_logs, [ { level => "error", message => "Put out the light." }, ], "each read clears the trap"; } libdancer-perl-1.3120+dfsg.orig/t/02_request/0000755000175000017500000000000012256332256020075 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/02_request/04_custom.t0000644000175000017500000000205112233013707022065 0ustar gregoagregoause Test::More tests => 8; use strict; use warnings FATAL => 'all'; use Dancer::Request; %ENV = ( 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/', 'PATH_INFO' => '/', 'QUERY_STRING' => 'foo=bar&number=42', ); my $req = Dancer::Request->new(env => \%ENV); is $req->path, '/', 'path is /'; is $req->method, 'GET', 'method is get'; is_deeply scalar($req->params), {foo => 'bar', number => 42}, 'params are parsed'; $req = Dancer::Request->new_for_request('GET', '/stuff'); is $req->path, '/stuff', 'path is changed'; is $req->method, 'GET', 'method is changed'; is_deeply scalar($req->params), {foo => 'bar', number => 42}, 'params are not touched'; $req = Dancer::Request->new_for_request('GET', '/stuff', {user => 'sukria'}); is_deeply scalar($req->params), {foo => 'bar', number => 42, user => 'sukria'}, 'params are updated'; $req = Dancer::Request->new_for_request('GET', '/stuff?foo=baz&number=24'); is_deeply scalar($req->params), {foo => 'baz', number => 24}, 'query string replace'; libdancer-perl-1.3120+dfsg.orig/t/02_request/01_load.t0000644000175000017500000000006612233013020021457 0ustar gregoagregoause Test::More tests => 1; use_ok 'Dancer::Request'; libdancer-perl-1.3120+dfsg.orig/t/02_request/07_raw_data.t0000644000175000017500000000233112233013707022341 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer::ModuleLoader; use Dancer; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); use LWP::UserAgent; use constant RAW_DATA => "var: 2; foo: 42; bar: 57\nHey I'm here.\r\n\r\n"; plan tests => 2; Test::TCP::test_tcp( client => sub { my $port = shift; my $rawdata = RAW_DATA; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(PUT => "http://127.0.0.1:$port/jsondata"); my $headers = { 'Content-Length' => length($rawdata) }; $req->push_header($_, $headers->{$_}) foreach keys %$headers; $req->content($rawdata); my $res = $ua->request($req); ok $res->is_success, 'req is success'; is $res->content, $rawdata, "raw_data is OK"; }, server => sub { my $port = shift; use TestApp; Dancer::Config->load; set( environment => 'production', port => $port, startup_info => 0); Dancer->dance(); }, ); libdancer-perl-1.3120+dfsg.orig/t/02_request/13_ajax.t0000644000175000017500000000312612233013707021502 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan tests => 8; use LWP::UserAgent; use HTTP::Headers; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $request = HTTP::Request->new(GET => "http://127.0.0.1:$port/req"); $request->header('X-Requested-With' => 'XMLHttpRequest'); my $res = $ua->request($request); ok($res->is_success, "server responded"); is($res->content, 1, "content ok"); $request = HTTP::Request->new(GET => "http://127.0.0.1:$port/req"); $res = $ua->request($request); ok($res->is_success, "server responded"); is($res->content, 0, "content ok"); }, server => sub { my $port = shift; use Dancer; set (port => $port, startup_info => 0); get '/req' => sub { request->is_ajax ? return 1 : return 0; }; Dancer->dance(); }, ); # basic interface $ENV{REQUEST_METHOD} = 'GET'; $ENV{PATH_INFO} = '/'; my $request = Dancer::Request->new(env => \%ENV); is $request->method, 'GET'; ok !$request->is_ajax, 'no headers'; my $headers = HTTP::Headers->new('foo' => 'bar'); $request->headers($headers); ok !$request->is_ajax, 'no requested_with headers'; $headers = HTTP::Headers->new('X-Requested-With' => 'XMLHttpRequest'); $request->headers($headers); ok $request->is_ajax; libdancer-perl-1.3120+dfsg.orig/t/02_request/16_delete.t0000644000175000017500000000051112233013020022003 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Request; plan tests => 3; $ENV{REQUEST_METHOD} = 'DELETE'; $ENV{PATH_INFO} = '/'; my $req = Dancer::Request->new(env => \%ENV); is $req->path, '/', 'path is set'; is $req->method, 'DELETE', 'method is delete'; ok $req->is_delete, 'request is delete'; libdancer-perl-1.3120+dfsg.orig/t/02_request/06_init_env.t0000644000175000017500000000335112233013020022360 0ustar gregoagregoause Test::More; use strict; use warnings FATAL => 'all'; use Dancer::Request; my $custom_env = { 'SERVER_PORT' => 3000, SERVER_PROTOCOL => 'http', 'QUERY_STRING' => 'foo=bar', 'PATH_INFO' => '/stuff', 'REQUEST_METHOD' => 'GET', 'XAUTHORITY' => '/var/run/gdm/auth-for-sukria-6en6nX/database', 'HTTP_ACCEPT' => 'image/png,image/*;q=0.8,*/*;q=0.5; text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.5) Gecko/20091109 Ubuntu/9.10 (karmic) Firefox/3.5.5; Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.5) Gecko/20091109 Ubuntu/9.10 (karmic) Firefox/3.5.5', 'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3; fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7; ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'HTTP_HOST' => 'localhost:3000; localhost:3000', 'HTTP_KEEP_ALIVE' => '300; 300', 'HTTP_ACCEPT_ENCODING' => 'gzip,deflate; gzip,deflate', 'HTTP_CONNECTION' => 'keep-alive; keep-alive', }; my @http_env = grep /^HTTP_/, keys (%$custom_env); plan tests => 6 + (2 * scalar(@http_env)); my $req = Dancer::Request->new(env => $custom_env); is $req->path, '/stuff', 'path is set from custom env'; is $req->method, 'GET', 'method is set from custom env'; is_deeply scalar($req->params), {foo => 'bar'}, 'params are set from custom env'; is $req->port, 3000, 'port is ok'; is $req->protocol, 'http', 'protocol is ok'; ok !$req->secure, 'not https'; foreach my $http (@http_env) { my $key = lc $http; $key =~ s/^http_//; is $req->{$key}, $custom_env->{$http}, "$http is found in request ($key)"; is $req->$key, $custom_env->{$http}, "$key is an accessor"; } libdancer-perl-1.3120+dfsg.orig/t/02_request/17_uri_base.t0000644000175000017500000000127512233013020022343 0ustar gregoagregoause Test::More; use Dancer::Request; plan tests => 2; my $env = { 'psgi.url_scheme' => 'http', REQUEST_METHOD => 'GET', SCRIPT_NAME => '/', PATH_INFO => '/bar/baz', REQUEST_URI => '/foo/bar/baz', QUERY_STRING => '', SERVER_NAME => 'localhost', SERVER_PORT => 5000, SERVER_PROTOCOL => 'HTTP/1.1', }; my $req = Dancer::Request->new(env => $env); is( $req->uri_base, 'http://localhost:5000', 'remove trailing slash if only one', ); $env->{'SCRIPT_NAME'} = '/foo/'; $req = Dancer::Request->new(env => $env); is( $req->uri_base, 'http://localhost:5000/foo/', 'keeping trailing slash if not only', ); libdancer-perl-1.3120+dfsg.orig/t/02_request/18_param_accessor.t0000644000175000017500000000026212233013020023530 0ustar gregoagregoause Test::More; plan tests => 1; { use Dancer ':tests'; get '/:foo' => sub { param 'foo'; }; } use Dancer::Test; response_content_is [GET => '/42'], 42; libdancer-perl-1.3120+dfsg.orig/t/02_request/08_params.t0000644000175000017500000000753412233013707022055 0ustar gregoagregoause Test::More tests => 26; use strict; use warnings FATAL => 'all'; use Dancer::Request; { # 1. - get params $ENV{REQUEST_METHOD} = 'GET'; $ENV{PATH_INFO} = '/'; for my $separator ('&', ';') { $ENV{QUERY_STRING} = join($separator, ('name=Alexis%20Sukrieh', 'IRC%20Nickname=sukria', 'Project=Perl+Dancer', 'hash=2', 'hash=4', 'int1=1', 'int2=0', 'url=http://foo.com/?bar=biz')); my $expected_params = { 'name' => 'Alexis Sukrieh', 'IRC Nickname' => 'sukria', 'Project' => 'Perl Dancer', 'hash' => [2, 4], int1 => 1, int2 => 0, url => 'http://foo.com/?bar=biz', }; my $req = Dancer::Request->new(env => \%ENV); is $req->path, '/', 'path is set'; is $req->method, 'GET', 'method is set'; ok $req->is_get, "request method is GET"; is_deeply scalar($req->params), $expected_params, 'params are OK'; is_deeply scalar($req->Vars), $expected_params, 'params are OK (using Vars)'; is $req->params->{'name'}, 'Alexis Sukrieh', 'params accessor works'; my %params = $req->params; is_deeply scalar($req->params), \%params, 'params wantarray works'; } } { # 2. - post params my $body = 'foo=bar&name=john&hash=2&hash=4&hash=6&'; open my $in, '<', \$body; my $env = { CONTENT_LENGTH => length($body), CONTENT_TYPE => 'application/x-www-form-urlencoded', REQUEST_METHOD => 'POST', SCRIPT_NAME => '/', 'psgi.input' => $in, }; my $expected_params = { name => 'john', foo => 'bar', hash => [2, 4, 6], }; my $req = Dancer::Request->new(env => $env); is $req->path, '/', 'path is set'; is $req->method, 'POST', 'method is set'; ok $req->is_post, 'method is post'; my $request_to_string = $req->to_string; like $request_to_string, qr{\[#\d+\] POST /}; is_deeply scalar($req->params), $expected_params, 'params are OK'; is $req->params->{'name'}, 'john', 'params accessor works'; my %params = $req->params; is_deeply scalar($req->params), \%params, 'params wantarray works'; } { # 3. - mixed params my $body = 'x=1&meth=post'; open my $in, '<', \$body; my $env = { CONTENT_LENGTH => length($body), CONTENT_TYPE => 'application/x-www-form-urlencoded', QUERY_STRING => 'y=2&meth=get', REQUEST_METHOD => 'POST', SCRIPT_NAME => '/', 'psgi.input' => $in, }; my $mixed_params = { meth => 'post', x => 1, y => 2, }; my $get_params = { y => 2, meth => 'get', }; my $post_params = { x => 1, meth => 'post', }; my $req = Dancer::Request->new(env => $env); is $req->path, '/', 'path is set'; is $req->method, 'POST', 'method is set'; is_deeply scalar($req->params), $mixed_params, 'params are OK'; is_deeply scalar($req->params('body')), $post_params, 'body params are OK'; is_deeply scalar($req->params('query')), $get_params, 'query params are OK'; } libdancer-perl-1.3120+dfsg.orig/t/02_request/12_base.t0000644000175000017500000000262712233013707021475 0ustar gregoagregoause Test::More; use Dancer::Request; plan tests => 11; my $env = { 'psgi.url_scheme' => 'http', REQUEST_METHOD => 'GET', SCRIPT_NAME => '/foo', PATH_INFO => '/bar/baz', REQUEST_URI => '/foo/bar/baz', QUERY_STRING => '', SERVER_NAME => 'localhost', SERVER_PORT => 5000, SERVER_PROTOCOL => 'HTTP/1.1', }; my $req = Dancer::Request->new(env => $env); is $req->base, 'http://localhost:5000/foo'; is $req->uri_for('bar', { baz => 'baz' }), 'http://localhost:5000/foo/bar?baz=baz'; is $req->uri_for('/bar'), 'http://localhost:5000/foo/bar'; ok $req->uri_for('/bar')->isa('URI'), 'uri_for returns a URI'; ok $req->uri_for('/bar', undef, 1)->isa('URI'), 'uri_for returns a URI (with $dont_escape)'; is $req->request_uri, '/foo/bar/baz'; is $req->path_info, '/bar/baz'; { local $env->{SCRIPT_NAME} = ''; is $req->uri_for('/foo'), 'http://localhost:5000/foo'; } { local $env->{SERVER_NAME} = 0; is $req->base, 'http://0:5000/foo'; local $env->{HTTP_HOST} = 'oddhostname:5000'; is $req->base, 'http://oddhostname:5000/foo'; } subtest '$dont_escape' => sub { plan tests => 2; my $url = '/bar?a=1&b=2'; is $req->uri_for($url) => 'http://localhost:5000/foo/bar%3Fa=1&b=2', 'escaped'; is $req->uri_for( '/bar?a=1&b=2', {}, 1) => 'http://localhost:5000/foo/bar?a=1&b=2', 'unescaped'; } libdancer-perl-1.3120+dfsg.orig/t/02_request/05_cgi_pm_compat.t0000644000175000017500000000064712233013020023352 0ustar gregoagregoause Test::More tests => 5; use strict; use warnings FATAL => 'all'; use Dancer::Request; my $req = Dancer::Request->new_for_request(get => '/stuff'); is $req->path, '/stuff', "path is set"; is $req->method, 'GET', "method is set"; is $req->path_info, '/stuff', 'path_info alias reads'; $req->path_info('/other'); is $req->path_info, '/other', 'path_info alias writes'; is $req->request_method, 'GET', 'method is set'; libdancer-perl-1.3120+dfsg.orig/t/02_request/000_create_fake_env.t0000644000175000017500000000052412233013020023717 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4, import => ['!pass']; foreach my $dir ( qw/ public logs views lib / ) { my $new_dir = File::Spec->catdir( dirname($0), $dir ); ok( ( -d $new_dir or mkpath($new_dir) ), "Created $new_dir", ); } libdancer-perl-1.3120+dfsg.orig/t/02_request/10_mixed_params.t0000644000175000017500000000277712233013707023240 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); use LWP::UserAgent; plan tests => 2; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $res = $ua->post("http://127.0.0.1:$port/params/route?a=1&var=query", {var => 'post', b => 2}); ok $res->is_success, 'req is success'; my $content = $res->content; my $VAR1; eval ("$content"); my $expected = { params => { a => 1, b => 2, var => 'post', }, body => { var => 'post', b => 2 }, query => { a => 1, var => 'query' }, route => { var => 'route' } }; is_deeply $VAR1, $expected, "parsed params are OK"; }, server => sub { my $port = shift; use TestApp; Dancer::Config->load; set ( environment => 'production', port => $port, startup_info => 0); Dancer->dance(); }, ); libdancer-perl-1.3120+dfsg.orig/t/02_request/11_accessors.t0000644000175000017500000000254512233013707022546 0ustar gregoagregoause Test::More tests => 15; use strict; use warnings; use Dancer::Request; my $env = { 'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/', 'REQUEST_URI' => '/', 'CONTENT_TYPE' => 'text/plain', 'REMOTE_ADDR' => '192.168.0.2', 'CONTENT_LENGTH' => 42, 'X_FORWARDED_FOR' => '192.168.0.3', 'HTTP_USER_AGENT' => 'Mozy', 'HTTP_HOST' => 'foo.bar.com', 'REMOTE_USER' => 'franck', 'REQUEST_BASE' => '/app-root', }; my $r = Dancer::Request->new(env => $env); is_deeply $r->env, $env, "environement looks good"; is $r->path, $env->{PATH_INFO}, 'path looks good'; is $r->method, $env->{REQUEST_METHOD}, 'method looks good'; is $r->content_type, $env->{CONTENT_TYPE}, 'content_type looks good'; is $r->content_length, $env->{CONTENT_LENGTH}, 'content_length looks good'; is $r->body, '', 'body looks good'; is $r->user_agent, 'Mozy', 'user_agent looks good'; is $r->agent, 'Mozy', 'agent looks good'; is $r->host, 'foo.bar.com', 'host looks good'; is $r->remote_address, '192.168.0.2', 'remote address looks good'; is $r->forwarded_for_address, '192.168.0.3', 'forwarded address looks good'; is $r->user, 'franck', 'remote user looks good'; is $r->request_uri, '/', 'request_uri looks good'; is $r->uri, $r->request_uri, '->uri is an alis on ->request_uri'; is $r->request_base, '/app-root', 'request_base looks good'; libdancer-perl-1.3120+dfsg.orig/t/02_request/14_uploads.t0000644000175000017500000001274112233013707022232 0ustar gregoagregoause strict; use warnings; use Dancer ':syntax'; use Dancer::Request; use Dancer::Test; use Dancer::FileUtils; use Test::More 'import' => ['!pass']; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); sub test_path { my ($file, $dir) = @_; is dirname($file), $dir, "dir of $file is $dir"; } my $filename = "some_\x{1A9}_file.txt"; my $filename_as_bytes = $filename; if ( $] >= 5.017009 ) { # The following song-and-dance is because Perl has, in 5.17.9, # started flagging wide characters in in-memory files as errors, to # wit: # Strings with code points over 0xFF may not be mapped into # in-memory file handles open my $out, '>:encoding(utf8)', \$filename_as_bytes; print { $out } "some_\x{1A9}_file.txt"; close $out; } my $content = qq{------BOUNDARY Content-Disposition: form-data; name="test_upload_file"; filename="$filename_as_bytes" Content-Type: text/plain SHOGUN ------BOUNDARY Content-Disposition: form-data; name="test_upload_file"; filename="yappo2.txt" Content-Type: text/plain SHOGUN2 ------BOUNDARY Content-Disposition: form-data; name="test_upload_file3"; filename="yappo3.txt" Content-Type: text/plain SHOGUN3 ------BOUNDARY Content-Disposition: form-data; name="test_upload_file4"; filename="yappo4.txt" Content-Type: text/plain SHOGUN4 ------BOUNDARY Content-Disposition: form-data; name="test_upload_file4"; filename="yappo5.txt" Content-Type: text/plain SHOGUN4 ------BOUNDARY Content-Disposition: form-data; name="test_upload_file6"; filename="yappo6.txt" Content-Type: text/plain SHOGUN6 ------BOUNDARY-- }; $content =~ s/\r\n/\n/g; $content =~ s/\n/\r\n/g; plan tests => 21; do { open my $in, '<', \$content; my $req = Dancer::Request->new( env => { 'psgi.input' => $in, CONTENT_LENGTH => length($content), CONTENT_TYPE => 'multipart/form-data; boundary=----BOUNDARY', REQUEST_METHOD => 'POST', SCRIPT_NAME => '/', SERVER_PORT => 80, } ); Dancer::SharedData->request($req); my @undef = $req->upload('undef'); is @undef, 0, 'non-existent upload as array is empty'; my $undef = $req->upload('undef'); is $undef, undef, '... and non-existent upload as scalar is undef'; my @uploads = upload('test_upload_file'); like $uploads[0]->content, qr|^SHOGUN|, "content for first upload is ok, via 'upload'"; like $uploads[1]->content, qr|^SHOGUN|, "... content for second as well"; is $req->uploads->{'test_upload_file4'}[0]->content, 'SHOGUN4', "... content for other also good"; note "headers"; is_deeply $uploads[0]->headers, { 'Content-Disposition' => qq[form-data; name="test_upload_file"; filename="$filename"], 'Content-Type' => 'text/plain', }; note "type"; is $uploads[0]->type, 'text/plain'; my $test_upload_file3 = $req->upload('test_upload_file3'); is $test_upload_file3->content, 'SHOGUN3', "content for upload #3 as a scalar is good, via req->upload"; my @test_upload_file6 = $req->upload('test_upload_file6'); is $test_upload_file6[0]->content, 'SHOGUN6', "content for upload #6 is good"; my $upload = $req->upload('test_upload_file6'); isa_ok $upload, 'Dancer::Request::Upload'; is $upload->filename, 'yappo6.txt', 'filename is ok'; ok $upload->file_handle, 'file handle is defined'; is $req->params->{'test_upload_file6'}, 'yappo6.txt', "filename is accessible via params"; # copy_to, link_to my $dest_dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $dest_file = File::Spec->catfile( $dest_dir, $upload->basename ); $upload->copy_to($dest_file); ok( ( -f $dest_file ), "file '$dest_file' has been copied" ); my $dest_file_link = File::Spec->catfile( $dest_dir, "hardlink" ); $upload->link_to( $dest_file_link ); ok( ( -f $dest_file_link ), "hardlink '$dest_file_link' has been created" ); # make sure cleanup is performed when the HTTP::Body object is purged my $file = $upload->tempname; ok( ( -f $file ), 'temp file exists while HTTP::Body lives' ); undef $req->{_http_body}; SKIP: { skip "Win32 can't remove file/link while open, deadlock with HTTP::Body", 1 if ($^O eq 'MSWin32'); ok( ( !-f $file ), 'temp file is removed when HTTP::Body object dies' ); } unlink($file) if ($^O eq 'MSWin32'); }; # test with Dancer::Test my $dest_dir = File::Temp::tempdir(CLEANUP => 1, TMPDIR => 1); my $dest_file = File::Spec->catfile( $dest_dir, 'foo' ); post( '/upload', sub { my $file = upload('test'); is $file->{filename}, $dest_file; return $file->content; } ); post( '/uploads', sub { my $content; my $uploads = request->uploads; foreach my $u (keys %$uploads){ $content .= $uploads->{$u}->content; } return $content; } ); $content = "foo"; open my $fh, '>', $dest_file; print $fh $content; close $fh; my $resp = dancer_response( 'POST', '/upload', { files => [ { name => 'test', filename => $dest_file } ] } ); is $resp->content, $content; my $files; for (qw/a b c/){ my $dest_file = File::Spec->catfile( $dest_dir, $_ ); open my $fh, '>', $dest_file; print $fh $_; close $fh; push @$files, {name => $_, filename => $dest_file}; } $resp = dancer_response( 'POST', '/uploads', {files => $files}); is length($resp->content), 3; like $resp->content, qr/a/; libdancer-perl-1.3120+dfsg.orig/t/02_request/15_headers.t0000644000175000017500000000363212233013707022176 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => 'Test::TCP is needed to run this test' unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); use LWP::UserAgent; my $plack_available = Dancer::ModuleLoader->load('Plack::Request'); Dancer::ModuleLoader->load('Plack::Loader') if $plack_available; plan tests => $plack_available ? 12 : 6; my @handlers = ('Standalone'); push @handlers, 'PSGI' if $plack_available; for my $handler (@handlers) { Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = LWP::UserAgent->new; my $request = HTTP::Request->new(GET => "http://127.0.0.1:$port/req"); $request->header('X-User-Head1' => 42); $request->header('X-User-Head2' => 43); my $res = $ua->request($request); ok($res->is_success, "$handler server responded"); is($res->header('X-Foo'), 2); is($res->header('X-Bar'), 3); is($res->header('Content-Type'), 'text/plain'); }, server => sub { my $port = shift; use Dancer; set( apphandler => $handler, port => $port, show_errors => 1, startup_info => 0 ); hook after => sub { my $response = shift; $response->header('X-Foo', 2); }; get '/req' => sub { is(request->header('X-User-Head1'), 42, "header X-User-Head1 is ok"); is(request->header('X-User-Head2'), 43, "header X-User-Head2 is ok"); headers('X-Bar', 3); content_type('text/plain'); }; if ($handler eq 'PSGI') { my $app = Dancer::Handler->get_handler()->dance; Plack::Loader->auto(port => $port)->run($app); } else { Dancer->dance(); } }, ); } libdancer-perl-1.3120+dfsg.orig/t/02_request/04_forward.t0000644000175000017500000000132312233013020022204 0ustar gregoagregoause Test::More tests => 6; use strict; use warnings FATAL => 'all'; use Dancer::Request; %ENV = ( 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/', 'PATH_INFO' => '/', 'QUERY_STRING' => 'foo=bar&number=42', ); my $req = Dancer::Request->new(env => \%ENV); is $req->path, '/', 'path is /'; is $req->method, 'GET', 'method is get'; is_deeply scalar($req->params), {foo => 'bar', number => 42}, 'params are parsed'; $req = Dancer::Request->forward($req, { to_url => "/new/path"} ); is $req->path, '/new/path', 'path is changed'; is $req->method, 'GET', 'method is unchanged'; is_deeply scalar($req->params), {foo => 'bar', number => 42}, 'params are not touched'; libdancer-perl-1.3120+dfsg.orig/t/16_timer/0000755000175000017500000000000012256332256017532 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/16_timer/00_base.t0000644000175000017500000000067712233013020021116 0ustar gregoagregoause strict; use warnings; use Test::More tests => 7; use_ok 'Dancer::Timer'; my $timer = Dancer::Timer->new; ok(defined($timer), "timer is defined"); isa_ok($timer, 'Dancer::Timer'); can_ok($timer, 'tick'); ok(defined($timer->start_time), "start_time is defined"); my $t1 = $timer->tick; sleep 1; my $t2 = $timer->tick; ok(($t2 > $t1), "tick has been increased: ".$timer->tick); ok(length($timer->to_string), "to_string returned a string"); libdancer-perl-1.3120+dfsg.orig/t/00_base/0000755000175000017500000000000012256332256017315 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/00_base/010_export_script.t0000644000175000017500000000031112233013020022736 0ustar gregoagregoause Test::More import => ["!pass"]; use Dancer ':script'; plan tests => 2; ok(exists($::{'get'}), "symbol `get' is exported"); use Cwd; ok setting("appdir"), ":script with exports allow app setup"; libdancer-perl-1.3120+dfsg.orig/t/00_base/views/0000755000175000017500000000000012256332256020452 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/00_base/views/unicode.tt0000644000175000017500000000011412233013020022421 0ustar gregoagregoasigma: 'Ʃ' pure_token: '<% pure_token %>' param_token: '<% param_token %>' libdancer-perl-1.3120+dfsg.orig/t/00_base/12_utf8_charset.t0000644000175000017500000000323412233013707022375 0ustar gregoagregoause strict; use warnings; use utf8; use Encode; use Test::More import => ['!pass']; use Dancer::ModuleLoader; use LWP::UserAgent; plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => '1.30'); plan tests => 4; Test::TCP::test_tcp( client => sub { my $port = shift; my $res; $res = _get_http_response(GET => '/string', $port); is d($res->content), "\x{1A9}", "utf8 static response"; $res = _get_http_response(GET => '/other/string', $port); is d($res->content), "\x{1A9}", "utf8 response through forward"; $res = _get_http_response(GET => "/param/".u("\x{1A9}"), $port); is d($res->content), "\x{1A9}", "utf8 route param"; $res = _get_http_response(GET => "/view?string1=".u("\x{E9}"), $port); is d($res->content), "sigma: 'Ʃ'\npure_token: 'Ʃ'\nparam_token: '\x{E9}'\n", "params and tokens are valid unicode"; }, server => sub { my $port = shift; use Dancer; use t::lib::TestAppUnicode; set( charset => 'utf8', port => $port, show_errors => 1, startup_info => 0, log => 'debug', logger => 'console'); Dancer->dance(); }, ); sub u { encode('UTF-8', $_[0]); } sub d { decode('UTF-8', $_[0]); } sub _get_http_response { my ($method, $path, $port) = @_; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new($method => "http://127.0.0.1:$port${path}"); return $ua->request($req); } libdancer-perl-1.3120+dfsg.orig/t/00_base/13_dancer_singleton.t0000644000175000017500000000167512233013020023310 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 10; my $test_counter = 0; { package MySingleton; use base qw(Dancer::Object::Singleton); __PACKAGE__->attributes( qw/foo/ ); sub init { my ($class, $instance) = @_; $test_counter++; $instance->foo('bar'); } } eval { MySingleton->new() }; like $@, qr/you can't call 'new'/, 'new unauthorized'; eval { MySingleton->clone() }; like $@, qr/you can't call 'clone'/, 'clone unauthorized'; can_ok 'MySingleton', 'foo'; my $instance = MySingleton->instance(); ok $instance, 'instance build'; is $test_counter, 1, 'counter incremented'; is $instance->foo, 'bar', 'attribute is set'; $instance->foo('baz'); is $instance->foo, 'baz', 'attribute changed'; my $instance2 = MySingleton->instance(); ok $instance2, 'instance retrieved'; is $instance2, $instance, 'instance is the same'; is $test_counter, 1, 'counter was not incremented'; libdancer-perl-1.3120+dfsg.orig/t/00_base/004_args.t0000644000175000017500000000273512233013020021004 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use vars '@ARGV'; use Dancer::GetOpt; use Dancer; my @tests = ( { args => ['--port=2345'], expected => sub { setting('port') == 2345 } }, { args => ['--port', '2345'], expected => sub { setting('port') eq '2345' }}, { args => ['-p', '2345'], expected => sub { setting('port') eq '2345' }}, { args => ['--daemon'], expected => sub { setting('daemon') } }, { args => ['-d'], expected => sub { setting('daemon') } }, { args => ['--environment=production'], expected => sub { setting('environment') eq 'production' } }, { args => ['--confdir=/tmp/foo'], expected => sub { setting('confdir') eq '/tmp/foo'} }, { args => ['--restart=1'], expected => sub { setting('auto_reload') == 1}}, { args => ['--restart=0'], expected => sub { setting('auto_reload') == 0}}, ); plan tests => scalar(@tests) + 3; foreach my $test (@tests) { @ARGV = @{ $test->{args}}; Dancer::GetOpt->process_args(); ok($test->{expected}->(), "arg processing looks good for: ".join(' ', @{$test->{args}})); } ok(Dancer::GetOpt->print_usage()); # Dancer->import process ARGV @ARGV = ('--port=1234'); Dancer->import(); is setting('port'), 1234, "->import process ARGV"; # Dancer->import doesn't process ARGV when PLACK_ENV is set (GH#473) @ARGV = ('--port=4321'); $ENV{PLACK_ENV} = 'development'; Dancer->import(); is setting('port'), 1234, "->import doesn't process ARGV"; libdancer-perl-1.3120+dfsg.orig/t/00_base/15_dependent_modules.t0000644000175000017500000000130712233013020023462 0ustar gregoagregoause strict; use warnings; use Test::More; unless ( $ENV{RELEASE_TESTING} ) { plan( skip_all => "Author tests not required for installation" ); } eval "use Test::DependentModules"; plan skip_all => "Need Test::DependentModules for this test" if $@; my @modules = qw( Dancer::Plugin::Auth::Twitter Dancer::Plugin::DBIC Dancer::Plugin::Database Dancer::Plugin::FlashMessage Dancer::Plugin::MobileDevice Dancer::Plugin::REST Dancer::Session::Cookie Dancer::Session::Storable ); # install them in your perlbrew first if ($ENV{CPANM_RUN}) { `cpanm -n --quiet $_` for @modules ; } plan tests => scalar(@modules); Test::DependentModules::test_module($_) for @modules; libdancer-perl-1.3120+dfsg.orig/t/00_base/005_module_loader.t0000644000175000017500000000075712233013020022666 0ustar gregoagregoause strict; use warnings; use Test::More tests => 6; BEGIN { use_ok 'Dancer::ModuleLoader' } ok( Dancer::ModuleLoader->load("File::Spec"), "File::Spec is loaded" ); ok( File::Spec->rel2abs('.'), "File::Spec is imported" ); ok( !Dancer::ModuleLoader->load("Non::Existent::Module"), "fake module is not loaded" ); ok( Dancer::ModuleLoader->load("File::Spec", "1.0"), "File::Spec version >= 1.0 is loaded"); ok( !Dancer::ModuleLoader->load("File::Spec", "9999"), "Can't load File::Spec v9999"); libdancer-perl-1.3120+dfsg.orig/t/00_base/007_load_syntax.t0000644000175000017500000000025612233013020022374 0ustar gregoagregoause strict; use warnings; use Test::More tests => 2, import => ['!pass']; BEGIN { use_ok( 'Dancer', ':syntax' ); } ok( ! setting('appdir'), 'Syntax import' ); libdancer-perl-1.3120+dfsg.orig/t/00_base/14_changelog.t0000644000175000017500000002146112233013707021731 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; unless ( $ENV{RELEASE_TESTING} ) { plan( skip_all => "Author tests not required for installation" ); } #### Change these values if the Changelog syntax changes : # changelog file name my $changelog_filename = 'CHANGES'; # don't check for versions older or equal to this my $stop_checking_version = '1.3079_03'; # ordered list of possible sections my @possible_sections = ('SECURITY', 'API CHANGES', 'BUG FIXES', 'ENHANCEMENTS', 'DOCUMENTATION', ); ################# # beware : below are some crazy paranoid testing my $possible_sections = join('|', @possible_sections); open(my $fh, '<', $changelog_filename); my @lines = map { chomp; $_ } <$fh>; my $tests_count = 0; while (1) { $lines[$tests_count++] !~ /^\Q$stop_checking_version\E(?:\s|$)/ or last } # test count = number of lines + 1 plan tests => $tests_count; my @struct; { # start scoping my $line_nb = 0; my $line; sub _consume_line { $line = shift @lines; defined $line or goto END_CHANGES; $line =~ /^\Q$stop_checking_version\E(?:\s|$)/ and goto END_CHANGES; $line_nb++; } sub _peek_line { $line = $lines[0]; defined $line or goto END_CHANGES; $line =~ /^\Q$stop_checking_version\E(?:\s|$)/ and goto END_CHANGES; } sub _fail { fail("changelog error (line $line_nb): " . shift() . " line was : '$line'"); } sub _fail_bail_out { _fail(@_); BAIL_OUT("changelog is not safe enough to continue checking"); } sub _pass { Test::More::pass("check line $line_nb"); } my $current_version; my $current_version_is_dev; my $current_section; my $current_item_start; my $current_item; WHERE_NEXT: _peek_line(); if (defined $current_item || defined $current_item_start) { # we can have an item line, a new item start, or a separator $line =~ /^\s+\*/ and goto ITEM_START; $line =~ /^\s+\S+/ and goto ITEM; $line =~ /^\s*$/ and goto SEPARATOR; _fail_bail_out("next line doesn't look like an item line, a new item start, or a separator"); } if (defined $current_section) { # we can have an item line, a new item start $line =~ /^\s+\*/ and goto ITEM_START; $line =~ /^\s+\S+/ and goto ITEM; _fail_bail_out("next line doesn't look like an item line, a new item start"); } if (defined $current_version) { # we can have a new section or a new version $line =~ /^\s/ and goto SECTION; $line =~ /^\S/ and goto VERSION; _fail_bail_out("next line doesn't look like a new section or new version"); } goto VERSION; SEPARATOR: # separator _consume_line(); $line eq '' ? _pass() : _fail_bail_out("should be a separator (empty line)"); $current_section = undef; $current_item_start = undef; $current_item = undef; goto WHERE_NEXT; VERSION: # version number _consume_line(); if ( (my ($pre, $version, $post)) = ($line =~ /^(\s*)(\S.*\S)(\s*)$/)) { defined $pre or $pre = ''; defined $post or $post = ''; my $lpre = length $pre; my $lpost = length $post; $lpre and _fail("line starts with $lpre blank caracters, but it should not"); $lpost and _fail("line ends with $lpre blank caracters, but it should not"); like($version, qr/^\{\{\$NEXT\}\}$|^\d\.\d{4}(_\d{2} | )\d{2}.\d{2}.\d{4}$/, "changelog line $line_nb: check version failed"); $version =~ qr/^(\{\{\$NEXT\}\})$|^\d\.\d{4}(_\d{2} | )\d{2}.\d{2}.\d{4}$/; # print STDERR " -------> [$1] [$2]\n"; $current_version_is_dev = defined $1 || $2 =~ /^_\d{2}/; $current_version = []; $current_section = undef; $current_item_start = undef; $current_item = undef; push @struct, { $version => $current_version }; } else { _fail("line should contain a version number, but it contains '$line'."); } $current_version_is_dev and goto SEPARATOR; goto CODENAME; CODENAME: # the codename is not mandatory, but strongly encouraged. So warn if it's not # there, but don't die _peek_line(); if ($line =~ /^\s*$/) { warn "It's recommended to add a CodeName to stable releases (non-dev versions).\n" . "There is no CodeName at line $line_nb. Codename format is : " . " ** Codename: // ** \n" . "The // ... part is optional."; goto SEPARATOR; } _consume_line(); like($line, qr|^ \*\* Codename: [^/]+( // [^/]+)? \*\*$|); goto SEPARATOR; SECTION: _consume_line(); if ( (my ($pre, $section, $post)) = ($line =~ /^(\s*)(\S.*\S)(\s*)$/) ) { defined $pre or $pre = ''; defined $post or $post = ''; my $lpre = length $pre; my $lpost = length $post; $pre ne ' ' and _fail("line starts with $lpre blank caracters, but it should start with exactly 4 spaces"); $lpost and _fail("line ends with $lpre blank caracters, but it should not"); like($section, qr/^\[ ($possible_sections) \]$/, "line $line_nb: check section"); $current_section = []; $current_item_start = undef; $current_item = undef; push @$current_version, { $section => $current_section }; } else { _fail_bail_out("line should contain a section string, but it contains '$line'."); } goto WHERE_NEXT; ITEM_START: _consume_line(); if ( (my ($pre, $item_start)) = ($line =~ /^(\s*)(.+)$/) ) { defined $pre or $pre = ''; my $lpre = length $pre; $pre ne ' ' and _fail("line starts with $lpre blank caracters, but it should start with exactly 4 spaces"); like($item_start, qr/^\* /, "line $line_nb: item line starts with *"); $current_item_start = [ $item_start ]; $current_item = undef; push @$current_section, $current_item_start; } else { _fail_bail_out("line should contain an item start, but it contains '$line'."); } goto WHERE_NEXT; ITEM: _consume_line(); if ( (my ($pre, $item)) = ($line =~ /^(\s*)(.+)$/) ) { defined $pre or $pre = ''; my $lpre = length $pre; $pre ne ' ' and _fail("line starts with $lpre blank caracters, but it should start with exactly 6 spaces"); _pass(); $current_item = $item; push @$current_item_start, $item; } else { _fail_bail_out("line should contain an item, but it contains '$line'."); } goto WHERE_NEXT; END_CHANGES: } # end scoping # we are doing advanced testing in a subtest because we couldn't compute the # number of test upfront. But now we can subtest 'Advanced testing of changelog' => sub { my $sections_count = 0; my $versions_next_count = 0; my $versions_count = scalar(@struct); foreach my $version_struct (@struct) { my $version_number = (keys(%$version_struct))[0]; $version_number eq '{{$NEXT}}' and $versions_next_count++; $sections_count += scalar(@{$version_struct->{$version_number}}); } my $section_comparison_count = ( ($versions_count-1) + ( ($versions_count-1) - $versions_next_count ) * 2); $section_comparison_count >= 0 or $section_comparison_count = 0; plan tests => $section_comparison_count + $sections_count; my $previous_version_struct; foreach my $version_struct (reverse @struct) { my $version_number = (keys(%$version_struct))[0]; my $previous_version_number = (keys(%$previous_version_struct))[0]; if (defined $previous_version_number) { isnt ($previous_version_number, '{{$NEXT}}', "version $version_number has {{\$NEXT}} as previous version, that's wrong"); if ($version_number ne '{{$NEXT}}') { my ($v1, $v2, $v3, $d1, $d2, $d3) = ( $version_number =~ /^(\d)\.(\d{4})(?:_(\d{2}))?\s+(\d{2})\.(\d{2})\.(\d{4})$/ ); my ($pv1, $pv2, $pv3, $pd1, $pd2, $pd3) = ( $previous_version_number =~ /^(\d)\.(\d{4})(?:_(\d{2}))?\s+(\d{2})\.(\d{2})\.(\d{4})$/ ); ok($v1 >= $pv1 || $v2 >= $pv2 || ($v3||0) >= ($pv3||0), "version '$version_number' is not greater than '$previous_version_number', that's wrong"); ok($d3 >= $pd3 || $d2 >= $pd2 || $d1 >= $pd1, "version '$version_number' is not newer (date) than '$previous_version_number', that's wrong"); } } my $previous_section_name; foreach my $section_struct (@{$version_struct->{$version_number}}) { my $section_name = (keys(%$section_struct))[0]; if (defined $previous_section_name) { my @temp = @possible_sections; while (1) { my $s = shift @temp; $previous_section_name eq "[ $s ]" and last; } my $allowed_section_names = join('|', @temp); like($section_name, qr/^\[ ($allowed_section_names) \]$/, "failure : section '$section_name' cannot come after '$previous_section_name'."); } else { Test::More::pass('first section ok'); } $previous_section_name = $section_name; } $previous_version_struct = $version_struct; } }; libdancer-perl-1.3120+dfsg.orig/t/00_base/11_file_utils.t0000644000175000017500000000135212233013707022133 0ustar gregoagregoause Test::More import => ['!pass']; use File::Spec; use Dancer ':syntax'; use Dancer::FileUtils qw/read_file_content path_or_empty/; use lib File::Spec->catdir( 't', 'lib' ); use TestUtils; use strict; use warnings; plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); plan tests => 3; my $tmp = File::Temp->new(); write_file($tmp, "one$/two"); my $content = read_file_content($tmp); ok $content = "one$/two"; my @content = read_file_content($tmp); ok $content[0] eq "one$/" && $content[1] eq 'two'; # returns UNDEF on non-existant path my $path = 'bla/blah'; if (! -e $path) { is( path_or_empty($path), '', 'path_or_empty on non-existent path', ); } libdancer-perl-1.3120+dfsg.orig/t/00_base/002_strict_and_warnings.t0000644000175000017500000000306212233013707024116 0ustar gregoagregoause Test::More tests => 10, import => ['!pass']; { package Webapp; use Dancer ':syntax'; # strict eval '$foo = 5;'; ::ok($@, 'got an error because strict is on'); ::like($@, qr/Global symbol \"\$foo\" requires explicit package name at/, 'got the right error'); # checking warnings are on by default { my $warn; local $SIG{__WARN__} = sub { $warn = $_[0] }; ::ok(!$warn, 'no warning yet'); eval 'my $bar = 1 + "hello"'; ::ok($warn, 'got a warning - default'); ::like($warn, qr/Argument \"hello\" isn\'t numeric in addition \(\+\)/, 'got the right warning'); } # check that we can disable it { # setting import_warnings => 0; # # Since we're importing warnings in Dancer.pm as documented, # no warnings; should be used instead of import_warnings; no warnings; my $warn; local $SIG{__WARN__} = sub { $warn = $_[0] }; ::ok( !$warn, 'no warnings yet' ); eval 'my $bar = 1 + "hello"'; ::ok( !$warn, 'no warnings now either' ); } # check that we can enable it { setting import_warnings => 1; my $warn; local $SIG{__WARN__} = sub { $warn = $_[0] }; ::ok(!$warn, 'no warning yet'); eval 'my $bar = 1 + "hello"'; ::ok($warn, 'got a warning - after enabling import'); ::like($warn, qr/Argument \"hello\" isn\'t numeric in addition \(\+\)/, 'got the right warning'); } } libdancer-perl-1.3120+dfsg.orig/t/00_base/09_load_app.t0000644000175000017500000000117312233013020021547 0ustar gregoagregoause Test::More tests => 5, import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; # XXX appdir is set to the path of the current test use Dancer::Test appdir => path($0); eval { load_app 'UnexistentApp' }; like $@, qr/unable to load application UnexistentApp : Can't locate/, 'load_app fails if the app is not found'; eval { load_app 'AppWithError' }; like $@, qr/unable to load application AppWithError : Bareword/, 'load_app fails if the app has syntax errors'; eval { load_app 'WorkingApp' }; is $@, '', "WorkingApp loaded"; route_exists [ GET => '/app']; response_content_is [ GET => '/app'], "app"; libdancer-perl-1.3120+dfsg.orig/t/00_base/000_create_fake_env.t0000644000175000017500000000057212233013020023142 0ustar gregoagregoause strict; use warnings; use File::Spec; use File::Path; use File::Basename; use Test::More tests => 4 * 3, import => ['!pass']; my @dirs = map { $_, File::Spec->catdir( dirname($0), $_ ), File::Spec->catdir( 't', 'lib', $_ ), } qw/ public logs views lib /; foreach my $dir (@dirs) { ok( ( -d $dir or mkpath($dir) ), "Created $dir", ); } libdancer-perl-1.3120+dfsg.orig/t/00_base/optional-module-versions.t0000644000175000017500000000176612233013707024462 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; plan tests => 1; # This isn't really a test, but simply to produce some diagnosis output showing # the versions of various modules in one place. Some modules, e.g. Test::TCP, # aren't a dependency, we simply skip tests if it's not available, so if it is # available, we don't get told the version in the test report. my @modules = qw( Test::TCP Test::More JSON YAML Clone Plack XML::Simple HTTP::Parser::XS ); for my $module (@modules) { # Just in case this fails for any modules for any reason, catch errors: eval { if (Dancer::ModuleLoader->load($module)) { my $version = $module->VERSION; diag("$module $version loaded successfully"); } else { diag("$module is not available"); } }; if ($@) { diag("Error while checking $module version - $@"); } } ok(1, "Done checking versions of optional modules"); libdancer-perl-1.3120+dfsg.orig/t/00_base/utf8.tt0000644000175000017500000000003412233013020020525 0ustar gregoagregoautf8: ’♣ ♤ ♥ ♦’ libdancer-perl-1.3120+dfsg.orig/t/00_base/lib/0000755000175000017500000000000012256332256020063 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/00_base/lib/AppWithError.pm0000644000175000017500000000016212233013020022762 0ustar gregoagregoapackage AppWithError; use Dancer ':syntax'; bogus_call_to_unkown_symbol; get '/webapp' => sub { 'webapp' }; 1; libdancer-perl-1.3120+dfsg.orig/t/00_base/lib/WorkingApp.pm0000644000175000017500000000011412233013020022452 0ustar gregoagregoapackage WorkingApp; use Dancer ':syntax'; get '/app' => sub { "app" }; 1; libdancer-perl-1.3120+dfsg.orig/t/00_base/06_dancer_object.t0000644000175000017500000000315612233013020022552 0ustar gregoagregoause Test::More; use strict; use warnings; use Dancer::ModuleLoader; plan skip_all => "the Clone module is needed for this test" unless Dancer::ModuleLoader->load('Clone'); plan tests => 19; use Dancer::Object; { package Person; use base 'Dancer::Object'; __PACKAGE__->attributes('name', 'age', 'sex'); } my $p = Person->new; ok $p->init, 'init works'; isa_ok $p, 'Person'; can_ok $p, qw(new init name age sex); ok $p->name('john'), 'setting name'; ok $p->age(10), 'setting age'; ok $p->sex('male'), 'setting sex'; is $p->name, 'john', 'getting name'; is $p->age, 10, 'getting age'; is $p->sex, 'male', 'getting sex'; my $p2 = $p->clone; isnt $p, $p2, "clone is not the same object"; is $p->age, $p2->age, "clone values are OK"; my $attrs = Person->get_attributes(); is_deeply $attrs, ['name', 'age', 'sex'], "attributes are ok"; { package Person::Child; use base 'Person'; __PACKAGE__->attributes('parent'); } my $child = Person::Child->new(); ok $child->parent($p), 'setting parent'; ok $child->name('bob'), 'setting child name'; ok $child->age(5), 'setting child age'; is $child->age, 5, 'age is ok'; is $child->parent->sex, 'male', 'age is ok'; my $child_attrs = Person::Child->get_attributes(); is_deeply $child_attrs, ['parent', 'name', 'age', 'sex'], "attributes are ok"; { package Person::Child::Blond; use base 'Person::Child'; __PACKAGE__->attributes('hair_length'); } my $blond_child = Person::Child::Blond->new(); my $blond_child_attrs = Person::Child::Blond->get_attributes(); is_deeply $blond_child_attrs, ['hair_length', 'parent', 'name', 'age', 'sex'], "attributes are ok"; libdancer-perl-1.3120+dfsg.orig/t/00_base/17_globalwarnings_config_on.t0000644000175000017500000000113212233013707025030 0ustar gregoagregoa#!/usr/bin/perl use warnings; use strict; use Test::More import => ['!pass']; use Dancer; set global_warnings => 1; is $^W, 1, "Global warnings turned on through global_warnings"; set global_warnings => 0; is $^W, 0, "Global warnings turned off through global_warnings"; # SKIP: { skip 'config setting \'import_warnings\' has been deprecated', 2 unless ($ENV{RELEASE_TESTING}); set import_warnings => 1; is $^W, 1, "Global warnings turned on through import_warnings"; set import_warnings => 0; is $^W, 0, "Global warnings turned off through import_warnings"; } done_testing(); libdancer-perl-1.3120+dfsg.orig/t/00_base/08_pod_coverage_dancer.t0000644000175000017500000000114212233013020023734 0ustar gregoagregoause strict; use warnings; use Test::More; # Ensure a recent version of Test::Pod::Coverage my $min_tpc = 1.08; eval "use Test::Pod::Coverage $min_tpc"; plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" if $@; # Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, # but older versions don't recognize some common documentation styles my $min_pc = 0.18; eval "use Pod::Coverage $min_pc"; plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" if $@; plan tests => 2; pod_coverage_ok('Dancer'); pod_coverage_ok('Dancer::Request'); libdancer-perl-1.3120+dfsg.orig/t/00_base/009_syntax_export.t0000644000175000017500000000061112233013020022773 0ustar gregoagregoause Test::More import => ["!pass"]; use Dancer ':moose', ':tests', ":syntax"; my @keywords = (qw/before after pass/); plan tests => scalar(@keywords) + 2; foreach my $symbol (@keywords) { ok( !exists( $::{$symbol} ), "symbol `$symbol' is not exported" ); } ok(exists($::{'get'}), "symbol `get' is exported"); use Cwd; ok !setting("appdir"), ":syntax with exports prevents app setup"; libdancer-perl-1.3120+dfsg.orig/t/00_base/normalize_path.t0000644000175000017500000000124612233013707022511 0ustar gregoagregoause strict; use warnings; use Test::More tests => 10; use Dancer::FileUtils 'normalize_path'; my %paths = ( 'one/../two' => 'two', '/one/../two' => '/two', '//one/../two' => '//two', '/one/../two/../three' => '/three', 'one/two/three/../' => 'one/two/', '/one/two/three/../' => '/one/two/', 'one/./two/./three/' => 'one/two/three/', 'a/../b' => 'b', 'a/b/../../c' => 'c', 'a/b/c/../../../d' => 'd', ); foreach my $path ( keys %paths ) { my $result = $paths{$path}; is( normalize_path($path), $result, "Normalized $path => $result", ); } libdancer-perl-1.3120+dfsg.orig/t/00_base/001_load.t0000644000175000017500000000027512233013020020761 0ustar gregoagregoause strict; use warnings; use Test::More tests => 1, import => ['!pass']; use Dancer; ok( setting('appdir'), 'Complete import' ); diag( "Testing Dancer $Dancer::VERSION, Perl $], $^X" ); libdancer-perl-1.3120+dfsg.orig/t/00_base/uri_for.t0000644000175000017500000000041112233013020021117 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; plan tests => 1; use Dancer; use Dancer::Test; get '/foo' => sub { return uri_for('/foo'); }; response_content_is [GET => '/foo'], 'http://localhost/foo', "uri_for works as expected"; libdancer-perl-1.3120+dfsg.orig/t/00_base/config.t0000644000175000017500000000052612233013020020726 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 3; use Dancer; use Dancer::Test; set foo => 42; get '/' => sub { config }; my $res = dancer_response(GET => '/'); is $res->{content}{foo}, 42, "setting is accessible via config"; is config->{'foo'}, 42, "config works"; is setting('foo'), 42, "setting works"; libdancer-perl-1.3120+dfsg.orig/t/00_base/003_syntax.t0000644000175000017500000000161512233013020021371 0ustar gregoagregoause Test::More import => ['!pass']; my @keywords = qw( after any before before_template cookie cookies config content_type dance debug del dirname error false forward from_dumper from_json from_yaml from_xml get halt header headers hook layout load load_app logger mime options param params pass path post prefix push_header put redirect request send_file send_error set setting set_cookie session splat status start template to_dumper to_json to_yaml to_xml true upload captures uri_for var vars warning ); plan tests => scalar(@keywords); use Dancer ':syntax'; foreach my $symbol (@keywords) { ok(exists($::{$symbol}), "symbol `$symbol' is exported"); } libdancer-perl-1.3120+dfsg.orig/t/00_base/008_export.t0000644000175000017500000000061712233013020021372 0ustar gregoagregoause Test::More import => ['!pass']; my @keywords = (qw/before after pass/); use Dancer ':moose', ':tests'; plan tests => scalar(@keywords) + 2; foreach my $symbol (@keywords) { ok( !exists( $::{$symbol} ), "symbol `$symbol' is not exported" ); } ok(exists($::{'get'}), "symbol `get' is exported"); use Cwd; is setting("appdir"), path( getcwd, dirname(__FILE__) ), "app was still set up"; libdancer-perl-1.3120+dfsg.orig/t/00_base/16_version.t0000644000175000017500000000023512233013707021465 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer qw(:syntax); is (int(dancer_version), 1, "dancer major version"); done_testing; libdancer-perl-1.3120+dfsg.orig/t/04_static_file/0000755000175000017500000000000012256332256020675 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/04_static_file/secretfile0000644000175000017500000000017412233013707022737 0ustar gregoagregoaThis file is used by 02_dir_traversal.t to ensure that static file requests cannot traverse upwards out of the public/ dir. libdancer-perl-1.3120+dfsg.orig/t/04_static_file/02_dir_traversal.t0000644000175000017500000000117212233013707024215 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Test; # All these paths should return 404; if we get a file served, we have a # directory traversal vulnerability! my @try_paths = qw( /css/../../secretfile ../secretfile /etc/passwd ../../../../../../../../../../../../etc/passwd ); plan tests => scalar @try_paths; use Dancer ':syntax'; set public => path( dirname(__FILE__), 'static' ); my $public = setting('public'); for my $path (@try_paths) { my $resp = Dancer::Test::_get_file_response( [ GET => $path ] ); ok !$resp, "Request to $path did not return a file response"; } libdancer-perl-1.3120+dfsg.orig/t/04_static_file/01_mime_types.t0000644000175000017500000000427312233013707023533 0ustar gregoagregoause strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; use Dancer::Test; use Test::More import => ['!pass']; use HTTP::Date qw( time2str ); plan tests => 10; # 1. test mime directly { is(mime->for_file('foo.zip'), 'application/zip', "a mime_type is found with MIME::Types"); is(mime->for_file('foo.nonexistent'), mime->default, 'mime_type defaults to the default defined mime_type' ); } # 2. test mimes of public files { # set environment... set public => path(dirname(__FILE__), 'static'); my $public = setting('public'); # test we do not have any mime_type alias defined. is_deeply(mime->custom_types, {}, "No aliases present."); my $path = '/hello.foo'; my $date = time2str( (stat "$public/$path")[9] ); # check if fake request is working response_status_is [GET => $path] => 200, "static file is found for $path"; # check that for unknown file types, the default value is set response_headers_are_deeply [GET => $path] => ['Content-Type' => mime->default, 'Last-Modified' => $date ], "$path is sent with default mime_type"; # we can change the default mime type set default_mime_type => 'text/plain'; # check that for unknown file types, the new default value is set response_headers_are_deeply [GET => $path] => ['Content-Type' => 'text/plain', 'Last-Modified' => $date], "$path is sent with new default mime_type"; # check we can add a mime type mime->add_type(foo => 'text/foo'); is mime->for_name("foo"), "text/foo", "can add an alias"; # check that mime type is returned in the aliases method is_deeply(mime->custom_types, {foo => 'text/foo'}, "just the 'foo' alias."); # and that is now is returned being our new mime_type response_headers_are_deeply [GET => $path] => ['Content-Type' => 'text/foo', 'Last-Modified' => $date], "$path is sent as text/foo"; # other test for standard extension $path = '/hello.txt'; $date = time2str( (stat "$public/$path")[9] ); # and the response is text/plain response_headers_are_deeply [GET => $path] => ['Content-Type' => 'text/plain', 'Last-Modified' => $date], "$path is sent as text/plain"; } libdancer-perl-1.3120+dfsg.orig/t/04_static_file/003_mime_types_reinit.t0000644000175000017500000000170312233013020025146 0ustar gregoagregoause strict; use warnings; use IO::Handle; use Dancer::MIME; use Dancer ':syntax'; use Dancer::ModuleLoader; use Test::More import => ['!pass']; plan tests => 3; # Test that MIME::Types gets initialised before the fork, as it'll # fail to read from DATA in all bar one child process in a # mod_perl-type preforking situation. # # See the comment near the top of Dancer/MIME.pm, and GH#136. my @cts; for (my $i = 0; $i < 3; $i++) { my ($p, $c) = (IO::Handle->new, IO::Handle->new); pipe($p, $c); if (my $pid = fork()) { # parent $c->close; my $ct = $p->getline; $p->close(); waitpid($pid, 0); push @cts, $ct; } else { # child $p->close; my $mime = Dancer::MIME->instance(); my $type = $mime->for_name('css'); $c->print($type); $c->close; exit 0; } } is $cts[0] => 'text/css'; is $cts[1] => 'text/css'; is $cts[2] => 'text/css'; libdancer-perl-1.3120+dfsg.orig/t/04_static_file/static/0000755000175000017500000000000012256332256022164 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/t/04_static_file/static/hello.foo0000644000175000017500000000001211506417160023760 0ustar gregoagregoaHello Foo libdancer-perl-1.3120+dfsg.orig/t/04_static_file/static/hello.txt0000644000175000017500000000001411506417160024016 0ustar gregoagregoahello there libdancer-perl-1.3120+dfsg.orig/t/04_static_file/001_base.t0000644000175000017500000000461212233013707022347 0ustar gregoagregoause strict; use warnings; # There is an issue with HTTP::Parser::XS while parsing an URI with \0 # Using the pure perl via PERL_ONLY works BEGIN { $ENV{PERL_ONLY} = 1; } use Test::More import => ['!pass']; use Dancer::Test; use HTTP::Date qw( time2str ); plan skip_all => "Skip test with Test::TCP in win32" if $^O eq 'MSWin32'; plan skip_all => "Test::TCP is required" unless Dancer::ModuleLoader->load('Test::TCP' => "1.30"); plan skip_all => "Plack is required" unless Dancer::ModuleLoader->load('Plack::Loader'); plan tests => 10; use Dancer ':syntax'; set public => path( dirname(__FILE__), 'static' ); my $public = setting('public'); my $date = time2str( (stat "$public/hello.txt")[9] ); my $req = [ GET => '/hello.txt' ]; response_is_file $req; my $resp = Dancer::Test::_get_file_response($req); is_deeply( $resp->headers_to_array, [ 'Content-Type' => 'text/plain', 'Last-Modified' => $date ], "response header looks good for @$req" ); is( ref( $resp->{content} ), 'GLOB', "response content looks good for @$req" ); ok $resp = Dancer::Test::_get_file_response( [ GET => "/hello\0.txt" ] ); my $r = Dancer::SharedData->response(); is $r->status, 400; is $r->content, 'Bad Request'; require HTTP::Request; require LWP::UserAgent; Test::TCP::test_tcp( client => sub { my $port = shift; my $req = HTTP::Request->new( GET => "http://127.0.0.1:$port/hello%00.txt" ); my $ua = LWP::UserAgent->new(); my $res = $ua->request($req); ok !$res->is_success; is $res->code, 400; }, server => sub { my $port = shift; setting apphandler => 'PSGI'; Dancer::Config->load; my $app = Dancer::Handler->psgi_app; Plack::Loader->auto( port => $port )->run($app); Dancer->dance(); } ); Test::TCP::test_tcp( client => sub { my $port = shift; my $req = HTTP::Request->new( GET => "http://127.0.0.1:$port/hello.txt", [ 'If-Modified-Since' => $date ] ); my $ua = LWP::UserAgent->new(); my $res = $ua->request($req); ok !$res->is_success; is $res->code, 304; }, server => sub { my $port = shift; setting apphandler => 'PSGI'; Dancer::Config->load; my $app = Dancer::Handler->psgi_app; Plack::Loader->auto( port => $port )->run($app); Dancer->dance(); } ); libdancer-perl-1.3120+dfsg.orig/t/TestPlugin.pm0000644000175000017500000000023512233013020020514 0ustar gregoagregoapackage TestPlugin; use strict; use warnings; use Dancer::Plugin; register 'test_plugin_symbol' => sub { "test_plugin_symbol"; }; register_plugin; 1; libdancer-perl-1.3120+dfsg.orig/lib/0000755000175000017500000000000012256332256016407 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/lib/Dancer/0000755000175000017500000000000012256332256017603 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/lib/Dancer/Request.pm0000644000175000017500000006440112251741334021572 0ustar gregoagregoapackage Dancer::Request; use strict; use warnings; use Carp; use base 'Dancer::Object'; use Dancer::Config 'setting'; use Dancer::Request::Upload; use Dancer::SharedData; use Dancer::Session; use Dancer::Exception qw(:all); use Encode; use HTTP::Body; use URI; use URI::Escape; my @http_env_keys = ( 'user_agent', 'accept_language', 'accept_charset', 'accept_encoding', 'keep_alive', 'connection', 'accept', 'accept_type', 'referer', #'host', managed manually ); my $count = 0; __PACKAGE__->attributes( # query 'env', 'path', 'method', 'content_type', 'content_length', 'body', 'id', 'uploads', 'headers', 'path_info', 'ajax', 'is_forward', @http_env_keys, ); sub new { my ($self, @args) = @_; if (@args == 1) { @args = ('env' => $args[0]); Dancer::Deprecation->deprecated( fatal => 1, feature => 'Calling Dancer::Request->new($env)', version => 1.3059, reason => 'Please use Dancer::Request->new( env => $env ) instead', ); } $self->SUPER::new(@args); } # aliases sub agent { $_[0]->user_agent } sub remote_address { $_[0]->address } sub forwarded_for_address { $_[0]->env->{'X_FORWARDED_FOR'} || $_[0]->env->{'HTTP_X_FORWARDED_FOR'} } sub address { $_[0]->env->{REMOTE_ADDR} } sub host { if (@_==2) { $_[0]->{host} = $_[1]; } else { my $host; $host = ($_[0]->env->{X_FORWARDED_HOST} || $_[0]->env->{HTTP_X_FORWARDED_HOST}) if setting('behind_proxy'); $host || $_[0]->{host} || $_[0]->env->{HTTP_HOST}; } } sub remote_host { $_[0]->env->{REMOTE_HOST} } sub protocol { $_[0]->env->{SERVER_PROTOCOL} } sub port { $_[0]->env->{SERVER_PORT} } sub request_uri { $_[0]->env->{REQUEST_URI} } sub user { $_[0]->env->{REMOTE_USER} } sub script_name { $_[0]->env->{SCRIPT_NAME} } sub request_base { $_[0]->env->{REQUEST_BASE} || $_[0]->env->{HTTP_REQUEST_BASE} } sub scheme { my $scheme; if (setting('behind_proxy')) { $scheme = $_[0]->env->{'X_FORWARDED_PROTOCOL'} || $_[0]->env->{'HTTP_X_FORWARDED_PROTOCOL'} || $_[0]->env->{'HTTP_X_FORWARDED_PROTO'} || $_[0]->env->{'HTTP_FORWARDED_PROTO'} || "" } return $scheme || $_[0]->env->{'psgi.url_scheme'} || $_[0]->env->{'PSGI.URL_SCHEME'} || ""; } sub secure { $_[0]->scheme eq 'https' } sub uri { $_[0]->request_uri } sub is_head { $_[0]->{method} eq 'HEAD' } sub is_post { $_[0]->{method} eq 'POST' } sub is_get { $_[0]->{method} eq 'GET' } sub is_put { $_[0]->{method} eq 'PUT' } sub is_delete { $_[0]->{method} eq 'DELETE' } sub is_patch { $_[0]->{method} eq 'PATCH' } sub header { $_[0]->{headers}->header($_[1]) } # public interface compat with CGI.pm objects sub request_method { method(@_) } sub Vars { params(@_) } sub input_handle { $_[0]->env->{'psgi.input'} || $_[0]->env->{'PSGI.INPUT'} } sub init { my ($self) = @_; $self->{env} ||= {}; $self->{path} = undef; $self->{method} = undef; $self->{params} = {}; $self->{body} = ''; $self->{is_forward} ||= 0; $self->{content_length} = $self->env->{CONTENT_LENGTH} || 0; $self->{content_type} = $self->env->{CONTENT_TYPE} || ''; $self->{id} = ++$count; $self->{_chunk_size} = 4096; $self->{_read_position} = 0; $self->{_body_params} = undef; $self->{_query_params} = undef; $self->{_route_params} = {}; $self->_build_headers(); $self->_build_request_env(); $self->_build_path() unless $self->path; $self->_build_path_info() unless $self->path_info; $self->_build_method() unless $self->method; $self->{_http_body} = HTTP::Body->new($self->content_type, $self->content_length); $self->{_http_body}->cleanup(1); $self->_build_params(); $self->_build_uploads unless $self->uploads; $self->{ajax} = $self->is_ajax; return $self; } sub to_string { my ($self) = @_; return "[#" . $self->id . "] " . $self->method . " " . $self->path; } # helper for building a request object by hand # with the given method, path, params, body and headers. sub new_for_request { my ($class, $method, $uri, $params, $body, $headers, $extra_env) = @_; $params ||= {}; $extra_env ||= {}; $method = uc($method); my ( $path, $query_string ) = ( $uri =~ /([^?]*)(?:\?(.*))?/s ); #from HTTP::Server::Simple my $env = { %ENV, %{$extra_env}, PATH_INFO => $path, QUERY_STRING => $query_string || $ENV{QUERY_STRING} || '', REQUEST_METHOD => $method }; my $req = $class->new(env => $env); $req->{params} = {%{$req->{params}}, %{$params}}; $req->_build_params(); $req->{_query_params} = $req->{params}; $req->{body} = $body if defined $body; $req->{headers} = $headers || HTTP::Headers->new; return $req; } #Create a new request which is a clone of the current one, apart #from the path location, which points instead to the new location sub forward { my ($class, $request, $to_data) = @_; my $env = $request->env; $env->{PATH_INFO} = $to_data->{to_url}; my $new_request = $class->new(env => $env, is_forward => 1); my $new_params = _merge_params(scalar($request->params), $to_data->{params} || {}); if (exists($to_data->{options}{method})) { die unless _valid_method($to_data->{options}{method}); $new_request->{method} = uc $to_data->{options}{method}; } $new_request->{params} = $new_params; $new_request->{_body_params} = $request->{_body_params}; $new_request->{_query_params} = $request->{_query_params}; $new_request->{_route_params} = $request->{_route_params}; $new_request->{_params_are_decoded} = 1; $new_request->{body} = $request->body; $new_request->{headers} = $request->headers; if( my $session = Dancer::Session->engine && Dancer::Session->get_current_session ) { my $name = $session->session_name; # make sure that COOKIE is populated $new_request->{env}{COOKIE} ||= $new_request->{env}{HTTP_COOKIE}; no warnings; # COOKIE can be undef unless ( $new_request->{env}{COOKIE} =~ /$name\s*=/ ) { $new_request->{env}{COOKIE} = join ';', grep { $_ } $new_request->{env}{COOKIE}, join '=', $name, Dancer::Session->get_current_session->id; } } $new_request->{uploads} = $request->uploads; return $new_request; } sub _valid_method { my $method = shift; return $method =~ /^(?:head|post|get|put|delete)$/i; } sub _merge_params { my ($params, $to_add) = @_; die unless ref $to_add eq "HASH"; for my $key (keys %$to_add) { $params->{$key} = $to_add->{$key}; } return $params; } sub base { my $self = shift; my $uri = $self->_common_uri; return $uri->canonical; } sub _common_uri { my $self = shift; my $path = $self->env->{SCRIPT_NAME} || ''; my $port = $self->env->{SERVER_PORT}; my $server = $self->env->{SERVER_NAME}; my $host = $self->host; my $scheme = $self->scheme; my $uri = URI->new; $uri->scheme($scheme); $uri->authority($host || "$server:$port"); if (setting('behind_proxy')) { my $request_base = $self->env->{REQUEST_BASE} || $self->env->{HTTP_REQUEST_BASE} || ''; $uri->path($request_base . $path || '/'); } else { $uri->path($path || '/'); } return $uri; } sub uri_base { my $self = shift; my $uri = $self->_common_uri; my $canon = $uri->canonical; if ( $uri->path eq '/' ) { $canon =~ s{/$}{}; } return $canon; } sub uri_for { my ($self, $part, $params, $dont_escape) = @_; my $uri = $self->base; # Make sure there's exactly one slash between the base and the new part my $base = $uri->path; $base =~ s|/$||; $part =~ s|^/||; $uri->path("$base/$part"); $uri->query_form($params) if $params; return $dont_escape ? uri_unescape($uri->canonical) : $uri->canonical; } sub params { my ($self, $source) = @_; my @caller = caller; if (not $self->{_params_are_decoded}) { $self->{params} = _decode($self->{params}); $self->{_body_params} = _decode($self->{_body_params}); $self->{_query_params} = _decode($self->{_query_params}); $self->{_route_params} = _decode($self->{_route_params}); $self->{_params_are_decoded} = 1; } return %{$self->{params}} if wantarray && @_ == 1; return $self->{params} if @_ == 1; if ($source eq 'query') { return %{$self->{_query_params}} if wantarray; return $self->{_query_params}; } elsif ($source eq 'body') { return %{$self->{_body_params}} if wantarray; return $self->{_body_params}; } if ($source eq 'route') { return %{$self->{_route_params}} if wantarray; return $self->{_route_params}; } else { raise core_request => "Unknown source params \"$source\"."; } } sub _decode { my ($h) = @_; return if not defined $h; if (!ref($h) && !utf8::is_utf8($h)) { return decode('UTF-8', $h); } if (ref($h) eq 'HASH') { while (my ($k, $v) = each(%$h)) { $h->{$k} = _decode($v); } return $h; } if (ref($h) eq 'ARRAY') { return [ map { _decode($_) } @$h ]; } return $h; } sub is_ajax { my $self = shift; # when using Plack::Builder headers are not set # so we're checking if it's actually there with PSGI plain headers if ( defined $self->{x_requested_with} ) { if ( $self->{x_requested_with} eq "XMLHttpRequest" ) { return 1; } } return 0 unless defined $self->headers; return 0 unless defined $self->header('X-Requested-With'); return 0 if $self->header('X-Requested-With') ne 'XMLHttpRequest'; return 1; } # context-aware accessor for uploads sub upload { my ($self, $name) = @_; my $res = $self->{uploads}{$name}; return $res unless wantarray; return () unless defined $res; return (ref($res) eq 'ARRAY') ? @$res : $res; } # Some Dancer's core components sometimes need to alter # the parsed request params, these protected accessors are provided # for this purpose sub _set_route_params { my ($self, $params) = @_; $self->{_route_params} = $params; $self->_build_params(); } sub _set_body_params { my ($self, $params) = @_; $self->{_body_params} = $params; $self->_build_params(); } sub _set_query_params { my ($self, $params) = @_; $self->{_query_params} = $params; $self->_build_params(); } sub _build_request_env { my ($self) = @_; # Don't refactor that, it's called whenever a request object is needed, that # means at least once per request. If refactored in a loop, this will cost 4 # times more than the following static map. my $env = $self->env; $self->{user_agent} = $env->{HTTP_USER_AGENT}; $self->{host} = $env->{HTTP_HOST}; $self->{accept_language} = $env->{HTTP_ACCEPT_LANGUAGE}; $self->{accept_charset} = $env->{HTTP_ACCEPT_CHARSET}; $self->{accept_encoding} = $env->{HTTP_ACCEPT_ENCODING}; $self->{keep_alive} = $env->{HTTP_KEEP_ALIVE}; $self->{connection} = $env->{HTTP_CONNECTION}; $self->{accept} = $env->{HTTP_ACCEPT}; $self->{accept_type} = $env->{HTTP_ACCEPT_TYPE}; $self->{referer} = $env->{HTTP_REFERER}; $self->{x_requested_with} = $env->{HTTP_X_REQUESTED_WITH}; } sub _build_headers { my ($self) = @_; $self->{headers} = Dancer::SharedData->headers; } sub _build_params { my ($self) = @_; # params may have been populated by before filters # _before_ we get there, so we have to save it first my $previous = $self->{params}; # now parse environment params... $self->_parse_get_params(); if ($self->is_forward) { $self->{_body_params} ||= {}; } else { $self->_parse_post_params(); } # and merge everything $self->{params} = { %$previous, %{$self->{_query_params}}, %{$self->{_route_params}}, %{$self->{_body_params}}, }; } # Written from PSGI specs: # http://search.cpan.org/dist/PSGI/PSGI.pod sub _build_path { my ($self) = @_; my $path = ""; $path .= $self->script_name if defined $self->script_name; $path .= $self->env->{PATH_INFO} if defined $self->env->{PATH_INFO}; # fallback to REQUEST_URI if nothing found # we have to decode it, according to PSGI specs. if (defined $self->request_uri) { $path ||= $self->_url_decode($self->request_uri); } raise core_request => "Cannot resolve path" if not $path; $self->{path} = $path; } sub _build_path_info { my ($self) = @_; my $info = $self->env->{PATH_INFO}; if (defined $info) { # Empty path info will be interpreted as "root". $info ||= '/'; } else { $info = $self->path; } $self->{path_info} = $info; } sub _build_method { my ($self) = @_; $self->{method} = $self->env->{REQUEST_METHOD} || $self->{request}->request_method(); } sub _url_decode { my ($self, $encoded) = @_; my $clean = $encoded; $clean =~ tr/\+/ /; $clean =~ s/%([a-fA-F0-9]{2})/pack "H2", $1/eg; return $clean; } sub _parse_post_params { my ($self) = @_; return $self->{_body_params} if defined $self->{_body_params}; my $body = $self->_read_to_end(); $self->{_body_params} = $self->{_http_body}->param; } sub _parse_get_params { my ($self) = @_; return $self->{_query_params} if defined $self->{_query_params}; $self->{_query_params} = {}; my $source = $self->env->{QUERY_STRING} || ''; foreach my $token (split /[&;]/, $source) { my ($key, $val) = split(/=/, $token, 2); next unless defined $key; $val = (defined $val) ? $val : ''; $key = $self->_url_decode($key); $val = $self->_url_decode($val); # looking for multi-value params if (exists $self->{_query_params}{$key}) { my $prev_val = $self->{_query_params}{$key}; if (ref($prev_val) && ref($prev_val) eq 'ARRAY') { push @{$self->{_query_params}{$key}}, $val; } else { $self->{_query_params}{$key} = [$prev_val, $val]; } } # simple value param (first time we see it) else { $self->{_query_params}{$key} = $val; } } return $self->{_query_params}; } sub _read_to_end { my ($self) = @_; my $content_length = $self->content_length; return unless $self->_has_something_to_read(); if ($content_length > 0) { my $buffer; while (defined ($buffer = $self->_read())) { $self->{body} .= $buffer; $self->{_http_body}->add($buffer); } } return $self->{body}; } sub _has_something_to_read { my ($self) = @_; return 0 unless defined $self->input_handle; } # taken from Miyagawa's Plack::Request::BodyParser sub _read { my ($self,) = @_; my $remaining = $self->content_length - $self->{_read_position}; my $maxlength = $self->{_chunk_size}; return if ($remaining <= 0); my $readlen = ($remaining > $maxlength) ? $maxlength : $remaining; my $buffer; my $rc; $rc = $self->input_handle->read($buffer, $readlen); if (defined $rc) { $self->{_read_position} += $rc; return $buffer; } else { raise core_request => "Unknown error reading input: $!"; } } # Taken gently from Plack::Request, thanks to Plack authors. sub _build_uploads { my ($self) = @_; my $uploads = _decode($self->{_http_body}->upload); my %uploads; for my $name (keys %{$uploads}) { my $files = $uploads->{$name}; $files = ref $files eq 'ARRAY' ? $files : [$files]; my @uploads; for my $upload (@{$files}) { push( @uploads, Dancer::Request::Upload->new( headers => $upload->{headers}, tempname => $upload->{tempname}, size => $upload->{size}, filename => $upload->{filename}, ) ); } $uploads{$name} = @uploads > 1 ? \@uploads : $uploads[0]; # support access to the filename as a normal param my @filenames = map { $_->{filename} } @uploads; $self->{_body_params}{$name} = @filenames > 1 ? \@filenames : $filenames[0]; } $self->{uploads} = \%uploads; $self->_build_params(); } 1; __END__ =pod =head1 NAME Dancer::Request - interface for accessing incoming requests =head1 DESCRIPTION This class implements a common interface for accessing incoming requests in a L<< Dancer >> application. In a route handler, the current request object can be accessed by the C method, like in the following example: get '/foo' => sub { request->params; # request, params parsed as a hash ref request->body; # returns the request body, unparsed request->path; # the path requested by the client # ... }; A route handler should not read the environment by itself, but should instead use the current request object. =head1 PUBLIC INTERFACE =head2 new() The constructor of the class, used internally by Dancer's core to create request objects. It uses the environment hash table given to build the request object: Dancer::Request->new(env => \%ENV); It also accepts the C boolean flag, if the new request object is the result of a forward. =head2 init() Used internally to define some default values and parse parameters. =head2 new_for_request($method, $path, $params, $body, $headers) An alternate constructor convenient for test scripts which creates a request object with the arguments given. =head2 forward($request, $new_location) Create a new request which is a clone of the current one, apart from the path location, which points instead to the new location. This is used internally to chain requests using the forward keyword. Note that the new location should be a hash reference. Only one key is required, the C, that should point to the URL that forward will use. Optional values are the key C to a hash of parameters to be added to the current request parameters, and the key C that points to a hash of options about the redirect (for instance, C pointing to a new request method). =head2 to_string() Return a string representing the request object (eg: C<"GET /some/path">) =head2 method() Return the HTTP method used by the client to access the application. While this method returns the method string as provided by the environment, it's better to use one of the following boolean accessors if you want to inspect the requested method. =head2 address() Return the IP address of the client. =head2 remote_host() Return the remote host of the client. This only works with web servers configured to do a reverse DNS lookup on the client's IP address. =head2 protocol() Return the protocol (HTTP/1.0 or HTTP/1.1) used for the request. =head2 port() Return the port of the server. =head2 uri() An alias to request_uri() =head2 request_uri() Return the raw, undecoded request URI path. =head2 user() Return remote user if defined. =head2 script_name() Return script_name from the environment. =head2 scheme() Return the scheme of the request =head2 secure() Return true of false, indicating whether the connection is secure =head2 is_get() Return true if the method requested by the client is 'GET' =head2 is_head() Return true if the method requested by the client is 'HEAD' =head2 is_patch() Return true if the method requested by the client is 'PATCH' =head2 is_post() Return true if the method requested by the client is 'POST' =head2 is_put() Return true if the method requested by the client is 'PUT' =head2 is_delete() Return true if the method requested by the client is 'DELETE' =head2 path() Return the path requested by the client. =head2 base() Returns an absolute URI for the base of the application. Returns a L object (which stringifies to the URL, as you'd expect). =head2 uri_base() Same thing as C above, except it removes the last trailing slash in the path if it is the only path. This means that if your base is I, C will return I (notice no trailing slash). This is considered very useful when using templates to do the following thing: =head2 uri_for(path, params) Constructs a URI from the base and the passed path. If params (hashref) is supplied, these are added to the query string of the uri. If the base is C, C<< request->uri_for('/bar', { baz => 'baz' }) >> would return C. Returns a L object (which stringifies to the URL, as you'd expect). =head2 params($source) Called in scalar context, returns a hashref of params, either from the specified source (see below for more info on that) or merging all sources. So, you can use, for instance: my $foo = params->{foo} If called in list context, returns a list of key => value pairs, so you could use: my %allparams = params; If the incoming form data contains multiple values for the same key, they will be returned as an arrayref. =head3 Fetching only params from a given source If a required source isn't specified, a mixed hashref (or list of key value pairs, in list context) will be returned; this will contain params from all sources (route, query, body). In practical terms, this means that if the param C is passed both on the querystring and in a POST body, you can only access one of them. If you want to see only params from a given source, you can say so by passing the C<$source> param to C: my %querystring_params = params('query'); my %route_params = params('route'); my %post_params = params('body'); If source equals C, then only params parsed from the route pattern are returned. If source equals C, then only params parsed from the query string are returned. If source equals C, then only params sent in the request body will be returned. If another value is given for C<$source>, then an exception is triggered. =head2 Vars Alias to the C accessor, for backward-compatibility with C interface. =head2 request_method Alias to the C accessor, for backward-compatibility with C interface. =head2 input_handle Alias to the PSGI input handle (C<< env->{psgi.input}> >>) =head2 content_type() Return the content type of the request. =head2 content_length() Return the content length of the request. =head2 header($name) Return the value of the given header, if present. If the header has multiple values, returns an the list of values if called in list context, the first one in scalar. =head2 body() Return the raw body of the request, unparsed. If you need to access the body of the request, you have to use this accessor and should not try to read C by hand. C already did it for you and kept the raw body untouched in there. =head2 is_ajax() Return true if the value of the header C is XMLHttpRequest. =head2 env() Return the current environment as a hashref. Note that a request's environment is not always reflected by the global variable C<%ENV> (e.g., when running via L). In consequence, it is recommended to always rely on the values returned by C, and not to access C<%ENV> directly. =head2 uploads() Returns a reference to a hash containing uploads. Values can be either a L object, or an arrayref of L objects. You should probably use the C accessor instead of manually accessing the C hash table. =head2 upload($name) Context-aware accessor for uploads. It's a wrapper around an access to the hash table provided by C. It looks at the calling context and returns a corresponding value. If you have many file uploads under the same name, and call C in an array context, the accessor will unroll the ARRAY ref for you: my @uploads = request->upload('many_uploads'); # OK Whereas with a manual access to the hash table, you'll end up with one element in @uploads, being the ARRAY ref: my @uploads = request->uploads->{'many_uploads'}; # $uploads[0]: ARRAY(0xXXXXX) That is why this accessor should be used instead of a manual access to C. =head1 Values Given a request to http://perldancer.org:5000/request-methods?a=1 these are the values returned by the various request-> method calls: base http://perldancer.org:5000/ uri_base http://perldancer.org:5000 uri /request-methods?a=1 request_uri /request-methods?a=1 path /request-methods method GET port 5000 protocol HTTP/1.1 scheme http =head1 HTTP environment variables All HTTP environment variables that are in %ENV will be provided in the Dancer::Request object through specific accessors, here are those supported: =over 4 =item C =item C =item C =item C =item C =item C (alias for C) =item C =item C =item C =item C =item C =item C =item C =item C =item C =item C =item C =back =head1 AUTHORS This module has been written by Alexis Sukrieh and was mostly inspired by L, written by Tatsuiko Miyagawa. Tatsuiko Miyagawa also gave a hand for the PSGI interface. =head1 LICENCE This module is released under the same terms as Perl itself. =head1 SEE ALSO L =cut libdancer-perl-1.3120+dfsg.orig/lib/Dancer/Handler.pm0000644000175000017500000001344112246715364021525 0ustar gregoagregoapackage Dancer::Handler; use strict; use warnings; use Carp; use File::stat; use HTTP::Headers; use Dancer::Logger; use Dancer::GetOpt; use Dancer::SharedData; use Dancer::Renderer; use Dancer::Config 'setting'; use Dancer::ModuleLoader; use Dancer::Exception qw(:all); use Dancer::Factory::Hook; use Encode; Dancer::Factory::Hook->instance->install_hooks( qw/on_handler_exception/ ); # This is where we choose which application handler to return sub get_handler { my $handler = 'Dancer::Handler::Standalone'; # force PSGI is PLACK_ENV is set if ($ENV{'PLACK_ENV'}) { Dancer::Logger::core("PLACK_ENV is set (".$ENV{'PLACK_ENV'}.") forcing PSGI handler"); setting('apphandler' => 'PSGI'); } # if Plack is detected or set by conf, use the PSGI handler if ( defined setting('apphandler') ) { $handler = 'Dancer::Handler::' . setting('apphandler'); } # load the app handler my ($loaded, $error) = Dancer::ModuleLoader->load($handler); raise core_handler => "Unable to load app handler `$handler': $error" if $error; # OK, everything's fine, load the handler Dancer::Logger::core('loading ' . $handler . ' handler'); return $handler->new; } # handle an incoming request, process it and return a response sub handle_request { my ($self, $request) = @_; my $ip_addr = $request->remote_address || '-'; Dancer::SharedData->reset_all( reset_vars => !$request->is_forward); Dancer::Logger::core("request: " . $request->method . " " . $request->path_info . " from $ip_addr"); # save the request object Dancer::SharedData->request($request); # deserialize the request body if possible $request = Dancer::Serializer->process_request($request) if Dancer::App->current->setting('serializer'); # read cookies from client Dancer::Cookies->init; if (Dancer::Config::setting('auto_reload')) { Dancer::App->reload_apps; } render_request($request); return $self->render_response(); } sub render_request { my $request = shift; my $action; $action = try { Dancer::Renderer->render_file || Dancer::Renderer->render_action || Dancer::Renderer->render_autopage || Dancer::Renderer->render_error(404); } continuation { # workflow exception (continuation) my ($continuation) = @_; $continuation->isa('Dancer::Continuation::Halted') or $continuation->rethrow(); # special case for halted workflow continuation: still render the response Dancer::Serializer->process_response(Dancer::SharedData->response); } catch { my ($exception) = @_; Dancer::Factory::Hook->execute_hooks('on_handler_exception', $exception); Dancer::Logger::error( sprintf( 'request to %s %s crashed: %s', $request->method, $request->path_info, $exception ) ); # use stringification, to get exception message in case of a # Dancer::Exception Dancer::Error->new( code => 500, title => "Runtime Error", message => "$exception", exception => $exception, )->render(); }; return $action; } sub psgi_app { my $self = shift; sub { my $env = shift; $self->init_request_headers($env); my $request = Dancer::Request->new(env => $env); $self->handle_request($request); }; } sub init_request_headers { my ($self, $env) = @_; my $psgi_headers = HTTP::Headers->new( map { (my $field = $_) =~ s/^HTTPS?_//; ($field => $env->{$_}); } grep {/^(?:HTTP|CONTENT|COOKIE)/i} keys %$env ); Dancer::SharedData->headers($psgi_headers); } # render a PSGI-formatted response from a response built by # handle_request() sub render_response { my $self = shift; my $response = Dancer::SharedData->response(); my $content = $response->content; unless ( ref($content) eq 'GLOB' ) { my $charset = setting('charset'); my $ctype = $response->header('Content-Type'); if ( $charset && $ctype && _is_text($ctype) ) { $content = Encode::encode( $charset, $content ) unless $response->_already_encoded; $response->header( 'Content-Type' => "$ctype; charset=$charset" ) if $ctype !~ /$charset/; } $response->header( 'Content-Length' => length($content) ) if !defined $response->header('Content-Length'); $content = [$content]; } else { if ( !defined $response->header('Content-Length') ) { my $stat = stat $content; $response->header( 'Content-Length' => $stat->size ); } } # drop content if request is HEAD $content = [''] if ( defined Dancer::SharedData->request && Dancer::SharedData->request->is_head() ); # drop content AND content_length if response is 1xx or (2|3)04 if ($response->status =~ (/^[23]04$/ )) { $content = ['']; $response->header('Content-Length' => 0); } Dancer::Logger::core("response: " . $response->status); my $status = $response->status(); my $headers = $response->headers_to_array(); # reverse streaming if ( ref $response->streamed and ref $response->streamed eq 'CODE' ) { return $response->streamed->( $status, $headers ); } return [ $status, $headers, $content ]; } sub _is_text { my ($content_type) = @_; return $content_type =~ /(x(?:ht)?ml|text|json|javascript)/; } # Fancy banner to print on startup sub print_banner { if (setting('startup_info')) { my $env = setting('environment'); print "== Entering the $env dance floor ...\n"; } } sub dance { (shift)->start(@_) } 1; libdancer-perl-1.3120+dfsg.orig/lib/Dancer/Hook/0000755000175000017500000000000012256332256020503 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/lib/Dancer/Hook/Properties.pm0000644000175000017500000000172212233013020023153 0ustar gregoagregoapackage Dancer::Hook::Properties; use strict; use warnings; use base 'Dancer::Object'; Dancer::Hook::Properties->attributes(qw/apps/); sub init { my ($self, %args) = @_; $self->_init_apps(\%args); return $self; } sub _init_apps { my ( $self, $args ) = @_; if ( my $apps = $args->{'apps'} ) { ref $apps ? $self->apps($apps) : $self->apps( [$apps] ); return; } else { $self->apps( [] ); } } sub should_run_this_app { my ( $self, $app ) = @_; return 1 unless scalar( @{ $self->apps } ); if ( $self->apps ) { return grep { $_ eq $app } @{ $self->apps }; } } 1; =head1 NAME Dancer::Hook::Properties - Properties attached to a hook =head1 DESCRIPTION Properties attached to a hook =head1 SYNOPSIS =head1 METHODS =head1 AUTHORS This module has been written by Alexis Sukrieh and others. =head1 LICENSE This module is free software and is published under the same terms as Perl itself. libdancer-perl-1.3120+dfsg.orig/lib/Dancer/GetOpt.pm0000644000175000017500000000450012233013707021332 0ustar gregoagregoapackage Dancer::GetOpt; use strict; use warnings; use Dancer::Config 'setting'; use Getopt::Long; use FindBin; use File::Spec; my $options = { port => setting('port'), daemon => setting('daemon'), confdir => setting('confdir') || setting('appdir'), environment => 'development', }; sub arg_to_setting { my ($option, $value) = @_; setting($option => $value); } sub process_args { my $help = 0; GetOptions( 'help' => \$help, 'port=i' => sub { arg_to_setting(@_) }, 'daemon' => sub { arg_to_setting(@_) }, 'environment=s' => sub { arg_to_setting(@_) }, 'confdir=s' => sub { arg_to_setting(@_) }, 'restart=s' => sub { arg_to_setting( auto_reload => $_[1] ) }, ) || usage_and_exit(); usage_and_exit() if $help; } sub usage_and_exit { print_usage() && exit(0) } sub print_usage { my $app = File::Spec->catfile( $FindBin::RealBin, $FindBin::RealScript ); print < setting. Useful when you want to switch this setting for a test without changing the value in your configurations file. EOF } 'Dancer::GetOpt'; libdancer-perl-1.3120+dfsg.orig/lib/Dancer/Handler/0000755000175000017500000000000012256332256021160 5ustar gregoagregoalibdancer-perl-1.3120+dfsg.orig/lib/Dancer/Handler/Standalone.pm0000644000175000017500000000324112233013707023576 0ustar gregoagregoapackage Dancer::Handler::Standalone; use strict; use warnings; use HTTP::Server::Simple::PSGI; use base 'Dancer::Handler', 'HTTP::Server::Simple::PSGI'; use Dancer::HTTP; use Dancer::GetOpt; use Dancer::Config 'setting'; use Dancer::FileUtils qw(read_glob_content); use Dancer::SharedData; # in standalone mode, this method initializes the process # and start an HTTP server sub start { my $self = shift; my $ipaddr = setting('server'); my $port = setting('port'); my $dancer = Dancer::Handler::Standalone->new($port); $dancer->host($ipaddr); my $app = $self->psgi_app(); $dancer->app($app); if (setting('daemon')) { my $pid = $dancer->background(); print_startup_info($pid); return $pid; } else { print_startup_info($$); $dancer->run(); } } sub print_startup_info { my $pid = shift; my $ipaddr = setting('server'); my $port = setting('port'); # we only print the info if we need to setting('startup_info') or return; # bare minimum print STDERR ">> Dancer $Dancer::VERSION server $pid listening " . "on http://$ipaddr:$port\n"; # all loaded plugins foreach my $module ( grep { $_ =~ m{^Dancer/Plugin/} } keys %INC ) { $module =~ s{/}{::}g; # change / to :: $module =~ s{\.pm$}{}; # remove .pm at the end my $version = $module->VERSION; defined $version or $version = 'no version number defined'; print ">> $module ($version)\n"; } } # Restore expected behavior for wait(), as # HTTP::Server::Simple sets SIGCHLD to IGNORE. # (Issue #499) sub after_setup_listener { $SIG{CHLD} = ''; } 1; libdancer-perl-1.3120+dfsg.orig/lib/Dancer/Handler/Debug.pm0000644000175000017500000000466712246715364022565 0ustar gregoagregoapackage Dancer::Handler::Debug; use strict; use warnings; use HTTP::Headers; use HTTP::Server::Simple::PSGI; use base 'Dancer::Object', 'Dancer::Handler', 'HTTP::Server::Simple::PSGI'; use Dancer::Config 'setting'; use Dancer::SharedData; sub run { my ($self, $req) = @_; my ($method, $path, $query) = @ARGV; my $host = "127.0.0.1"; my $port = "3000"; my $env = { 'HTTP_ACCEPT' => '*/*', 'HTTP_HOST' => "$host:$port", 'HTTP_USER_AGENT' => 'curl', 'QUERY_STRING' => $query, 'REMOTE_ADDR' => "$host:$port", 'REMOTE_HOST' => "$host:$port", 'REQUEST_METHOD' => $method, 'REQUEST_URI' => $path, 'SERVER_NAME' => $host, 'SERVER_PORT' => $port, 'SERVER_PROTOCOL' => 'HTTP/1.1', 'SERVER_SOFTWARE' => 'HTTP::Server::Simple/0.41', 'SERVER_URL' => "http://$host:$port/", }; $req = Dancer::Request->new(env => $env); my $headers = HTTP::Headers->new( 'User-Agent' => 'curl', 'Host', "$host:$port", 'Accept', '*/*' ); $req->headers($headers); # now simulate a PSGI response for the current request only my $res = eval { $self->{psgi_app}->($env) } || [500, ['Content-Type', 'text/plain'], ["Internal Server Error"]]; $self->_handle_response($res); print "\n"; return $res; } sub start { my ($self, $req) = @_; print STDERR ">> Dancer dummy debug server\n" if setting('startup_info'); my $dancer = Dancer::Handler::Debug->new(); my $psgi = sub { my $env = shift; my $req = Dancer::Request->new(env => $env); $dancer->handle_request($req); }; $dancer->{psgi_app} = $psgi; $dancer->run($req); } sub dance { start(@_) } 1; __END__ =pod =head1 NAME Dancer::Handler::Debug - a debug handler for easy tracing =head1 DESCRIPTION When developing a Dancer application, it can be useful to trace precisely what happen when a query is processed. This handler is here to provide the developer with a way to easily run the dancer application with the Perl debugger. This handler will process only one query, based on the first argument given on the command line ($ARGV[0]). =head1 USAGE # in bin/app.pl set apphandler => 'Debug'; # then, run the app the following way perl -d bin/app.pl GET '/some/path/to/test' 'with=parameters&other=42' =head1 AUTHORS Dancer contributors libdancer-perl-1.3120+dfsg.orig/lib/Dancer/Handler/PSGI.pm0000644000175000017500000000570012233013707022252 0ustar gregoagregoapackage Dancer::Handler::PSGI; use strict; use warnings; use Carp; use base 'Dancer::Handler'; use Dancer::Deprecation; use Dancer::GetOpt; use Dancer::Config; use Dancer::ModuleLoader; use Dancer::SharedData; use Dancer::Logger; use Dancer::Exception qw(:all); sub new { my $class = shift; raise core_handler_PSGI => "Plack::Request is needed by the PSGI handler" unless Dancer::ModuleLoader->load('Plack::Request'); my $self = {}; bless $self, $class; } sub start { my $self = shift; my $app = $self->psgi_app(); foreach my $setting (qw/plack_middlewares plack_middlewares_map/) { if (Dancer::Config::setting($setting)) { my $method = 'apply_'.$setting; $app = $self->$method($app); } } return $app; } sub apply_plack_middlewares_map { my ($self, $app) = @_; my $mw_map = Dancer::Config::setting('plack_middlewares_map'); foreach my $req (qw(Plack::App::URLMap Plack::Builder)) { raise core_handler_PSGI => "$req is needed to use apply_plack_middlewares_map" unless Dancer::ModuleLoader->load($req); } my $urlmap = Plack::App::URLMap->new; while ( my ( $path, $mw ) = each %$mw_map ) { my $builder = Plack::Builder->new(); $builder->add_middleware(@$_) for @$mw; $urlmap->map( $path => $builder->to_app($app) ); } $urlmap->map('/' => $app) unless $mw_map->{'/'}; return $urlmap->to_app; } sub apply_plack_middlewares { my ($self, $app) = @_; my $middlewares = Dancer::Config::setting('plack_middlewares'); raise core_handler_PSGI => "Plack::Builder is needed for middlewares support" unless Dancer::ModuleLoader->load('Plack::Builder'); ref $middlewares eq "ARRAY" or raise core_handler_PSGI => "'plack_middlewares' setting must be an ArrayRef"; my $builder = Plack::Builder->new(); for my $mw (@$middlewares) { Dancer::Logger::core "add middleware " . $mw->[0]; $builder->add_middleware(@$mw) } return $builder->to_app($app); } sub init_request_headers { my ($self, $env) = @_; my $plack = Plack::Request->new($env); Dancer::SharedData->headers($plack->headers); } 1; __END__ =pod =head1 NAME Dancer::Handler::PSGI - a PSGI handler for Dancer applications =head1 DESCRIPTION This handler allows Dancer applications to run as part of PSGI stacks. Dancer will automatically determine when running in a PSGI environment and enable this handler, such that calling C will return a valid PSGI application. You may enable Plack middleware in your configuration file under the C key. See L for more information. Note that you must have L installed for this handler to work. =head1 USAGE # in bin/app.pl set apphandler => 'Debug'; # then, run the app the following way perl -d bin/app.pl GET '/some/path/to/test' 'with=parameters&other=42' =head1 AUTHORS Dancer contributors libdancer-perl-1.3120+dfsg.orig/lib/Dancer/Config.pm0000644000175000017500000004747212246715364021370 0ustar gregoagregoapackage Dancer::Config; use strict; use warnings; use base 'Exporter'; use vars '@EXPORT_OK'; use Dancer::Config::Object 'hashref_to_object'; use Dancer::Deprecation; use Dancer::Template; use Dancer::ModuleLoader; use Dancer::FileUtils 'path'; use Carp; use Dancer::Exception qw(:all); use Encode; @EXPORT_OK = qw(setting); my $SETTINGS = {}; # mergeable settings my %MERGEABLE = map { ($_ => 1) } qw( plugins handlers ); my %_LOADED; sub settings {$SETTINGS} my $setters = { logger => sub { my ($setting, $value) = @_; require Dancer::Logger; Dancer::Logger->init($value, settings()); }, log_file => sub { require Dancer::Logger; Dancer::Logger->init(setting("logger"), setting()); }, session => sub { my ($setting, $value) = @_; require Dancer::Session; Dancer::Session->init($value, settings()); }, template => sub { my ($setting, $value) = @_; require Dancer::Template; Dancer::Template->init($value, settings()); }, route_cache => sub { my ($setting, $value) = @_; require Dancer::Route::Cache; Dancer::Route::Cache->reset(); }, serializer => sub { my ($setting, $value) = @_; require Dancer::Serializer; Dancer::Serializer->init($value); }, # This setting has been deprecated in favor of global_warnings. import_warnings => sub { my ($setting, $value) = @_; Dancer::Deprecation->deprecated( message => "import_warnings has been deprecated, please use global_warnings instead." ); $^W = $value ? 1 : 0; }, global_warnings => sub { my ($setting, $value) = @_; $^W = $value ? 1 : 0; }, traces => sub { my ($setting, $traces) = @_; $Dancer::Exception::Verbose = $traces ? 1 : 0; }, }; $setters->{log_path} = $setters->{log_file}; my $normalizers = { charset => sub { my ($setting, $charset) = @_; length($charset || '') or return $charset; my $encoding = Encode::find_encoding($charset); defined $encoding or raise core_config => "Charset defined in configuration is wrong : couldn't identify '$charset'"; my $name = $encoding->name; # Perl makes a distinction between the usual perl utf8, and the strict # utf8 charset. But we don't want to make this distinction $name eq 'utf-8-strict' and $name = 'utf-8'; return $name; }, }; sub normalize_setting { my ($class, $setting, $value) = @_; $value = $normalizers->{$setting}->($setting, $value) if exists $normalizers->{$setting}; return $value; } # public accessor for get/set sub setting { if (@_ == 1) { return _get_setting(shift @_); } else { # can be useful for debug! Use Logger, instead? die "Odd number in 'set' assignment" unless scalar @_ % 2 == 0; my $count = 0; while (@_) { my $setting = shift; my $value = shift; _set_setting ($setting, $value); # At the moment, with any kind of hierarchical setter, # there is no case where the same trigger will be run more # than once. If/when a hierarchical setter is implemented, # we should create a list of the hooks that should be run, # and run them at the end of this while, only (efficiency # purposes). _trigger_hooks($setting, $value); $count++ } return $count; # just to return anything, the number of items set. } } sub _trigger_hooks { my ($setting, $value) = @_; $setters->{$setting}->(@_) if defined $setters->{$setting}; } sub _set_setting { my ($setting, $value) = @_; return unless @_ == 2; # normalize the value if needed $value = Dancer::Config->normalize_setting($setting, $value); $SETTINGS->{$setting} = $value; return $value; } sub _get_setting { my $setting = shift; return $SETTINGS->{$setting}; } sub conffile { path(setting('confdir') || setting('appdir'), 'config.yml') } sub environment_file { my $env = setting('environment'); # XXX for compatibility reason, we duplicate the code from `init_envdir` here # we don't know how if some application don't already do some weird stuff like # the test in `t/15_plugins/02_config.t`. my $envdir = setting('envdir') || path(setting('appdir'), 'environments'); return path($envdir, "$env.yml"); } sub init_confdir { return setting('confdir') if setting('confdir'); setting confdir => $ENV{DANCER_CONFDIR} || setting('appdir'); } sub init_envdir { return setting('envdir') if setting('envdir'); my $appdirpath = defined setting('appdir') ? path( setting('appdir'), 'environments' ) : path('environments'); setting envdir => $ENV{DANCER_ENVDIR} || $appdirpath; } sub load { init_confdir(); init_envdir(); # look for the conffile return 1 unless -f conffile; # load YAML my ( $result, $error ) = Dancer::ModuleLoader->load('YAML'); if ( not $result ) { confess "Configuration file found but could not load YAML: $error"; } if (!$_LOADED{conffile()}) { load_settings_from_yaml(conffile); $_LOADED{conffile()}++; } my $env = environment_file; # don't load the same env twice unless( $_LOADED{$env} ) { if (-f $env ) { load_settings_from_yaml($env); $_LOADED{$env}++; } elsif (setting('require_environment')) { # failed to load the env file, and the main config said we needed it. confess "Could not load environment file '$env', and require_environment is set"; } } foreach my $key (grep { $setters->{$_} } keys %$SETTINGS) { $setters->{$key}->($key, $SETTINGS->{$key}); } if ( $SETTINGS->{strict_config} ) { $SETTINGS = hashref_to_object($SETTINGS); } return 1; } sub load_settings_from_yaml { my ($file) = @_; my $config; eval { $config = YAML::LoadFile($file) }; if (my $err = $@ || (!$config)) { confess "Unable to parse the configuration file: $file: $@"; } for my $key (keys %{$config}) { if ($MERGEABLE{$key}) { my $setting = setting($key); $setting->{$_} = $config->{$key}{$_} for keys %{$config->{$key}}; } else { _set_setting($key, $config->{$key}); } } return scalar(keys %$config); } sub load_default_settings { $SETTINGS->{server} ||= $ENV{DANCER_SERVER} || '0.0.0.0'; $SETTINGS->{port} ||= $ENV{DANCER_PORT} || '3000'; $SETTINGS->{content_type} ||= $ENV{DANCER_CONTENT_TYPE} || 'text/html'; $SETTINGS->{charset} ||= $ENV{DANCER_CHARSET} || ''; $SETTINGS->{startup_info} ||= $ENV{DANCER_STARTUP_INFO} || 1; $SETTINGS->{daemon} ||= $ENV{DANCER_DAEMON} || 0; $SETTINGS->{apphandler} ||= $ENV{DANCER_APPHANDLER} || 'Standalone'; $SETTINGS->{warnings} ||= $ENV{DANCER_WARNINGS} || 0; $SETTINGS->{auto_reload} ||= $ENV{DANCER_AUTO_RELOAD} || 0; $SETTINGS->{traces} ||= $ENV{DANCER_TRACES} || 0; $SETTINGS->{server_tokens} ||= $ENV{DANCER_SERVER_TOKENS} || 1; $SETTINGS->{logger} ||= $ENV{DANCER_LOGGER} || 'file'; $SETTINGS->{environment} ||= $ENV{DANCER_ENVIRONMENT} || $ENV{PLACK_ENV} || 'development'; setting $_ => {} for keys %MERGEABLE; setting template => 'simple'; } load_default_settings(); 1; __END__ =pod =head1 NAME Dancer::Config - how to configure Dancer to suit your needs =head1 DESCRIPTION Dancer::Config handles reading and changing the configuration of your Dancer apps. The documentation for this module aims to describe how to change settings, and which settings are available. =head1 SETTINGS You can change a setting with the keyword B, like the following: use Dancer; # changing default settings set port => 8080; set content_type => 'text/plain'; set startup_info => 0; A better way of defining settings exists: using YAML file. For this to be possible, you have to install the L module. If a file named B exists in the application directory, it will be loaded, as a setting group. The same is done for the environment file located in the B directory. =head1 SUPPORTED SETTINGS =head2 Run mode and listening interface/port =head3 server (string) The IP address that the Dancer app should bind to. Default is 0.0.0.0, i.e. bind to all available interfaces. =head3 port (int) The port Dancer will listen to. Default value is 3000. This setting can be changed on the command-line with the B<--port> switch. =head3 daemon (boolean) If set to true, runs the standalone webserver in the background. This setting can be changed on the command-line with the B<--daemon> flag. =head3 behind_proxy (boolean) If set to true, Dancer will look to C and C when constructing URLs (for example, when using C. This is useful if your application is behind a proxy. =head2 Content type / character set =head3 content_type (string) The default content type of outgoing content. Default value is 'text/html'. =head3 charset (string) This setting has multiple effects: =over =item * It sets the default charset of outgoing content. C item will be added to Content-Type response header. =item * It makes Unicode bodies in HTTP responses of C types to be encoded to this charset. =item * It also indicates to Dancer in which charset the static files and templates are encoded. =item * If you're using L, UTF-8 support will automatically be enabled for your database - see L =back Default value is empty which means don't do anything. HTTP responses without charset will be interpreted as ISO-8859-1 by most clients. You can cancel any charset processing by specifying your own charset in Content-Type header or by ensuring that response body leaves your handler without Unicode flag set (by encoding it into some 8bit charset, for example). Also, since automatically serialized JSON responses have C Content-Type, you should always encode them by hand. =head3 default_mime_type (string) Dancer's L module uses C as a default mime type. This setting lets the user change it. For example, if you have a lot of files being served in the B folder that do not have an extension, and are text files, set the C to C. =head2 File / directory locations =head3 environment (string) This is the name of the environment that should be used. Standard Dancer applications have a C folder with specific configuration files for different environments (usually development and production environments). They specify different kind of error reporting, deployment details, etc. These files are read after the generic C configuration file. The running environment can be set with: set environment => "production"; Note that this variable is also used as a default value if other values are not defined. =head3 appdir (directory) This is the path where your application will live. It's where Dancer will look by default for your config files, templates and static content. It is typically set by C to use the same directory as your script. =head3 public (directory) This is the directory, where static files are stored. Any existing file in that directory will be served as a static file, before matching any route. By default, it points to $appdir/public. =head3 views (directory) This is the directory where your templates and layouts live. It's the "view" part of MVC (model, view, controller). This defaults to $appdir/views. =head2 Templating & layouts =head3 template Allows you to configure which template engine should be used. For instance, to use Template Toolkit, add the following to C: template: template_toolkit =head3 layout (string) The name of the layout to use when rendering view. Dancer will look for a matching template in the directory $views/layout. Your can override the default layout using the third argument of the C