libdancer-perl-1.3513+dfsg.orig/0000755000175000017500000000000013614371230015641 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/LICENSE0000644000175000017500000004366313614371230016662 0ustar gregoagregoaThis software is copyright (c) 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) 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. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 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) 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.3513+dfsg.orig/MANIFEST0000644000175000017500000002424113614371230016775 0ustar gregoagregoaAUTHORS CONTRIBUTORS Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL README SIGNATURE bin/dancer cpanfile doap.xml 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/HTTP.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/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/Policy.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/JSONP.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 lib/HTTP/Tiny/NoProxy.pm t/00-compile.t t/00-report-prereqs.dd t/00-report-prereqs.t 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/15_dependent_modules.t t/00_base/17_globalwarnings_config_on.t t/00_base/config.t t/00_base/easymocker.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_param_array.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/02_request/19_json_body.t t/02_request/20_body.t t/02_request/21_dancer_response_multiple_params.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/12_response_halt.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/16_embedded_prefixes.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/30_forward_session.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/36_false_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/07_apphandlers/08_is_text.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/05_template_toolkit_fromdata.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/11_logger/unicode.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/10_error_dumper_without_clone.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/07_request_jsonp.t t/14_serializer/17_clear_serializer.t t/14_serializer/18_mutable_template_or_serialize.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/05b_plugins_and_c3.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/23_dancer_tests/03_uris.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/author-pod-syntax.t t/TestAppExt.pm t/TestPlugin.pm t/lib/EasyMocker.pm t/lib/Forum.pm t/lib/FromDataApp.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/TestPluginMRO.pm t/lib/TestUtils.pm t/pod.t t/release-distmeta.t libdancer-perl-1.3513+dfsg.orig/Changes0000644000175000017500000025120713614371230017143 0ustar gregoagregoaRevision history for Dancer 1.3513 2020-01-29 21:00:41+00:00 Europe/London [BUG FIXES] - Fix test failures since YAML.pm 1.30 (GH #1208) - More test failures with proxy env var set (GH #1204) 1.3512 2019-03-31 20:10:08+01:00 Europe/London Promoting previous trial release 1.3511 to stable. 1.3511 2019-03-29 11:16:08+00:00 Europe/London (TRIAL RELEASE) [BUG FIXES] - More session cookie handling fun - avoid causing test failures in dependencies in some cases (e.g. RT #128911 and others) [ENHANCEMENTS] - hold session in SharedData, to avoid reading the session contents every time anything is requested, could be a performance win 1.3510 2019-03-19 14:42:26+00:00 Europe/London Promoting previous trial release 1.3501 to stable. Fix #1204 - more proxy-related test failure fun 1.3501 2019-03-14 19:19:49+00:00 Europe/London (TRIAL RELEASE) [BUG FIXES] Fix "too late to set cookie" errors if you access a session within an after hook after using send_file(). 1.3500 2018-10-12 21:31:46+01:00 Europe/London Promoting previous trial releases to stable. 1.3403 2018-10-11 23:41:11+01:00 Europe/London (TRIAL RELEASE) [ENHANCEMENTS] - request->address now respects behind_proxy - if behind_proxy is set, then request->address looks at HTTP_X_FORWARDED_FOR, so you get the user's IP, not the proxy. (PR-1199, bigpresh) - restore ability to use load_settings_from_yaml() without passing YAML parser class (PR-1198, snakpak) - Fixing some spurious cpantesters test failures by subclassing HTTP::Tiny in our tests and disabling proxying for 127.0.0.1 - otherwise smokers with HTTP proxy env vars set fail tests (PR-1197, bigpresh) - Tidied POD for Tutorial (PR-1196, manwar) 1.3402 2018-10-10 11:42:07+01:00 Europe/London (TRIAL RELEASE) 1.3401 2018-10-01 12:49:53+01:00 Europe/London (TRIAL RELEASE) [ENHANCEMENTS] - Avoid test failures on perls without '.' in @INC - censor cookie_key in dumps (PR-1193, thefatphil) - spelling fixes in POD from Debian Perl Group, PR-1191 1.3400 2018-06-15 23:08:34+01:00 Europe/London Promoting previous trial releases to stable. 1.3205 2018-06-13 22:59:32+01:00 Europe/London (TRIAL RELEASE) [ENHANCEMENTS] - require MIME::Types 2.17, as 2.16 has some funny ideas, like responding to a ZIP file with 'application/vnd.easykaraoke.cdgdownload' - Fix YAML-related test failures if YAML::XS not installed (GH 1184, PR 1189, bigpresh) [BUG FIXES] - Avoid accidental route matches if a previous successful match had left %+ populated (GH 1187, PR 1188, bigpresh, reported by skington) 1.3204 2018-05-23 14:40:33+01:00 Europe/London (TRIAL RELEASE) [ENHANCEMENTS] - Try to use 127.0.0.11 for listen tests, fall back to 127.0.0.1 on systems that don't have 127/8, e.g. FreeBSD (GH 1183, PR 1185, bigpresh) 1.3203 2018-05-20 20:44:30+01:00 Europe/London (TRIAL RELEASE) [DOCUMENTATION] - Add environment var hint to cookbook (PR 1161, castaway) [ENHANCEMENTS] - Make it possible to switch out YAML for YAML::XS for config parsing and serialisation (there was already an attempt at this in place, and it was documented as posisble, but didn't work) (PR 1164, 1nickt) - New test method response_redirect_like (PR 1159, 1nickt) - New config option raw_request_body_in_ram, which controls whether the raw request body is available via request->body or not. See Issue #1140 for the problems the previous approach, of getting it from the temp file that HTTP::Body might (or might not) have written it to. - Validate session IDs read from client - GH #1172 - potential security risk if the session provider in use passes the session ID in a way where injection is possible. 1.3301 2016-02-16 [BUG FIXES] - Reverted session ID validation (PR-1155) as it breaks Dancer::Session::Cookie (bigpresh) 1.3300 2016-02-15 [BUG FIXES] - More temp directory handling fixes (Issue #1147) - Avoid request body truncation in hand-assembled requests in tests (PR 1148, skington) - Avoid tests failing when "localhost" doesn't resolve (PR 1142, gbarco) - Avoid test failures due to race condition in selecting a port to listen on by using 127.0.0.10 instead (more of a hacky workaround than a fix, but should help (bigpresh) - Fix YAML session handler under taint mode (chrisjrob) - Make request->body work again for URL-encoded POST requests - Issue 1140 reported by miyagawa (bigpresh) - Validate session IDs read from cookies before passing to session engine, to protect against any engine that might feed that value straight to a file path for security - Issue 1118 (bigpresh) [DOCUMENTATION] - Better doc for forward_for_address (PR 1146, Relequestual) [ENHANCEMENTS] - Let Dancer::Test::dancer_response() handle supplying multiple params with the same name - Issue 1116 (bigpresh) 1.3202 2015-11-07 - Re-releasing 1.3200 again now CPAN perms should be fully sorted. 1.3201 2015-11-07 - Re-releasing 1.3200 now I should have the required permissions. (Can't re-upload as 1.3200 even though it wasn't indexed due to PAUSE restrictions) 1.3200 2015-11-06 [BUG FIXES] - Fix temporary directory handling in serialiser tests (PR 1133, nanis) [ENHANCEMENTS] - Promoting 1.3144 to stable. Only one odd, rare failure remains on CPAN Testers, which I cannot reproduce. - Bind to 127.0.0.1 in tests to avoid occasional spurious failures on busy build hosts (PR 1136, thanks to @redbaron) - More efficient handling of large requests - don't store the raw request body, but fish it out of the HTTP::Body object's temp file if required (PR 1134, David Precious (bigpresh)) [NEW FEATURES] - Allow mixd named params and splats in route definitions (PR 1086, veryrusty) 1.3144 2015-11-04 [ENHANCEMENTS] - Bind to 127.0.0.1 in tests to avoid occasional spurious failures on busy build hosts (PR 1136, thanks to @redbaron) 1.3143 2015-10-26 - Note: new release manager for Dancer1: David Precious (BIGPRESH) [BUG FIXES] - Fix temporary directory handling in serialiser tests (PR 1133, nanis) [ENHANCEMENTS] - More efficient handling of large requests - don't store the raw request body, but fish it out of the HTTP::Body object's temp file if required (PR 1134, David Precious (bigpresh)) [NEW FEATURES] - Allow mixd named params and splats in route definitions (PR 1086, veryrusty) 1.3142 2015-09-14 - Promotion to stable release. [STATISTICS] - code churn: 1 file changed, 15 insertions(+), 8 deletions(-) 1.3141 2015-09-07 [BUG FIXES] - Dancer::Logger::Abstract now always try to convert to the configured charset. (GH#1125, ironcamel) - Fix test that was failing on Windows because of platform-specific directory separators. (GH#1122, nanis) [STATISTICS] - code churn: 11 files changed, 52 insertions(+), 37 deletions(-) 1.3140 2015-07-03 - Promote 1.3139 to non-trial release. [STATISTICS] - code churn: 1 file changed, 17 insertions(+), 9 deletions(-) 1.3139 2015-06-25 [BUG FIXES] - Reverted caching of session, as it can cause problem when the user is using 'session->destroy' (GH#1120). - Reverted loading config from hash. (GH#1121) [STATISTICS] - code churn: 9 files changed, 55 insertions(+), 249 deletions(-) 1.3138 2015-06-12 - Promote 1.3137 to non-trial release. [STATISTICS] - code churn: 1 file changed, 1796 insertions(+), 1754 deletions(-) 1.3137 2015-06-05 [BUG FIXES] - Dancer::Logger->init invocation was using `setting()` instead of `settings()`. (GH#1103, jwittkoski) - Skip utf8 tests on cygwin. (GH#1046, mokko) - Dancer::Session::YAML now refuse cookies that aren't alphanumerical. (yanick) [ENHANCEMENTS] - Provide a way to load settings directly from hash. (GH#1113, fgabolde) - Remove 'auto-reload' feature. (GH#1058, alambike) - Add methods to interact with TT's wrappers. (GH#1034, David Zurborg) [STATISTICS] - code churn: 13 files changed, 277 insertions(+), 212 deletions(-) 1.3136 2015-05-24 [DOCUMENTATION] - Remove mention of format 'with_id' from Dancer::Logger::Abstract. (GH#112, Fabrice Gabolde) [ENHANCEMENTS] - Cache sessions such that they are only retrieved once per request. (GH#1105, GH#992, Yanick Champoux) [STATISTICS] - code churn: 7 files changed, 119 insertions(+), 16 deletions(-) 1.3135 2015-04-22 [DOCUMENTATION] - Document how to work with Dist::Zilla and the 'devel' branch. [ENHANCEMENTS] - Deprecate 'auto_reload' and document alternatives. (GH#1106, isync) - Change YAML tests to be in line with new specs. (GH#1108, Slaven Rezić) [STATISTICS] - code churn: 12 files changed, 150 insertions(+), 50 deletions(-) 1.3134 2015-02-22 [DOCUMENTATION] - Improve Dancer::Request documentation. (GH#1095, Gabor Szabo) - Added descriptions to a bunch of internal modules. (GH#1097, Brad Macpherson) - Correcting the documentation's grammar. (GH#1101, Jonathan Hall) - Improve Dancer.pm's documentation wrt the export of 'warnings'. (GH#1100, Brad Macpherson) - Generated development.yml was saying the logs appear on STDOUT whereas it's really STDERR. (GH#1102, Fabrice Gabolde) [ENHANCEMENTS] - Skip tests requiring 'fork' if on a perl that doesn't implement it. (GH#1094, Steve Hay) - Using ':script' disable command-line argument munging globally. (GH#1098, Brad Macpherson) [STATISTICS] - code churn: 33 files changed, 173 insertions(+), 113 deletions(-) 1.3133 2014-11-26 [BUG FIXES] - Test was failing for Perl 5.21+ (error message changed). (GH#1073, cpansprout) [DOCUMENTATION] - Mention environment variables in Dancer::Config. (GH#1085, Sniperovitch) - Replace "return send_file" with "send_file". (GH#1089, Ashley Willis) - Fix NAME section for Dancer::Plugin::Ajax. (GH#1090, Ivan Bessarabov) - Fix wrong layout directory in documentation. (GH#1091, olof) [ENHANCEMENTS] - Speedup in the upload of large files. (GH#1092, snakpak) [STATISTICS] - code churn: 6 files changed, 100 insertions(+), 35 deletions(-) 1.3132 2014-10-20 [STATISTICS] - code churn: 1 file changed, 12 insertions(+), 6 deletions(-) 1.3131_1 2014-10-13 [BUG FIXES] - One test would fail if Template::Toolkit was not installed. (GH#1083) [STATISTICS] - code churn: 2 files changed, 26 insertions(+), 10 deletions(-) 1.3131_0 2014-10-11 [BUG FIXES] - Test was failing under perl 5.8.9. (GH#1057, Tom Hukins) - Don't get tripped by YAML::XS's readonly values. (GH#1070) [DOCUMENTATION] - Minor doc update to detail how to pass protocol information in Apache (GH#1079, Andy Beverley) - Add the Dancer policy POD. [ENHANCEMENTS] - Dancer::Template::TemplateToolkit now supports DATA-embedded templates. (GH#1061, Jochen Lutz) - New function 'param_array'. (GH#1055, Yanick Champoux) - D::Serializer::YAML and Dancer::Config can now use 'YAML::XS'. [MISC] - Add 'YAML' as a recommended dependency. (GH#1080) [STATISTICS] - code churn: 14 files changed, 348 insertions(+), 30 deletions(-) 1.3130 2014-09-15 [BUG FIXES] - Bogus dependency for 'mro'. (GH#1069) [STATISTICS] - code churn: 2 files changed, 21 insertions(+), 12 deletions(-) 1.3129 2014-09-09 [BUG FIXES] - Dzil conversion left 'dancer' script behind. (GH#1066) [STATISTICS] - code churn: 17 files changed, 1425 insertions(+), 1432 deletions(-) 1.3128 2014-09-09 [BUG FIXES] - Remove test dependency for Person and Person::Child. (GH#1063) 1.3127 2014-09-08 [BUG FIXES] - Test was using deprecated 'import_warnings'. (GH#1045, mokko) - Fix default test names for headers and redirection test methods. (GH#1048, odyniec) - DANCER_SERVER_TOKENS and DANCER_SESSION_INFO are now DANCER_NO_SERVER_TOKENS and DANCER_NO_SESSION_INFO. And working. :-) (GH#1014, Yanick Champoux) - 'any' wasn't understanding 'del' (only 'delete'). (GH#1044, Yanick Champoux) [DISTRIBUTION] - Now using Dist::Zilla as package manager. [DOCUMENTATION] - Correct POD formatting for HTTP methods in introduction.pod. (GH#1047, Lx) [ENHANCEMENTS] - environment configs are now merged with the global config, versus the previous behavior that was overriding the whole config segments. (GH#1016, Yanick Champoux) - Dancer::Handler::Debug now accepts env variables from the command-line. (GH#1056, Yanick Champoux) - Accessing values abstracted as methods in Dancer::Session. (GH#1000, John Wittkoski) 1.3126 2014-07-14 [BUG FIXES] - Bunch of files were not in the MANIFEST. 1.3125 2014-07-12 [DOCUMENTATION] - Improve the wording of the params() section in Dancer. (GH#1025, Warren Young) - Explain how to access config in Dancer::Config's POD. (GH#1026, Gabor Szabo) - Cookbook typo fix. (GH#1031, Florian Sojer) [ENHANCEMENT] - Skip bad cookie definitions. (GH#1036, Manuel Weiss) - 'dancer' script warns and die if trying to create an app with the same name of an existing module. (GH#1038, Racke) - In Dancer::Logger::Abstract, default host name to '-' if not available. (GH#1029, John Wittkoski) - Add Dancer::Serializer::JSONP. (GH#1035, David Zurborg) 1.3124 2014-05-09 [BUG FIXES] - Remove print statement in Dancer::ModuleLoad::require. (GH#1021, John Wittkoski) - Test was failing if JSON module was absent. (GH#1022, Yanick Champoux) - Allow for routes evaluating to false ('0', '', etc). (GH#1020, Yanick Champoux) [DOCUMENTATION] - Specify defaults in POD. (GH#1023, isync) - Fix doc for params(). (GH#1025, reported by Warren Young) [ENHANCEMENTS] - Also check X-Forwarded-Proto. (GH#1015, Andy Jones) - Update bundle jQuery to v1.11.0. (GH#1018, Michal Wojciechowski) - Add session support to the skeleton config. (GH#1008. Gabor Szabo) [MISC] - Update mailing list url in README. (GH#1017, Racke) - Markdownify the README. (GH#986, Chris Seymour) 1.3123 2014-04-12 [BUG FIXES] - Test was skipping wrong number of tests if JSON was absent. 1.3122 2014-04-10 [BUG FIXES] - Serializer::Mutable now consider 'Accept' before 'Content-Type'. (GH#996, Bernhard Reutner-Fischer) - Serializer::Mutable now correctly deals with content-types with charsets. (GH#996, Bernhard Reutner-Fischer) - Without Clone(), Dancer::Error::dumper() could clobber values in deep structures. (GH#1006, fix by asergei) - 'session_name' in Dancer::Session::Abstract couldn't be redefined. (GH#1004, patch by Lee Carmichael) [DOCUMENTATION] - GH #995: Documentation improvements. (Colin Kuskie) [MISC] - Unused function 'path_no_verify' removed. (GH#998, reported by mjemmeson) 1.3121 2014-02-02 [DOCUMENTATION] - GH #983: Correction of various typos. (Akash Ayare) - GH #981: Add synopsis to Dancer::Request::Upload. (smashz) - GH #985: Change mentions of 'PerlHandler' to 'PerlResponseHandler' (Xaerxess) [ENHANCEMENTS] - GH #994: change heuristic so that 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' is not recognized as text. (Skeeve) - GH #987: get_current_session() now accepts option 'no_update'. (Lee Carmichael) 1.3120 2013-12-24 [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) [ENHANCEMENTS] - GH #974: Make plugins play nicely with mro 'c3'. (Fabrice Gabolde) 1.3119 2013-10-26 [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) [ENHANCEMENTS] - GH #965: Serializer also serialize content for DELETE. (reported by Achim Adam) 1.3118 2013-09-01 [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) [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) [MISC] - GH #949: fixes a few errors in the serializer testsuite. (Franck Cuny) 1.3117 2013-07-31 [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) [ENHANCEMENTS] - GH #836: Provide more information when an engine fails to load. (Yanick Champoux, reported by Daniel Perrett) 1.3116 2013-07-03 [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 2013-06-09 [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 2013-06-02 [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. [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) 1.3113 2013-05-08 [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). [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) 1.3112 2013-04-10 [BUG FIXES] - GH #900: backport the security patch for Dancer::ModuleLoader from Dancer2 (mokko). [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). 1.3111_02 2013-04-01 [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 2013-03-30 [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). [ENHANCEMENTS] - GH #895: JSON serializer now uses JSON's "-support_by_pp" (Jonathan Schatz). 1.3111 2013-02-24 [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 2012-10-06 [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). [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). [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). 1.3100 2012-08-25 [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) [DOCUMENTATION] - GH #818: Use "MyWeb::App" instead of "mywebapp" in examples. (pdl) [ENHANCEMENTS] - GH #755: HTTP::Headers accepted by dancer_response. (Roberto Patriarca) 1.3099 2012-08-11 [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) [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 ) [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) 1.3098 2012-07-28 [DOCUMENTATION] - Fix escaping on some docs (Stefan Hornburg @racke). [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). 1.3097 2012-07-08 [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 2012-07-06 - Codename: Chop Hooey // Neil Hooey ** [ENHANCEMENTS] - Finally released, thanks to Neil Hooey bugging my sorry ass. 1.3095_02 2012-07-03 [BUG FIXES] - fix exception tests in some cases (GH #734) (Damien Krotkine & katkad ) [DOCUMENTATION] - Clarify serialization in introduction POD (Mark A. Stratman) - Typo fix (Sam Kington) [ENHANCEMENTS] - If YAML does not load, Dancer::Config now reports why (Ovid) 1.3095_01 2012-06-22 [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) [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) [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) 1.3095 2012-04-01 [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 2012-03-31 [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) [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). [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). 1.3093 2012-02-29 [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) [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) [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) 1.3092 2012-01-27 [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-) [DOCUMENTATION] - Document how to work with Dotcloud. (Oliver Gorwits) - Clean ups and fix ups. (David Precious, Sawyer X, Michal Wojciechowski) [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) 1.3091 2011-12-17 [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) [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) [ENHANCEMENTS] - GH #711, #652: Add server_tokens variable to allow removal of headers. (John Wittkoski) 1.3090 2011-12-13 - 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 2011-11-26 [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). [DOCUMENTATION] - Clean up "plack_middlewares" example in docs (Richard Simões). [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). 1.3080 2011-10-25 - Codename: Sawyer's Sugar Stream // Sawyer X ** [ENHANCEMENTS] - No functional changes, just releasing as stable. 1.3079_05 2011-10-02 [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 2011-10-02 [DOCUMENTATION] - Dancer::Plugins typos (Olof Johansson). - PSGI handler documented (chromatic). [ENHANCEMENTS] - PSGI handler code cleaned up (chromatic). - Improved warning localizations (chromatic). 1.3079_03 2011-09-10 [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) [ENHANCEMENTS] - Support XML::Simple configuration for serializing/deserializing (Alberto Simões) - Hard deprecate lots of stuff (Alberto Simões) 1.3079_02 2011-08-28 [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.3079_01 2011-08-17 [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) [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) [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) 1.3072 2011-08-23 - Codename: Precious David Precious // David Precious (bigpresh) ** [ENHANCEMENTS] - No functional changes, just releasing as stable. 1.3071 2011-07-26 - 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 2011-07-14 - Codename: The Exceptional Mr. Dams // Damien Krotkine (dams) ** [ENHANCEMENTS] - No functional changes, just releasing as stable. 1.3069_02 2011-07-10 [BUG FIXES] - Fix a bunch of cpan testers reports (Alberto Simões) 1.3069_01 2011-07-07 [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) [DOCUMENTATION] - Documentation on tokens automatically added to templates. (Alberto Simões) - Documentation on serializer magical access to put/posted data. (Alberto Simões) [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) 1.3060 2011-06-15 - Codename: Pirouetting Pedro // Pedro Melo ** [ENHANCEMENTS] - No functional changes, just releasing as stable. 1.3059_04 2011-06-12 [BUG FIXES] - Fix a bunch of cpan testers reports - (Alberto Simões) 1.3059_03 2011-06-11 [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) [DOCUMENTATION] - Improve FileUtils documentation. (mokko) [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) 1.3059_02 2011-05-29 [BUG FIXES] - Fix for smoker failure under Perl 5.13.4 http://www.cpantesters.org/cpan/report/b37416b8-88df-11e0-9c74-cad5bcb80 94c Better use of Time::Hires in t/22_hooks/04_template.t (Franck Cuny) 1.3059_01 2011-05-27 [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) [DOCUMENTATION] - Improve Serializers documentation (Damien Krotkine) [ENHANCEMENTS] - Cookie accessor to manipulate cookies directly. (Niko) 1.3051 2011-05-27 - 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 2011-05-20 - Codename: The Captain Hook Adventure // Franck Cuny ** [DOCUMENTATION] - Improve Dancer documentation (Damien Krotkine) [ENHANCEMENTS] - No functional changes, just releasing as stable. 1.3049_01 2011-05-14 [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 2011-05-01 - Codename: Yanick in Black // Yanick Champoux, Labor Day - May Day ** [ENHANCEMENTS] - No functional changes, just releasing as stable. 1.3039_01 2011-04-27 [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) [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) [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) 1.3030 2011-04-13 - 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 2011-04-10 [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 2011-04-08 [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) [DOCUMENTATION] - POD fix. (Stefan Hornburg - Racke) [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) 1.3029_01 2011-04-01 [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) [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) [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) 1.3020 2011-03-21 - Codename: The Schwern Cometh // Michael G. Schwern ** [ENHANCEMENTS] - No functional changes, just releasing as stable. 1.3019_02 2011-03-14 [BUG FIXES] - GH #354: Tokens are not passed to layout if no params are passed to template. (Damien Krotkine) 1.3019_01 2011-03-13 [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 2011-03-10 [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) [DOCUMENTATION] - Dancing on command line. (Maurice Mengel) - Improve Dancer::Cookbook. (Maurice Mengel) [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) 1.3014 2011-03-04 [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 2011-03-01 [ENHANCEMENTS] - Fix test suite: the changelog test is skipped if not under RELEASE_TESTING environment. 1.3012 2011-03-01 [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) [DOCUMENTATION] - Add missing methods (e.g. "referer"), sorting, clean up. (Flavio Poletti) - Complete working example of deployment under Nginx/Starman in Deployment.pod (Geistteufel) [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) 1.3011 2011 .02.14 [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 2011 .02.12 [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) [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) [ENHANCEMENTS] - Better detection of the application layout under non-UNIX platforms. (Rowan Thorpe, Alexis Sukrieh) 1.3010 2011 .02.10 [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 2011 .02.06 [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) 1.3002 2011-02-02 [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) 1.3001 2011-01-27 [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). [David Precious] - Point people towards D::P::Database in the tutorial. - Mention leaving ratings on cpanratings. - Some minor typo fixed in the documentations. [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 [Hagen Fuchs] - Request.pm Decode HTTP::Request's uploads [jahmed] - Fix a bug in YAML session backend, during the creation of the session file. [mokko] - typos and a little more substatial changes to Development.pod 1.3000_02 2011-01-03 [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 [Sawyer X] - Added forward() functionality (incl. tests and docs) 1.3000_01 2010-12-22 [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. [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 [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) [Gabor Szabo] - Adding test for multi-leveled scaffolding. [Maurice Mengel (mokko)] - Skip file upload tests on Cygwin, not just win32. [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) [jamhed] - Fix some unicode issues, refactored all file openings in one function in Dancer::FileUtils. 1.2003 2010-12-10 - Production release. 1.2002_02 2010-12-08 [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. 1.2002_01 2010-12-07 [Franck Cuny] - Fix test failures on old machines with Test::More without done_testing. [Joel Roth] - Code fixes in documentation (Dancer::Session, Dancer::Introduction). 1.2002 2011-01-27 - Productionized! :) 1.2001_01 2010-12-02 [Danijel Tasov] - Default layout now validates. [David Precious, Ivan Bessarabov] - Fixing TT example config. 1.2001 2010-11-30 [David Precious] - Doc fixes. Clarifications to Cookbook's REST section. - Don't crash if application name is invalid and provide better information. [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 [Sawyer X] - Fix clash with KiokuDB because of Dancer::Serializer::Dumper. 1.2000 2011-01-27 - 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. 1.1999_04 2010-11-14 [Sawyer X] - Load Plack::Loader dynamically in test. [Yanick Champoux] - Doc fix. 1.1999_03 2010-11-11 [Al Newkirk] - fixed redirect to redirect immediately (+ refactoring by franck) [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 [Dave Doyle] - clarify Pod as to how before_template works [Franck Cuny] - Closes issue 181 (unknown log level) - Plack middlewares must be listed in an arrayref (listing them in a hashref is now deprecated) [Philippe Bruhat] - Dancer::Logger::Abstract: turn _should() into a closure, and avoid setting up the hash again and agai [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) 1.1999_02 2010-10-15 [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. [Damien Krotkine] - replace all die and warn with croak and carp [Franck Cuny] - Dancer::Test load D::Session::Simple - rewrite how Dancer handle HTTP headers - no more Dancer::Headers - all headers are HTTP::Headers object [Mark Allen] - Add a tutorial (Dancer::Tutorial) - example application 'Dancr', provided in example/ [Naveen] - add --version to the dancer CLI - changed the URI fetched by the dancer script to check Dancer's version [Philippe Bruhat] - use Pod::Usage 1.1999_01 2010-10-14 [Adam J. Foxson] - FIX for issue GH#136: "readline() on closed filehandle DATA" error that appears when running the app with Starman [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 [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' }; [Franck Cuny] - FIX for issue GH#129 don't add multiple content-type to headers - fix broken tests (they were testing incorrect content type) [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. [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) [Sebastian de Castelberg] - The dancer helper is able to download files via a transparent proxy (thanks to LWP). 1.1904 2011-01-27 [Sawyer X, Franck Cuny] - SAX, not Sax. - Check for XML::Parser or XML::SAX in test as well. 1.1903 2011-01-27 [Sawyer X, Franck Cuny] - XML::Simple needs either XML::SAX or XML::Parser. (fixed test fails from Dancer::Serializer::XML) 1.1902 2010-11-02 [Adam J. Foxson] - Addresses issue #136: "readline() on closed filehandle DATA" 1.1901 2010-09-24 [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). [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 1.1812 2010-09-21 [Alexis Sukrieh] - Fix for scaffolded apps - Dancer::Deployment cleanup (CGI section) - Declare LWP explicitly (already implied by HTTP::Body and HTTP::Headers) [Franck Cuny] - Skip bogus uploads test on Win32 (thanks to Alias for reporting) [Sawyer X] - Nitpicking at tabs and spaces at end of lines 1.1811 2010-09-03 [Franck Cuny] - FIX for issue #113 and #112 [Naveed Massjouni] - FIX for issues #111 and #108 1.1810 2010-09-01 [Alexis Sukrieh] - Fix a test that depends on YAML (pass if not present) (Smoker failure '2010-08-30T11:07:59Z'). [Naveed Massjouni] - FIX for issue #108 replaced Clone::clone() with Storable::dclone(). - Fixed the plan of one of the test files. 1.1809 2010-08-25 [Alexis Sukrieh] - fix plan for t/03_route_handler/24_named_captures.t [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 1.1808 2010-08-24 [Alexis Sukrieh] - FIX test failures - t/08_session/07_session_expires.t - t/08_session/07_session_expires.t 1.1807 2010-08-23 [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). [Naveed Massjouni] - Dancer::Test can now test requests with a body [Sawyer X] - Fix for RT #60403: removing Test::Exception requirement [jamhed] - Support for new setting "session_expire" in order to allow session cookies to expire before the browser is closed. 1.1806_02 2010-08-16 [David Precious] - Add Dancer::Plugins POD, describing useful plugins - Extend sessions & logging in entry in cookbook [François Charlier] - fix for GH#76 and GH#88 [James Aitken] - fix issues GH #84 #86 and #87 (failing tests on < 5.10 due to regex with named captures) [franck cuny] - update cookbook 1.1806_01 2010-08-15 [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. [Marc Chantreux] - Support for regexp objects in route definition - Support for named captures (keyword 'captures' added to Dancer's syntax). [jbarratt] - Dancer::Serializer::JSON supports 'allow_blessed' and 'convert_blessed' options. [sebastian de castelberg] - Support for path_info() in Dancer::Request so it's possible to mount an application under a directory. 1.1805 2010-06-22 [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) 1.1804 2010-06-18 [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 [Daniel Pittman] - FIX for issue #80 Make sure the tempfiles created during uploads are removed when the request object dies. [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 [sebastian de castelberg] - Fix priority in D::S::Mutable. 1.1803 2010-05-23 [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. 1.1802 2010-05-19 [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!) 1.1801 2010-05-19 [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. 1.1800 2010-05-16 [Alexis Sukrieh] - merge of the devel branch into master, first stable release of 1.178_01 and 1.178_02 1.178_02 2010-05-11 [Alexis Sukrieh] - Errors are caught in before filters - halt can be given a Dancer::Response object rahter than plain text content 1.178_01 2010-05-05 [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. [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. [Sawyer X] - Adding "import_warnings" settings. On by default, but allows to disable auto-import of "warnings" pragma. Reported by Adam Kennedy. 1.176 2010-04-22 - Bringing 1.175_01 into production. 1.175_01 2010-04-19 [Sawyer X] - Documentation for Dancer::FileUtils. - Documentation for Dancer::Cookie. - Fixing PNG bug on IE (reported by Adam Kennedy - thank you). 1.175 2010-04-11 [Alexis Sukrieh] - fixed t/15_plugins/02_config.t when YAML is not installed [Sawyer X] - RT #56395 reported by Jonathan Yu on behalf of Debian Perl team. - Documentation for Dancer::Error. 1.174 2010-04-08 [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. [Gabor Szabo] - Docs fixes, typo in warning. - TestUtils.pm is now in "t/lib". [Sawyer X] - RT #56381 reported by Jonathan Yu on behalf of Debian Perl team. (Adding LICENSE file) 1.173_01 2010-04-04 [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. [Franck Cuny] - Doc fixes. (Thanks to poisonbit) - Plugins configuration - Cleaning up tests [Sawyer X] - Fixed Windows PSGI.URL_SCHEME bug, causing tests to fail (Thanks to ADAMK for reporting) 1.173 2010-04-04 [Alexis Sukrieh] - Documenting set_cookie in Dancer.pm. [David Precious] - Fix issue 52 - creating invalid cookie expiration dates. Thanks to Juanjo (reidrac) for reporting! [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 1.172 2010-03-28 [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. 1.171 2010-03-24 [Alexis Sukrieh] - Removed bogus TestApp/ directory 1.170 2010-03-24 [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) [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. [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) [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) 1.160 2010-03-07 [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. [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 [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 1.150 2010-02-17 [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. [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(). [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 [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. [Paul Driver] - Support for virtual location. It's now possible to mount a Dancer app under a user-defined prefix. 1.140 2010-02-09 - 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 1.130 2010-01-29 - 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. 1.122 2010-01-16 - 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. 1.121 2010-01-15 - Fix for POST data parsing (was broken in 1.120) now Dancer depends on HTTP::Body for that. 1.120 2010-01-15 - 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) 1.110 2010-01-11 - Fix test script `t/11_logger/04_syslog.t' - Fix test script `t/10_template/05_template_toolkit.t' 1.100 2009-01-01 - 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) 1.000 2009-01-01 - 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) 0.9906 2009-01-01 - move from File::MimeInfo to File::MimeInfo::Simple for smooth run on Mac OSX and Win32 systems. 0.9005 2009-01-01 - Source code extract on error catching - Support for configurable error handling - New design for the starting app built with script/dancer 0.9004 2009-01-01 - Support for PSGI/Plack environment - script/dancer helper script for bootstraping a new app 0.9003 2009-01-01 - 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.3513+dfsg.orig/AUTHORS0000644000175000017500000001177313614371230016722 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 ] a-adam Achim Adam Adam J. Foxson Akash Ayare Al Newkirk Alan Haggai Alavi Alex Kalderimis Alex Kapranoff Andrei Andy Anirvan Chatterjee Anton Gerasimov asergei Ask Bjørn Hansen Bernhard Reutner-Fischer boris shomodjvarac Brian E. Lozier Brian Phillips burnersk Chris Andrews Chris Seymour chromatic Colin Keith Colin Kuskie 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 Michal Wojciechowski 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 Skeeve smashz Stefan Hornburg (Racke) Tatsuhiko Miyagawa tednolan Tom Heady Tom Hukins Tom Wyant Vyacheslav Matyukhin Xaerxess Zefram libdancer-perl-1.3513+dfsg.orig/INSTALL0000644000175000017500000000426313614371230016677 0ustar gregoagregoaThis is the Perl distribution Dancer. Installing Dancer is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm Dancer If it does not have permission to install modules to the current perl, cpanm will automatically set up and install to a local::lib in your home directory. See the local::lib documentation (https://metacpan.org/pod/local::lib) for details on enabling it in your environment. ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan Dancer ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, install configure prerequisites (see below), then build it: % perl Makefile.PL % make && make test Then install it: % make install On Windows platforms, you should use `dmake` or `nmake`, instead of `make`. If your perl is system-managed, you can create a local::lib in your home directory to install modules to. For details, see the local::lib documentation: https://metacpan.org/pod/local::lib The prerequisites of this distribution will also have to be installed manually. The prerequisites are listed in one of the files: `MYMETA.yml` or `MYMETA.json` generated by running the manual build process described above. ## Configure Prerequisites This distribution requires other modules to be installed before this distribution's installer can be run. They can be found under the "configure_requires" key of META.yml or the "{prereqs}{configure}{requires}" key of META.json. ## Other Prerequisites This distribution may require additional modules to be installed after running Makefile.PL. Look for prerequisites in the following phases: * to run make, PHASE = build * to use the module code itself, PHASE = runtime * to run tests, PHASE = test They can all be found in the "PHASE_requires" key of MYMETA.yml or the "{prereqs}{PHASE}{requires}" key of MYMETA.json. ## Documentation Dancer documentation is available as POD. You can run `perldoc` from a shell to read the documentation: % perldoc Dancer For more information on installing Perl modules via CPAN, please see: https://www.cpan.org/modules/INSTALL.html libdancer-perl-1.3513+dfsg.orig/cpanfile0000644000175000017500000000426613614371230017355 0ustar gregoagregoarequires "Carp" => "0"; requires "Cwd" => "0"; requires "Data::Dumper" => "0"; requires "Encode" => "0"; requires "Exporter" => "0"; requires "Fcntl" => "0"; requires "File::Basename" => "0"; requires "File::Copy" => "0"; requires "File::Path" => "0"; requires "File::Spec" => "0"; requires "File::Spec::Functions" => "0"; requires "File::Temp" => "0"; requires "File::stat" => "0"; requires "FindBin" => "0"; requires "Getopt::Long" => "0"; requires "HTTP::Body" => "0"; requires "HTTP::Date" => "0"; requires "HTTP::Headers" => "0"; requires "HTTP::Server::Simple::PSGI" => "0"; requires "HTTP::Tiny" => "0.014"; requires "Hash::Merge::Simple" => "0"; requires "IO::File" => "0"; requires "MIME::Types" => "0"; requires "Module::Runtime" => "0"; requires "POSIX" => "0"; requires "Pod::Usage" => "0"; requires "Scalar::Util" => "0"; requires "Test::Builder" => "0"; requires "Test::More" => "0"; requires "Time::HiRes" => "0"; requires "Try::Tiny" => "0"; requires "URI" => "0"; requires "URI::Escape" => "0"; requires "base" => "0"; requires "bytes" => "0"; requires "constant" => "0"; requires "lib" => "0"; requires "overload" => "0"; requires "parent" => "0"; requires "strict" => "0"; requires "vars" => "0"; requires "warnings" => "0"; recommends "MIME::Types" => "2.17"; recommends "YAML" => "0"; recommends "YAML::XS" => "0"; on 'test' => sub { requires "Data::Dump" => "0"; requires "Devel::Hide" => "0"; requires "Digest::MD5" => "0"; requires "ExtUtils::MakeMaker" => "0"; requires "File::Spec" => "0"; requires "HTTP::CookieJar" => "0.008"; requires "HTTP::Request" => "0"; requires "HTTP::Tiny" => "0.014"; requires "IO::Handle" => "0"; requires "IO::Socket::INET" => "0"; requires "IPC::Open3" => "0"; requires "JSON" => "2.90"; requires "Plack::Builder" => "0"; requires "Test::More" => "0"; requires "Test::NoWarnings" => "0"; requires "perl" => "5.006"; requires "utf8" => "0"; }; on 'test' => sub { recommends "CPAN::Meta" => "2.120900"; }; on 'configure' => sub { requires "ExtUtils::MakeMaker" => "0"; }; on 'configure' => sub { suggests "JSON::PP" => "2.27300"; }; on 'develop' => sub { requires "Test::CPAN::Meta" => "0"; requires "Test::Pod" => "1.41"; }; libdancer-perl-1.3513+dfsg.orig/doap.xml0000644000175000017500000021247513614371230017321 0ustar gregoagregoa Dancer lightweight yet powerful web application framework 1nickt a-adam Achim Adam Adam J. Foxson Adam Kennedy Akash Ayare alambike Alan Haggai Alavi Alberto Simoes Alessandro Ranellucci Alex C Alexis Sukrieh Alex Kalderimis Alex Kapranoff Alex Peters Alfie John Al Newkirk Al Newkirk Andrew Beverley andy Anirvan Chatterjee Anton Gerasimov asergei Ashley Willis A. Sinan Unur Ask Bjørn Hansen Assaf Gordon Ben Hutton Bernhard Reutner-Fischer boris shomodjvarac Brad Macpherson Breno G. de Oliveira Brian E. Lozier Brian Hann Brian Phillips burnersk Chris Andrews chrisjrob Chris Seymour Christian Walde chromatic Colin Keith Colin Kuskie CPAN Service Craig Treptow Dagfinn Ilmari Mannsåker Damien Krotkine Damien Krotkine Damyan Ivanov Dan Book Dan Book Danijel Tasov Dave Doyle David Cantrell David Golden David Moreno David Precious David Steinbrunner David Zurborg Dennis Lichtenthaeler Duncan Hutty Emmanuel Rodriguez Fabrice Gabolde Fabrice Gabolde Fabrice Gabolde Fayland Lam Felix Dorner Flavio Poletti Florian Larysch Florian Sojer Franck Cuny François Charlier François Charlier Gabor Szabo Gary Mullen geistteufel Gil Magno Gonzalo Barco Graham Knop Grzegorz Rożniecki Hagen Fuchs Hans Dieter Pearcey Ilmari Vacklin Ilya Chesnokov isync Ivan Bessarabov Ivan Paponov Jacob Rideout Jakob Voss James Aitken jamhed Jess Jesse van Herk Jochen Lutz Joel Roth John Barrett John Wittkoski jonasreinsch Jonathan "Duke" Leto Jonathan Hall Jonathan Otsuka jonathan schatz Jonathan Scott Duff Joshua Barratt JT Smith Juan J. Martínez Jury Gorky Kaitlyn Parkhurst Kent Fredric Kirk Kimmel Lars Thegler Lee Carmichael Lee Johnson Manuel Weiss Marc Chantreux Mark Allen Mark A. Stratman Mark Stosberg Martin Schut Matthew Horsfall alh Maurice Maxim Ivanov Max Maischein Michael Genereux Michael G. Schwern Michal Wojciechowski Mikolaj Kucharski miyagawa mlbarrow Mohammad S Anwar Murray Natal Ngétal Nate Jones Naveed Massjouni Naveed Massjouni Naveed Naveen Neil Hooey Nick Tonkin Nicolas Oudard niko Nuno Carvalho Oliver Gorwits Olivier Mengué Olof Johansson Ovid Paul Driver Paul Fenwick Paul Johnson Paul Tomlin pdl Pedro Melo Perlover Phil Carmody Philippe Bruhat BooK ppisar Richard Simões Rick Myers Rik Brown Roberto Patriarca Roman Galeev Roman Nuritdinov Rowan Thorpe Russell Jenkins Sam Kington Sapphire Paw Sawyer X scoopio Scott Penrose sdeseille Sean Smith Sebastian de Castelberg Skeeve Slaven Rezic Sniperovitch Squeeks Stefan Hornburg Racke Steve Hay Tatsuhiko Miyagawa tednolan Tim King Tom Heady Tom Hukins Tom Wyant Vyacheslav Matyukhin William Wolf Yanick Champoux YOUR_NAME Zefram 0.9003 2009-01-01 0.9004 2009-01-01 0.9005 2009-01-01 0.9906 2009-01-01 1.000 2009-01-01 1.100 2009-01-01 1.110 2010-01-11 1.120 2010-01-15 1.121 2010-01-15 1.122 2010-01-16 1.130 2010-01-29 1.140 2010-02-09 1.150 2010-02-17 1.160 2010-03-07 1.170 2010-03-24 1.171 2010-03-24 1.172 2010-03-28 1.173 2010-04-04 1.173_01 2010-04-04 1.174 2010-04-08 1.175 2010-04-11 1.175_01 2010-04-19 1.176 2010-04-22 1.178_01 2010-05-05 1.178_02 2010-05-11 1.1800 2010-05-16 1.1801 2010-05-19 1.1802 2010-05-19 1.1803 2010-05-23 1.1804 2010-06-18 1.1805 2010-06-22 1.1806_01 2010-08-15 1.1806_02 2010-08-16 1.1807 2010-08-23 1.1808 2010-08-24 1.1809 2010-08-25 1.1810 2010-09-01 1.1811 2010-09-03 1.1812 2010-09-21 1.1901 2010-09-24 1.1902 2010-11-02 1.1903 2011-01-27 1.1904 2011-01-27 1.1999_01 2010-10-14 1.1999_02 2010-10-15 1.1999_03 2010-11-11 1.1999_04 2010-11-14 1.2000 2011-01-27 1.2001 2010-11-30 1.2001_01 2010-12-02 1.2002 2011-01-27 1.2002_01 2010-12-07 1.2002_02 2010-12-08 1.2003 2010-12-10 1.3000_01 2010-12-22 1.3000_02 2011-01-03 1.3001 2011-01-27 1.3002 2011-02-02 1.3003 2011 1.3010 2011 1.3010_01 2011 1.3011 2011 1.3012 2011-03-01 1.3013 2011-03-01 1.3014 2011-03-04 1.3014_01 2011-03-10 1.3019_01 2011-03-13 1.3019_02 2011-03-14 1.3020 2011-03-21 1.3029_01 2011-04-01 1.3029_02 2011-04-08 1.3029_03 2011-04-10 1.3030 2011-04-13 1.3039_01 2011-04-27 1.3040 2011-05-01 1.3049_01 2011-05-14 1.3050 2011-05-20 1.3051 2011-05-27 1.3059_01 2011-05-27 1.3059_02 2011-05-29 1.3059_03 2011-06-11 1.3059_04 2011-06-12 1.3060 2011-06-15 1.3069_01 2011-07-07 1.3069_02 2011-07-10 1.3070 2011-07-14 1.3071 2011-07-26 1.3072 2011-08-23 1.3079_01 2011-08-17 1.3079_02 2011-08-28 1.3079_03 2011-09-10 1.3079_04 2011-10-02 1.3079_05 2011-10-02 1.3080 2011-10-25 1.3089_01 2011-11-26 1.3090 2011-12-13 1.3091 2011-12-17 1.3092 2012-01-27 1.3093 2012-02-29 1.3094 2012-03-31 1.3095 2012-04-01 1.3095_01 2012-06-22 1.3095_02 2012-07-03 1.3096 2012-07-06 1.3097 2012-07-08 1.3098 2012-07-28 1.3099 2012-08-11 1.3100 2012-08-25 1.3110 2012-10-06 1.3111 2013-02-24 1.3111_01 2013-03-30 1.3111_02 2013-04-01 1.3112 2013-04-10 1.3113 2013-05-08 1.3114 2013-06-02 1.3115 2013-06-09 1.3116 2013-07-03 1.3117 2013-07-31 1.3118 2013-09-01 1.3119 2013-10-26 1.3120 2013-12-24 1.3121 2014-02-02 1.3122 2014-04-10 1.3123 2014-04-12 1.3124 2014-05-09 1.3125 2014-07-12 1.3126 2014-07-14 1.3127 2014-09-08 1.3128 2014-09-09 1.3129 2014-09-09 1.3130 2014-09-15 1.3131_0 2014-10-11 1.3131_1 2014-10-13 1.3132 2014-10-20 1.3133 2014-11-26 1.3134 2015-02-22 1.3135 2015-04-22 1.3136 2015-05-24 1.3137 2015-06-05 1.3138 2015-06-12 1.3139 2015-06-25 1.3140 2015-07-03 1.3141 2015-09-07 1.3142 2015-09-14 1.3143 2015-10-26 1.3144 2015-11-04 1.3200 2015-11-06 1.3201 2015-11-07 1.3202 2015-11-07 1.3203 2018-05-20T20:44:30+01:00 1.3204 2018-05-23T14:40:33+01:00 1.3205 2018-06-13T22:59:32+01:00 1.3300 2016-02-15 1.3301 2016-02-16 1.3400 2018-06-15T23:08:34+01:00 1.3401 2018-10-01T12:49:53+01:00 1.3402 2018-10-10T11:42:07+01:00 1.3403 2018-10-11T23:41:11+01:00 1.3500 2018-10-12T21:31:46+01:00 1.3501 2019-03-14T19:19:49+00:00 1.3510 2019-03-19T14:42:26+00:00 1.3511 2019-03-29T11:16:08+00:00 1.3512 2019-03-31T20:10:08+01:00 Perl libdancer-perl-1.3513+dfsg.orig/README0000644000175000017500000012726013614371230016531 0ustar gregoagregoaNAME Dancer - lightweight yet powerful web application framework VERSION version 1.3513 SYNOPSIS #!/usr/bin/perl use Dancer; get '/hello/:name' => sub { return "Why, hello there " . param('name'); }; dance; The above is a basic but functional web app created with Dancer. If you want to see more examples and get up and running quickly, check out the Dancer::Introduction and the Dancer::Cookbook. For examples on deploying your Dancer applications, see Dancer::Deployment. DESCRIPTION Dancer is a web application framework designed to be as effortless as possible for the developer, taking care of the boring bits as easily as possible, yet staying out of your way and letting you get on with writing your code. Dancer aims to provide the simplest way for writing web applications, and offers the flexibility to scale between a very simple lightweight web service consisting of a few lines of code in a single file, all the way up to a more complex fully-fledged web application with session support, templates for views and layouts, etc. If you don't want to write CGI scripts by hand, and find Catalyst too big or cumbersome for your project, Dancer is what you need. Dancer has few pre-requisites, so your Dancer webapps will be easy to deploy. Dancer apps can be used with an embedded web server (great for easy testing), and can run under PSGI/Plack for easy deployment in a variety of webserver environments. MORE DOCUMENTATION This documentation describes all the exported symbols of Dancer. If you want a quick start guide to discover the framework, you should look at Dancer::Introduction, or Dancer::Tutorial to learn by example. If you want to have specific examples of code for real-life problems, see the Dancer::Cookbook. If you want to see configuration examples of different deployment solutions involving Dancer and Plack, see Dancer::Deployment. You can find out more about the many useful plugins available for Dancer in Dancer::Plugins. DANCER 2 This is the original version of Dancer, which is now in maintenance mode. This means that it will not receive significant new features, but will continue to receive bugfixes and security fixes. However, no "end of life" date has been set, and it is expected that this version of Dancer will continue to receive bugfixes and security fixes for quite some time yet. However, you should consider migrating to Dancer2 instead when you can, and are advised to use Dancer2 for newly-started apps. Dancer2 is mostly backwards compatible, but has been re-written from the ground up to be more maintainable and extensible, and is the future of Dancer. Dancer2::Manual::Migration covers the changes you should be aware of when migrating an existing Dancer 1 powered app to Dancer 2. EXPORTS By default, use Dancer exports all the functions below plus sets up your app. You can control the exporting through the normal Exporter mechanism. For example: # Just export the route controllers use Dancer qw(get post put patch del); # Export everything but pass to avoid clashing with Test::More use Test::More; use Dancer qw(!pass); Please note that the utf8 and strict pragmas are exported by this module. By default, the warnings pragma will also be exported, meaning your app/script will be running under use warnings. If you do not want this, set the global_warnings setting to a false value. There are also some special tags to control exports and behaviour. :moose This will export everything except functions which clash with Moose. Currently these are after and before. :syntax This tells Dancer to just export symbols and not set up your app. This is most useful for writing Dancer code outside of your main route handler. :tests This will export everything except functions which clash with commonly used testing modules. Currently these are pass. It can be combined with other export pragmas. For example, while testing... use Test::More; use Dancer qw(:syntax :tests); # Test::Most also exports "set" and "any" use Test::Most; use Dancer qw(:syntax :tests !set !any); # Alternatively, if you want to use Dancer's set and any... use Test::Most qw(!set !any); use Dancer qw(:syntax :tests); :script This will export all the keywords, load the configuration, and will not try to parse command-line arguments via Dancer::GetOpt. This is useful when you want to use your Dancer application from a script. use MyApp; use Dancer ':script'; MyApp::schema('DBSchema')->deploy(); Note that using :script will disable command-line parsing for all subsequent invocations of use Dancer (such that you don't have to use :script for each and every module to make sure the command-line arguments don't get stolen by Dancer). !keyword If you want to simply prevent Dancer from exporting specific keywords (perhaps you plan to implement them yourself in a different way, or you don't plan to use them and they clash with another module you're loading), you can simply exclude them: use Dancer qw(!session); The above would import all keywords as normal, with the exception of session. FUNCTIONS after Deprecated - see the after hook. any Defines a route for multiple HTTP methods at once: any ['get', 'post'] => '/myaction' => sub { # code }; Or even, a route handler that would match any HTTP methods: any '/myaction' => sub { # code }; before Deprecated - see the before hook. before_template Deprecated - see the before_template hook. cookies Accesses cookies values, it returns a HashRef of Dancer::Cookie objects: get '/some_action' => sub { my $cookie = cookies->{name}; return $cookie->value; }; In the case you have stored something other than a Scalar in your cookie: get '/some_action' => sub { my $cookie = cookies->{oauth}; my %values = $cookie->value; return ($values{token}, $values{token_secret}); }; cookie Accesses a cookie value (or sets it). Note that this method will eventually be preferred over set_cookie. cookie lang => "fr-FR"; # set a cookie and return its value cookie lang => "fr-FR", expires => "2 hours"; # extra cookie info cookie "lang" # return a cookie value If your cookie value is a key/value URI string, like token=ABC&user=foo cookie will only return the first part (token=ABC) if called in scalar context. Use list context to fetch them all: my @values = cookie "name"; Note that if the client has sent more than one cookie with the same value, the one returned will be the last one seen. This should only happen if you have set multiple cookies with the same name but different paths. So, don't do that. config Accesses the configuration of the application: get '/appname' => sub { return "This is " . config->{appname}; }; content_type Sets the content-type rendered, for the current route handler: get '/cat/:txtfile' => sub { content_type 'text/plain'; # here we can dump the contents of param('txtfile') }; You can use abbreviations for content types. For instance: get '/svg/:id' => sub { content_type 'svg'; # here we can dump the image with id param('id') }; Note that if you want to change the default content-type for every route, you have to change the content_type setting instead. dance Alias for the start keyword. dancer_version Returns the version of Dancer. If you need the major version, do something like: int(dancer_version); debug Logs a message of debug level: debug "This is a debug message"; See Dancer::Logger for details on how to configure where log messages go. dirname Returns the dirname of the path given: my $dir = dirname($some_path); engine Given a namespace, returns the current engine object my $template_engine = engine 'template'; my $html = $template_engine->apply_renderer(...); $template_engine->apply_layout($html); error Logs a message of error level: error "This is an error message"; See Dancer::Logger for details on how to configure where log messages go. false Constant that returns a false value (0). forward Runs an internal redirect of the current request to another request. This helps you avoid having to redirect the user using HTTP and set another request to your application. It effectively lets you chain routes together in a clean manner. get '/demo/articles/:article_id' => sub { # you'll have to implement this next sub yourself :) change_the_main_database_to_demo(); forward "/articles/" . params->{article_id}; }; In the above example, the users that reach /demo/articles/30 will actually reach /articles/30 but we've changed the database to demo before. This is pretty cool because it lets us retain our paths and offer a demo database by merely going to /demo/.... You'll notice that in the example we didn't indicate whether it was GET or POST. That is because forward chains the same type of route the user reached. If it was a GET, it will remain a GET (but if you do need to change the method, you can do so; read on below for details.) WARNING : using forward will not preserve session data set on the forwarding rule. WARNING : Issuing a forward immediately exits the current route, and perform the forward. Thus, any code after a forward is ignored, until the end of the route. e.g. get '/foo/:article_id' => sub { if ($condition) { forward "/articles/" . params->{article_id}; # The following code is never executed do_stuff(); } more_stuff(); }; So it's not necessary anymore to use return with forward. Note that forward doesn't parse GET arguments. So, you can't use something like: return forward '/home?authorized=1'; But forward supports an optional HashRef with parameters to be added to the actual parameters: return forward '/home', { authorized => 1 }; Finally, you can add some more options to the forward method, in a third argument, also as a HashRef. That option is currently only used to change the method of your request. Use with caution. return forward '/home', { auth => 1 }, { method => 'POST' }; from_dumper ($structure) Deserializes a Data::Dumper structure. from_json ($structure, \%options) Deserializes a JSON structure. Can receive optional arguments. Those arguments are valid JSON arguments to change the behaviour of the default JSON::from_json function. Compatibility notice: from_json changed in 1.3002 to take a hashref as options, instead of a hash. from_yaml ($structure) Deserializes a YAML structure. from_xml ($structure, %options) Deserializes a XML structure. Can receive optional arguments. These arguments are valid XML::Simple arguments to change the behaviour of the default XML::Simple::XMLin function. get Defines a route for HTTP GET requests to the given path: get '/' => sub { return "Hello world"; } Note that a route to match HEAD requests is automatically created as well. halt Sets a response object with the content given. When used as a return value from a filter, this breaks the execution flow and renders the response immediately: hook before sub { if ($some_condition) { halt("Unauthorized"); # This code is not executed : do_stuff(); } }; get '/' => sub { "hello there"; }; WARNING : Issuing a halt immediately exits the current route, and perform the halt. Thus, any code after a halt is ignored, until the end of the route. So it's not necessary anymore to use return with halt. headers Adds custom headers to responses: get '/send/headers', sub { headers 'X-Foo' => 'bar', X-Bar => 'foo'; } header adds a custom header to response: get '/send/header', sub { header 'x-my-header' => 'shazam!'; } Note that it will overwrite the old value of the header, if any. To avoid that, see "push_header". push_header Do the same as header, but allow for multiple headers with the same name. get '/send/header', sub { push_header 'x-my-header' => '1'; push_header 'x-my-header' => '2'; will result in two headers "x-my-header" in the response } hook Adds a hook at some position. For example : hook before_serializer => sub { my $response = shift; $response->content->{generated_at} = localtime(); }; There can be multiple hooks assigned to a given position, and each will be executed in order. Note that all hooks are always called, even if they are defined in a different package loaded via load_app. (For details on how to register new hooks from within plugins, see Dancer::Hook.) Supported before hooks (in order of execution): before_deserializer This hook receives no arguments. hook before_deserializer => sub { ... }; before_file_render This hook receives as argument the path of the file to render. hook before_file_render => sub { my $path = shift; ... }; before_error_init This hook receives as argument a Dancer::Error object. hook before_error_init => sub { my $error = shift; ... }; before_error_render This hook receives as argument a Dancer::Error object. hook before_error_render => sub { my $error = shift; }; before This hook receives one argument, the route being executed (a Dancer::Route object). hook before => sub { my $route_handler = shift; ... }; it is equivalent to the deprecated before sub { ... }; before_template_render This is an alias to 'before_template'. This hook receives as argument a HashRef containing the tokens that will be passed to the template. You can use it to add more tokens, or delete some specific token. hook before_template_render => sub { my $tokens = shift; delete $tokens->{user}; $tokens->{time} = localtime; }; is equivalent to hook before_template => sub { my $tokens = shift; delete $tokens->{user}; $tokens->{time} = localtime; }; before_layout_render This hook receives two arguments. The first one is a HashRef containing the tokens. The second is a ScalarRef representing the content of the template. hook before_layout_render => sub { my ($tokens, $html_ref) = @_; ... }; before_serializer This hook receives as argument a Dancer::Response object. hook before_serializer => sub { my $response = shift; $response->content->{start_time} = time(); }; Supported after hooks (in order of execution): after_deserializer This hook receives no arguments. hook after_deserializer => sub { ... }; after_file_render This hook receives as argument a Dancer::Response object. hook after_file_render => sub { my $response = shift; }; after_template_render This hook receives as argument a ScalarRef representing the content generated by the template. hook after_template_render => sub { my $html_ref = shift; }; after_layout_render This hook receives as argument a ScalarRef representing the content generated by the layout hook after_layout_render => sub { my $html_ref = shift; }; after This is an alias for after. This hook runs after a request has been processed, but before the response is sent. It receives a Dancer::Response object, which it can modify if it needs to make changes to the response which is about to be sent. hook after => sub { my $response = shift; }; This is equivalent to the deprecated after sub { my $response = shift; }; after_error_render This hook receives as argument a Dancer::Response object. hook after_error_render => sub { my $response = shift; }; on_handler_exception This hook is called when an exception has been caught, at the handler level, just before creating and rendering Dancer::Error. This hook receives as argument a Dancer::Exception object. hook on_handler_exception => sub { my $exception = shift; }; on_reset_state This hook is called when global state is reset to process a new request. It receives a boolean value that indicates whether the reset was called as part of a forwarded request. hook on_reset_state => sub { my $is_forward = shift; }; on_route_exception This hook is called when an exception has been caught, at the route level, just before rethrowing it higher. This hook receives the exception as argument. It can be a Dancer::Exception, or a string, or whatever was used to die. hook on_route_exception => sub { my $exception = shift; }; info Logs a message of info level: info "This is a info message"; See Dancer::Logger for details on how to configure where log messages go. layout This method is deprecated. Use set: set layout => 'user'; logger Deprecated. Use 'console'> to change current logger engine. load Loads one or more perl scripts in the current application's namespace. Syntactic sugar around Perl's require: load 'UserActions.pl', 'AdminActions.pl'; load_app Loads a Dancer package. This method sets the libdir to the current ./lib directory: # if we have lib/Webapp.pm, we can load it like: load_app 'Webapp'; # or with options load_app 'Forum', prefix => '/forum', settings => {foo => 'bar'}; Note that the package loaded using load_app must import Dancer with the :syntax option. To load multiple apps repeat load_app: load_app 'one'; load_app 'two'; The old way of loading multiple apps in one go (load_app 'one', 'two';) is deprecated. mime Shortcut to access the instance object of Dancer::MIME. You should read the Dancer::MIME documentation for full details, but the most commonly-used methods are summarized below: # set a new mime type mime->add_type( foo => 'text/foo' ); # set a mime type alias mime->add_alias( f => 'foo' ); # get mime type for an alias my $m = mime->for_name( 'f' ); # get mime type for a file (based on extension) my $m = mime->for_file( "foo.bar" ); # get current defined default mime type my $d = mime->default; # set the default mime type using config.yml # or using the set keyword set default_mime_type => 'text/plain'; params This method should be called from a route handler. It's an alias for the Dancer::Request params accessor. In list context it returns a list of key/value pair of all defined parameters. In scalar context it returns a hash reference instead. Check param below to access quickly to a single parameter value. param This method should be called from a route handler. This method is an accessor to the parameters hash table. post '/login' => sub { my $username = param "user"; my $password = param "pass"; # ... } param_array This method should be called from a route handler. Like param, but always returns the parameter value or values as a list. Returns the number of values in scalar context. # if request is '/tickets?tag=open&tag=closed&order=desc'... get '/tickets' => sub { my @tags = param_array 'tag'; # ( 'open', 'closed' ) my $tags = param 'tag'; # array ref my @order = param_array 'order'; # ( 'desc' ) my $order = param 'order'; # 'desc' }; pass This method should be called from a route handler. Tells Dancer to pass the processing of the request to the next matching route. WARNING : Issuing a pass immediately exits the current route, and performs the pass. Thus, any code after a pass is ignored until the end of the route. So it's not necessary any more to use return with pass. get '/some/route' => sub { if (...) { # we want to let the next matching route handler process this one pass(...); # This code will be ignored do_stuff(); } }; patch Defines a route for HTTP PATCH requests to the given URL: patch '/resource' => sub { ... }; (PATCH is a relatively new and not-yet-common HTTP verb, which is intended to work as a "partial-PUT", transferring just the changes; please see http://tools.ietf.org/html/rfc5789|RFC5789 for further details.) Please be aware that, if you run your app in standalone mode, PATCH requests will not reach your app unless you have a new version of HTTP::Server::Simple which accepts PATCH as a valid verb. The current version at time of writing, 0.44, does not. A pull request has been submitted to add this support, which you can find at: https://github.com/bestpractical/http-server-simple/pull/1 path Concatenates multiple paths together, without worrying about the underlying operating system: my $path = path(dirname($0), 'lib', 'File.pm'); It also normalizes (cleans) the path aesthetically. It does not verify the path exists. post Defines a route for HTTP POST requests to the given URL: post '/' => sub { return "Hello world"; } prefix Defines a prefix for each route handler, like this: prefix '/home'; From here, any route handler is defined to /home/*: get '/page1' => sub {}; # will match '/home/page1' You can unset the prefix value: prefix undef; get '/page1' => sub {}; will match /page1 For a safer alternative you can use lexical prefix like this: prefix '/home' => sub { ## Prefix is set to '/home' here get ...; get ...; }; ## prefix reset to the previous version here This makes it possible to nest prefixes: prefix '/home' => sub { ## some routes prefix '/private' => sub { ## here we are under /home/private... ## some more routes }; ## back to /home }; ## back to the root Notice: once you have a prefix set, do not add a caret to the regex: prefix '/foo'; get qr{^/bar} => sub { ... } # BAD BAD BAD get qr{/bar} => sub { ... } # Good! del Defines a route for HTTP DELETE requests to the given URL: del '/resource' => sub { ... }; options Defines a route for HTTP OPTIONS requests to the given URL: options '/resource' => sub { ... }; put Defines a route for HTTP PUT requests to the given URL: put '/resource' => sub { ... }; redirect Generates an HTTP redirect (302). You can either redirect to a completely different site or within the application: get '/twitter', sub { redirect 'http://twitter.com/me'; }; You can also force Dancer to return a specific 300-ish HTTP response code: get '/old/:resource', sub { redirect '/new/'.params->{resource}, 301; }; It is important to note that issuing a redirect by itself does not exit and redirect immediately. Redirection is deferred until after the current route or filter has been processed. To exit and redirect immediately, use the return function, e.g. get '/restricted', sub { return redirect '/login' if accessDenied(); return 'Welcome to the restricted section'; }; render_with_layout Allows a handler to provide plain HTML (or other content), but have it rendered within the layout still. This method is DEPRECATED, and will be removed soon. Instead, you should be using the engine keyword: get '/foo' => sub { # Do something which generates HTML directly (maybe using # HTML::Table::FromDatabase or something) my $content = ...; # get the template engine my $template_engine = engine 'template'; # apply the layout (not the renderer), and return the result $template_engine->apply_layout($content) }; It works very similarly to template in that you can pass tokens to be used in the layout, and/or options to control the way the layout is rendered. For instance, to use a custom layout: render_with_layout $content, {}, { layout => 'layoutname' }; request Returns a Dancer::Request object representing the current request. See the Dancer::Request documentation for the methods you can call, for example: request->referer; # value of the HTTP referer header request->remote_address; # user's IP address request->user_agent; # User-Agent header value send_error Returns an HTTP error. By default the HTTP code returned is 500: get '/photo/:id' => sub { if (...) { send_error("Not allowed", 403); } else { # return content } } WARNING : Issuing a send_error immediately exits the current route, and perform the send_error. Thus, any code after a send_error is ignored, until the end of the route. So it's not necessary anymore to use return with send_error. get '/some/route' => sub { if (...) { # we want to let the next matching route handler process this one send_error(..); # This code will be ignored do_stuff(); } }; send_file Lets the current route handler send a file to the client. Note that the path of the file must be relative to the public directory unless you use the system_path option (see below). get '/download/:file' => sub { send_file(params->{file}); } WARNING : Issuing a send_file immediately exits the current route, and performs the send_file. Thus, any code after a send_file is ignored until the end of the route. So it's not necessary any more to use return with send_file. get '/some/route' => sub { if (...) { # we want to let the next matching route handler process this one send_file(...); # This code will be ignored do_stuff(); } }; Send file supports streaming possibility using PSGI streaming. The server should support it but normal streaming is supported on most, if not all. get '/download/:file' => sub { send_file( params->{file}, streaming => 1 ); } You can control what happens using callbacks. First, around_content allows you to get the writer object and the chunk of content read, and then decide what to do with each chunk: get '/download/:file' => sub { send_file( params->{file}, streaming => 1, callbacks => { around_content => sub { my ( $writer, $chunk ) = @_; $writer->write("* $chunk"); }, }, ); } You can use around to all get all the content (whether a filehandle if it's a regular file or a full string if it's a scalar ref) and decide what to do with it: get '/download/:file' => sub { send_file( params->{file}, streaming => 1, callbacks => { around => sub { my ( $writer, $content ) = @_; # we know it's a text file, so we'll just stream # line by line while ( my $line = <$content> ) { $writer->write($line); } }, }, ); } Or you could use override to control the entire streaming callback request: get '/download/:file' => sub { send_file( params->{file}, streaming => 1, callbacks => { override => sub { my ( $respond, $response ) = @_; my $writer = $respond->( [ $newstatus, $newheaders ] ); $writer->write("some line"); }, }, ); } You can also set the number of bytes that will be read at a time (default being 42K bytes) using bytes: get '/download/:file' => sub { send_file( params->{file}, streaming => 1, bytes => 524288, # 512K ); }; The content-type will be set depending on the current MIME types definition (see mime if you want to define your own). If your filename does not have an extension, or you need to force a specific mime type, you can pass it to send_file as follows: send_file(params->{file}, content_type => 'image/png'); Also, you can use your aliases or file extension names on content_type, like this: send_file(params->{file}, content_type => 'png'); For files outside your public folder, you can use the system_path switch. Just bear in mind that its use needs caution as it can be dangerous. send_file('/etc/passwd', system_path => 1); If you have your data in a scalar variable, send_file can be useful as well. Pass a reference to that scalar, and send_file will behave as if there were a file with that contents: send_file( \$data, content_type => 'image/png' ); Note that Dancer is unable to guess the content type from the data contents. Therefore you might need to set the content_type properly. For this kind of usage an attribute named filename can be useful. It is used as the Content-Disposition header, to hint the browser about the filename it should use. send_file( \$data, content_type => 'image/png' filename => 'onion.png' ); set Defines a setting: set something => 'value'; You can set more than one value at once: set something => 'value', otherthing => 'othervalue'; setting Returns the value of a given setting: setting('something'); # 'value' set_cookie Creates or updates cookie values: get '/some_action' => sub { set_cookie name => 'value', expires => (time + 3600), domain => '.foo.com'; }; In the example above, only 'name' and 'value' are mandatory. You can also store more complex structure in your cookies: get '/some_auth' => sub { set_cookie oauth => { token => $twitter->request_token, token_secret => $twitter->secret_token, ... }; }; You can't store more complex structure than this. All keys in the HashRef should be Scalars; storing references will not work. See Dancer::Cookie for further options when creating your cookie. Note that this method will be eventually deprecated in favor of the new cookie method. session Provides access to all data stored in the user's session (if any). It can also be used as a setter to store data in the session: # getter example get '/user' => sub { if (session('user')) { return "Hello, ".session('user')->name; } }; # setter example post '/user/login' => sub { ... if ($logged_in) { session user => $user; } ... }; You may also need to clear a session: # destroy session get '/logout' => sub { ... session->destroy; ... }; If you need to fetch the session ID being used for any reason: my $id = session->id; In order to be able to use sessions, first you need to enable session support in one of the configuration files. A quick way to do it is to add session: "YAML" to config.yml. For more details, see Dancer::Session. splat Returns the list of captures made from a route handler with a route pattern which includes wildcards: get '/file/*.*' => sub { my ($file, $extension) = splat; ... }; There is also the extensive splat (A.K.A. "megasplat"), which allows extensive greedier matching, available using two asterisks. The additional path is broken down and returned as an ArrayRef: get '/entry/*/tags/**' => sub { my ( $entry_id, $tags ) = splat; my @tags = @{$tags}; }; This helps with chained actions: get '/team/*/**' => sub { my ($team) = splat; var team => $team; pass; }; prefix '/team/*'; get '/player/*' => sub { my ($player) = splat; # etc... }; get '/score' => sub { return score_for( vars->{'team'} ); }; start Starts the application or the standalone server (depending on the deployment choices). This keyword should be called at the very end of the script, once all routes are defined. At this point, Dancer takes over control. status Changes the status code provided by an action. By default, an action will produce an HTTP 200 OK status code, meaning everything is OK: get '/download/:file' => { if (! -f params->{file}) { status 'not_found'; return "File does not exist, unable to download"; } # serving the file... }; In that example Dancer will notice that the status has changed, and will render the response accordingly. The status keyword receives either a numeric status code or its name in lower case, with underscores as a separator for blanks. See the list in "HTTP CODES" in Dancer::HTTP. template Returns the response of processing the given template with the given parameters (and optional settings), wrapping it in the default or specified layout too, if layouts are in use. An example of a route handler which returns the result of using template to build a response with the current template engine: get '/' => sub { ... return template 'some_view', { token => 'value'}; }; Note that template simply returns the content, so when you use it in a route handler, if execution of the route handler should stop at that point, make sure you use 'return' to ensure your route handler returns the content. Since template just returns the result of rendering the template, you can also use it to perform other templating tasks, e.g. generating emails: post '/some/route' => sub { if (...) { email { to => 'someone@example.com', from => 'foo@example.com', subject => 'Hello there', msg => template('emails/foo', { name => params->{name} }), }; return template 'message_sent'; } else { return template 'error'; } }; Compatibility notice: template was changed in version 1.3090 to immediately interrupt execution of a route handler and return the content, as it's typically used at the end of a route handler to return content. However, this caused issues for some people who were using template to generate emails etc, rather than accessing the template engine directly, so this change has been reverted in 1.3091. The first parameter should be a template available in the views directory, the second one (optional) is a HashRef of tokens to interpolate, and the third (again optional) is a HashRef of options. For example, to disable the layout for a specific request: get '/' => sub { template 'index', {}, { layout => undef }; }; Or to request a specific layout, of course: get '/user' => sub { template 'user', {}, { layout => 'user' }; }; Some tokens are automatically added to your template (perl_version, dancer_version, settings, request, params, vars and, if you have sessions enabled, session). Check Dancer::Template::Abstract for further details. to_dumper ($structure) Serializes a structure with Data::Dumper. to_json ($structure, \%options) Serializes a structure to JSON. Can receive optional arguments. Thoses arguments are valid JSON arguments to change the behaviour of the default JSON::to_json function. Compatibility notice: to_json changed in 1.3002 to take a hashref as options, instead of a hash. to_yaml ($structure) Serializes a structure to YAML. to_xml ($structure, %options) Serializes a structure to XML. Can receive optional arguments. Thoses arguments are valid XML::Simple arguments to change the behaviour of the default XML::Simple::XMLout function. true Constant that returns a true value (1). upload Provides access to file uploads. Any uploaded file is accessible as a Dancer::Request::Upload object. You can access all parsed uploads via: post '/some/route' => sub { my $file = upload('file_input_foo'); # file is a Dancer::Request::Upload object }; If you named multiple inputs of type "file" with the same name, the upload keyword will return an Array of Dancer::Request::Upload objects: post '/some/route' => sub { my ($file1, $file2) = upload('files_input'); # $file1 and $file2 are Dancer::Request::Upload objects }; You can also access the raw HashRef of parsed uploads via the current request object: post '/some/route' => sub { my $all_uploads = request->uploads; # $all_uploads->{'file_input_foo'} is a Dancer::Request::Upload object # $all_uploads->{'files_input'} is an ArrayRef of Dancer::Request::Upload objects }; Note that you can also access the filename of the upload received via the params keyword: post '/some/route' => sub { # params->{'files_input'} is the filename of the file uploaded }; See Dancer::Request::Upload for details about the interface provided. uri_for Returns a fully-qualified URI for the given path: get '/' => sub { redirect uri_for('/path'); # can be something like: http://localhost:3000/path }; Querystring parameters can be provided by passing a hashref as a second param, and URL-encoding can be disabled via a third parameter: uri_for('/path', { foo => 'bar' }, 1); # would return e.g. http://localhost:3000/path?foo=bar captures Returns a reference to a copy of %+, if there are named captures in the route Regexp. Named captures are a feature of Perl 5.10, and are not supported in earlier versions: get qr{ / (? user | ticket | comment ) / (? delete | find ) / (? \d+ ) /?$ }x , sub { my $value_for = captures; "i don't want to $$value_for{action} the $$value_for{object} $$value_for{id} !" }; var Provides an accessor for variables shared between filters and route handlers. Given a key/value pair, it sets a variable: hook before sub { var foo => 42; }; Later, route handlers and other filters will be able to read that variable: get '/path' => sub { my $foo = var 'foo'; ... }; vars Returns the HashRef of all shared variables set during the filter/route chain with the var keyword: get '/path' => sub { if (vars->{foo} eq 42) { ... } }; warning Logs a warning message through the current logger engine: warning "This is a warning"; See Dancer::Logger for details on how to configure where log messages go. AUTHOR This module has been written by Alexis Sukrieh and others, see the AUTHORS file that comes with this distribution for details. SOURCE CODE The source code for this module is hosted on GitHub https://github.com/PerlDancer/Dancer. Feel free to fork the repository and submit pull requests! (See Dancer::Development for details on how to contribute). Also, why not watch the repo to keep up to date with the latest upcoming changes? GETTING HELP / CONTRIBUTING The Dancer development team can be found on #dancer on irc.perl.org: irc://irc.perl.org/dancer If you don't have an IRC client installed/configured, there is a simple web chat client at http://www.perldancer.org/irc for you. There is also a Dancer users mailing list available. Subscribe at: http://lists.preshweb.co.uk/mailman/listinfo/dancer-users If you'd like to contribute to the Dancer project, please see http://www.perldancer.org/contribute for all the ways you can help! DEPENDENCIES The following modules are mandatory (Dancer cannot run without them): HTTP::Server::Simple::PSGI HTTP::Tiny MIME::Types URI The following modules are optional: JSON : needed to use JSON serializer Plack : in order to use PSGI Template : in order to use TT for rendering views XML::Simple and XML:SAX or XML:Parser for XML serialization YAML : needed for configuration file support SEE ALSO Main Dancer web site: http://perldancer.org/. The concept behind this module comes from the Sinatra ruby project, see http://www.sinatrarb.com/ for details. AUTHOR Dancer Core Developers COPYRIGHT AND LICENSE This software is copyright (c) 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. libdancer-perl-1.3513+dfsg.orig/t/0000755000175000017500000000000013614562017016111 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/19_dancer/0000755000175000017500000000000013614562017017656 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/19_dancer/02_script_version_from.t0000644000175000017500000000262713614371230024442 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, 'bin', '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.3513+dfsg.orig/t/19_dancer/01_script.t0000644000175000017500000000243713614371230021650 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,'lib'); $libdir = '"'.$libdir.'"' if $libdir =~ / /; # this is for windows, but works in UNIX systems as well... my $dancer = File::Spec->catfile( $cwd, 'bin', '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.3513+dfsg.orig/t/01_config/0000755000175000017500000000000013614562017017656 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/01_config/yaml_dependency.t0000644000175000017500000000152613614371230023202 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/Could not load YAML: Fish error. Goldfish in YAML./, "Dancer::Config cannot load without YAML"; unmock 'Dancer::ModuleLoader' => method 'load'; SKIP: { skip 'YAML not available', 1 unless Dancer::ModuleLoader->load('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.3513+dfsg.orig/t/01_config/06_stack_trace.t0000644000175000017500000000553513614371230022636 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Template::TemplateToolkit; eval "use Template; 1" or plan skip_all => "tests require module 'Template' to be installed"; plan tests => 18; # scoping for $Carp::Verbose localization { # first of all, test without verbose Exceptions local $Dancer::Exception::Verbose = 0; eval { Dancer::Template::TemplateToolkit->new->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->new->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=HASH\(0x[0-9a-fA-F]+\)['"]?, ['"]/not/a/valid/file['"]\) called at!, "test verbose croak stack trace"; like($error_lines[2], qr!^\s*eval \{...\} called at (?:[.]/)?\Q$0\E!, "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->new->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->new->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=HASH\(0x[0-9a-fA-F]+\)['"]?, ['"]/not/a/valid/file['"]\) called at!, "test verbose croak stack trace"; like($error_lines[2], qr!^\s*eval \{...\} called at (?:[.]/)?\Q$0\E!, "test verbose croak stack trace"); } libdancer-perl-1.3513+dfsg.orig/t/01_config/01_settings.t0000644000175000017500000000213013614371230022172 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.3513+dfsg.orig/t/01_config/environments/0000755000175000017500000000000013614371230022400 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/01_config/environments/development.pl0000644000175000017500000000000313614371230025250 0ustar gregoagregoa1; libdancer-perl-1.3513+dfsg.orig/t/01_config/08_environments.t0000644000175000017500000000310513614371230023073 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::ModuleLoader; plan skip_all => "YAML or YAML::XS needed to run these tests" unless Dancer::ModuleLoader->load('YAML::XS') or Dancer::ModuleLoader->load('YAML'); 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); Dancer::ModuleLoader->load('YAML::XS') and config->{engines}->{YAML}->{module} = 'YAML::XS'; 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.3513+dfsg.orig/t/01_config/04_config_file.t0000644000175000017500000000447413614371230022616 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan skip_all => "YAML or YAML::XS needed to run these tests" unless Dancer::ModuleLoader->load('YAML::XS') or 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'); Dancer::ModuleLoader->load('YAML::XS') and config->{engines}->{YAML}->{module} = 'YAML::XS'; 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.3513+dfsg.orig/t/01_config/06_config_api.t0000644000175000017500000000260113614371230022440 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Config; plan skip_all => "YAML or YAML::XS needed to run these tests" unless Dancer::ModuleLoader->load('YAML::XS') or Dancer::ModuleLoader->load('YAML'); plan skip_all => "File::Temp 0.22 required" unless Dancer::ModuleLoader->load( 'File::Temp', '0.22' ); for my $module (qw(YAML::XS YAML)) { SKIP: { if (!Dancer::ModuleLoader->load($module)) { skip "$module not available", 2; } my $mversion = $module->VERSION; diag "Testing YAML parsing with $module version $mversion"; eval { Dancer::Config::load_settings_from_yaml('foo', $module); }; like $@, qr/Unable to parse the configuration file/, "non-existent YAML file reported correctly, using $module"; 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 '><(((o>'; # fishy-looking YAML close $fh; eval { Dancer::Config::load_settings_from_yaml($config_file, $module); }; like $@, qr/Unable to parse the configuration file/, "invalid YAML file reported correctly, using $module"; File::Temp::cleanup(); } } done_testing(); libdancer-perl-1.3513+dfsg.orig/t/01_config/02_mime_type.t0000644000175000017500000000174013614371230022331 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.3513+dfsg.orig/t/01_config/05_serializers.t0000644000175000017500000000223513614371230022700 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.3513+dfsg.orig/t/01_config/03_logger.t0000644000175000017500000000321613614371230021621 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.3513+dfsg.orig/t/01_config/07_strict_config.t0000644000175000017500000000427613614371230023212 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan skip_all => "YAML or YAML::XS needed to run these tests" unless Dancer::ModuleLoader->load('YAML::XS') or 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; Dancer::ModuleLoader->load('YAML::XS') and config->{engines}->{YAML}->{module} = 'YAML::XS'; # 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.3513+dfsg.orig/t/17_apps/0000755000175000017500000000000013614562017017363 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/17_apps/00_base.t0000644000175000017500000000140713614371230020756 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.3513+dfsg.orig/t/17_apps/05_api.t0000644000175000017500000000063213614371230020621 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.3513+dfsg.orig/t/17_apps/03_prefix.t0000644000175000017500000000175313614371230021350 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.3513+dfsg.orig/t/17_apps/01_settings.t0000644000175000017500000000232213614371230021702 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.3513+dfsg.orig/t/17_apps/000_create_fake_env.t0000644000175000017500000000052413614371230023224 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.3513+dfsg.orig/t/17_apps/02_load_app.t0000644000175000017500000000206513614371230021626 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"; for ( { name => "main", routes => 1 }, { name => "TestApp", routes => 20 }, { name => "Forum", routes => 5 }, ) { my $app = Dancer::App->get($_->{name}); ok( defined($app) , "app $_->{name} is defined", ); is( @{ $app->registry->routes('get') }, $_->{routes}, "Expected number of get routes defined for " . $_->{name}, ); } 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.3513+dfsg.orig/t/12_response/0000755000175000017500000000000013614562017020251 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/12_response/10_error_dumper_without_clone.t0000644000175000017500000000116113614371230026400 0ustar gregoagregoause strict; use warnings; BEGIN { use Test::More; plan skip_all => 'Devel::Hide required' unless eval 'use Devel::Hide; 1'; } use Devel::Hide 'Clone'; plan tests => 3; { package MyApp; use Dancer; my $data = { deep => { secret => 'akadabra' } }; get '/dump' => sub { Dancer::Error::dumper( $data ) }; get '/straight' => sub { $data->{deep}{secret} }; } use Dancer::Test; response_content_is '/straight' => 'akadabra', 'secret visible'; response_content_like '/dump' => qr/secret.*Hidden/, 'masked by dumper()'; response_content_is '/straight' => 'akadabra', '...but not modified'; libdancer-perl-1.3513+dfsg.orig/t/12_response/05_api.t0000644000175000017500000000123413614371230021506 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.3513+dfsg.orig/t/12_response/06_filter_halt_status.t0000644000175000017500000000170313614371230024637 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.3513+dfsg.orig/t/12_response/03_charset.t0000644000175000017500000000500513614371230022364 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.3513+dfsg.orig/t/12_response/09_headers_to_array.t0000644000175000017500000000163713614371230024263 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.3513+dfsg.orig/t/12_response/02_headers.t0000644000175000017500000000423413614371230022350 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.3513+dfsg.orig/t/12_response/07_cookies.t0000644000175000017500000000150513614371230022374 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.3513+dfsg.orig/t/12_response/000_create_fake_env.t0000644000175000017500000000052413614371230024112 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.3513+dfsg.orig/t/12_response/01_CRLF_injection.t0000644000175000017500000000136413614371230023525 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.3513+dfsg.orig/t/12_response/11_CVE-2012-5572.t0000644000175000017500000000145513614371230022336 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.3513+dfsg.orig/t/12_response/08_drop_content.t0000644000175000017500000000231213614371230023434 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; for (qw/204 304/) { my $res = $ua->get($url . $_); ok !$res->{content}, 'no content for '.$_; ok !$res->{headers}{'content-length'}, 'no content-length for '.$_; } }, server => sub { my $port = shift; set port => $port, server => '127.0.0.1', startup_info => 0; get '/204' => sub { status 204; return 'foo' }; get '/304' => sub { status 304; return 'foo' }; Dancer->dance(); }, ); } libdancer-perl-1.3513+dfsg.orig/t/12_response/04_charset_server.t0000644000175000017500000000662513614371230023764 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 ); use HTTP::Tiny::NoProxy; plan tests => 10; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = HTTP::Tiny::NoProxy->new; my $res = $ua->post_form("http://127.0.0.1:$port/name", [ name => 'vasya' ]); my $headers = HTTP::Headers->new(%{$res->{headers}}); is $headers->content_type, 'text/html'; ok $headers->content_type_charset; # we always have charset if the setting is set is $res->{content}, 'Your name: vasya'; $res = $ua->get("http://127.0.0.1:$port/unicode"); $headers = HTTP::Headers->new(%{$res->{headers}}); is $headers->content_type, 'text/html'; is $headers->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, server => '127.0.0.1', startup_info => 0 ); Dancer->dance(); }, ); Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = HTTP::Tiny::NoProxy->new; my $res = $ua->get("http://127.0.0.1:$port/unicode-content-length"); my $headers = HTTP::Headers->new(%{$res->{headers}}); is $headers->content_type, 'text/html'; # UTF-8 seems to be Dancer's default encoding my $v = "\x{100}0123456789"; utf8::encode($v); is $res->{content}, $v; }, server => sub { my $port = shift; use lib "t/lib"; use TestAppUnicode; Dancer::Config->load; set( # no charset environment => 'production', port => $port, server => '127.0.0.1', startup_info => 0, ); Dancer->dance; }, ); SKIP: { skip "JSON module required for test", 2 unless Dancer::ModuleLoader->load('JSON'); Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = HTTP::Tiny::NoProxy->new; my $res = $ua->get("http://127.0.0.1:$port/unicode-content-length-json"); my $headers = HTTP::Headers->new(%{$res->{headers}}); is $headers->content_type, 'application/json'; is_deeply(from_json($res->{content}), { test => "\x{100}" }); }, server => sub { my $port = shift; use lib "t/lib"; use TestAppUnicode; Dancer::Config->load; set( # no charset environment => 'production', port => $port, server => '127.0.0.1', startup_info => 0, serializer => 'JSON', ); Dancer->dance; }, ); } libdancer-perl-1.3513+dfsg.orig/t/12_response/10_error_dumper.t0000644000175000017500000000146213614371230023441 0ustar gregoagregoause strict; use warnings; use Test::More; use Dancer::Error; use Dancer::ModuleLoader; plan tests => 5; my $error_obj = Dancer::Error->new( code => '404', pass => 'secret', deep => { pass => 'secret' }, ); isa_ok( $error_obj, 'Dancer::Error' ); my $censored = $error_obj->dumper; like( $censored, qr/\QNote: Values of 2 sensitive-looking keys hidden\E/, 'Data was censored in the output', ); is( $error_obj->{'pass'}, 'secret', 'Original data was not overwritten', ); is( $error_obj->{'deep'}{'pass'}, 'secret', 'Censoring of complex data structures works fine', ); 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.3513+dfsg.orig/t/release-distmeta.t0000644000175000017500000000040113614371230021514 0ustar gregoagregoa#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { print qq{1..0 # SKIP these tests are for release candidate testing\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::MetaTests. use Test::CPAN::Meta; meta_yaml_ok(); libdancer-perl-1.3513+dfsg.orig/t/25_exceptions/0000755000175000017500000000000013614562017020600 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/25_exceptions/views/0000755000175000017500000000000013614562017021735 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/25_exceptions/views/index.tt0000644000175000017500000000002113614371230023401 0ustar gregoagregoafoo => <% foo %> libdancer-perl-1.3513+dfsg.orig/t/25_exceptions/views/layouts/0000755000175000017500000000000013614371230023430 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/25_exceptions/views/layouts/main.tt0000644000175000017500000000004313614371230024722 0ustar gregoagregoastart <% time %> <% content %>stop libdancer-perl-1.3513+dfsg.orig/t/25_exceptions/views/error.tt0000644000175000017500000000010513614371230023426 0ustar gregoagregoaTITLE: <% title %> MESSAGE: <% message %> EXCEPTION: <% exception %> libdancer-perl-1.3513+dfsg.orig/t/25_exceptions/02_exceptions.t0000644000175000017500000000707313614371230023451 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.3513+dfsg.orig/t/25_exceptions/03_exceptions.t0000644000175000017500000000176113614371230023450 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.3513+dfsg.orig/t/25_exceptions/04_exceptions_warn.t0000644000175000017500000000240213614371230024471 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.3513+dfsg.orig/t/25_exceptions/01_exceptions.t0000644000175000017500000000735013614371230023446 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.3513+dfsg.orig/t/06_helpers/0000755000175000017500000000000013614562017020060 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/06_helpers/05_send_error.t0000644000175000017500000000063113614371230022706 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.3513+dfsg.orig/t/06_helpers/public/0000755000175000017500000000000013614371230021331 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/06_helpers/public/file.txt0000644000175000017500000000000613614371230023005 0ustar gregoagregoa1 2 3 libdancer-perl-1.3513+dfsg.orig/t/06_helpers/routes.pl0000644000175000017500000000004513614371230021730 0ustar gregoagregoaget '/foo' => sub { 'foo loaded' }; libdancer-perl-1.3513+dfsg.orig/t/06_helpers/000_create_fake_env.t0000644000175000017500000000052413614371230023721 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.3513+dfsg.orig/t/06_helpers/02_http_status.t0000644000175000017500000000216713614371230023131 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.3513+dfsg.orig/t/06_helpers/01_send_file.t0000644000175000017500000001122013614371230022464 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.3513+dfsg.orig/t/06_helpers/03_content_type.t0000644000175000017500000000141013614371230023251 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.3513+dfsg.orig/t/06_helpers/06_load.t0000644000175000017500000000043613614371230021467 0ustar gregoagregoause Test::More 'no_plan', import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; use FindBin qw($Bin); use lib "$Bin/../../"; 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.3513+dfsg.orig/t/06_helpers/04_status.t0000644000175000017500000000072613614371230022073 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.3513+dfsg.orig/t/14_serializer/0000755000175000017500000000000013614562017020566 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/14_serializer/01_helpers.t0000644000175000017500000001412113614371230022707 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.3513+dfsg.orig/t/14_serializer/07_request_jsonp.t0000644000175000017500000000103313614371230024152 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 => 2; } set 'serializer' => 'JSONP', 'show_errors' => 1; get '/' => sub { { foo => 'bar' } }; my $res = dancer_response( GET => '/' , { params => { callback => 'func' } } ); is $res->header('Content-Type'), 'application/javascript'; like $res->content, qr/func\( \s* \{ \s* "foo" \s* : \s* "bar" \s* \} \s* \); /mix; libdancer-perl-1.3513+dfsg.orig/t/14_serializer/06_api.t0000644000175000017500000000740213614371230022027 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 => 18; 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: { Dancer::ModuleLoader->load($_) or skip "$_ is needed to run this test", 5 for qw/ JSON YAML /; set serializer => 'Mutable'; my $s = Dancer::Serializer->engine; my $tmpdir = File::Spec->tmpdir; %ENV = ( 'REQUEST_METHOD' => 'GET', 'HTTP_CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'text/xml', 'HTTP_ACCEPT_TYPE' => 'text/x-yaml', 'PATH_INFO' => '/', 'TMPDIR' => $tmpdir, ); my $req = Dancer::Request->new( env => \%ENV ); Dancer::SharedData->request($req); my $ct = Dancer::Serializer::Mutable::_request_content_types($req); is_deeply $ct, [ 'application/json' ]; $ct = Dancer::Serializer::Mutable::_response_content_types($req); is_deeply $ct, [ 'text/xml', 'text/x-yaml', 'application/json' ]; %ENV = ( 'REQUEST_METHOD' => 'PUT', 'PATH_INFO' => '/', 'TMPDIR' => $tmpdir, ); $req = Dancer::Request->new( env => \%ENV ); Dancer::SharedData->request($req); $ct = Dancer::Serializer::Mutable::_request_content_types($req); is_deeply $ct, ['application/json']; $ct = Dancer::Serializer::Mutable::_response_content_types($req); is_deeply $ct, ['application/json']; %ENV = ( 'REQUEST_METHOD' => 'PUT', 'PATH_INFO' => '/', 'HTTP_ACCEPT' => 'text/xml', 'CONTENT_TYPE' => 'application/json', 'TMPDIR' => $tmpdir, ); $req = Dancer::Request->new( env => \%ENV ); Dancer::SharedData->request($req); $ct = Dancer::Serializer::Mutable::_response_content_types($req); is_deeply $ct, [ 'text/xml', 'application/json' ]; } # 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.3513+dfsg.orig/t/14_serializer/17_clear_serializer.t0000644000175000017500000000275213614371230024602 0ustar gregoagregoause Dancer ':tests'; use Dancer::Test; use Test::More; use Dancer::ModuleLoader; use HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; my $res; $res = $ua->get("http://127.0.0.1:$port/"); ok( $res->{success}, 'Successful response from server' ); like( $res->{content}, qr/"foo" \s \: \s "bar"/x, 'Correct content', ); # new request, no serializer $res = $ua->get("http://127.0.0.1:$port/"); ok( $res->{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, server => '127.0.0.1', show_errors => 1, startup_info => 0 ); get '/' => sub { $data }; hook after => sub { set serializer => undef }; Dancer->dance(); }, ); libdancer-perl-1.3513+dfsg.orig/t/14_serializer/05_request_mutable.t0000644000175000017500000000537413614371230024464 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Test; BEGIN { plan skip_all => 'YAML or YAML::XS is needed to run this test' unless Dancer::ModuleLoader->load('YAML::XS') or Dancer::ModuleLoader->load('YAML'); plan skip_all => 'JSON is needed to run this test' unless Dancer::ModuleLoader->load('JSON'); } plan tests => 10; Dancer::ModuleLoader->load('YAML::XS') and config->{engines}->{YAML}->{module} = 'YAML::XS'; setting serializer => 'mutable'; get '/' => sub { { foo => 1 } }; post '/' => sub { request->params }; post '/echo' => sub { 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' => 'text/x-yaml' ] } ); is_deeply(from_yaml($res->content), {foo => 42}); is $res->header('Content-Type'), 'text/x-yaml'; # Make sure to grok correct (de)serializer for body params # when the Content-Type is as supported media type with additional # parameters. my $data = { bar => 4711 }; $res = dancer_response( POST => '/echo', { body => to_yaml($data), # make sure to stringify # Specifying this content_type is redundant but dancer_response # has a bug in that it does not take the Content-Type of the # headers before falling back to # application/x-www-form-urlencoded :( content_type => 'text/x-yaml; charset=utf-8', headers => [ 'Content-Type' => 'text/x-yaml; charset=utf-8', ] } ); is_deeply( from_yaml( $res->content ), $data ); is $res->header('Content-Type'), 'text/x-yaml; charset=utf-8'; # We were incorrectly using 'Content-Type' also for responses although # the user told us in 'Accept' to use a different format. $res = dancer_response( POST => '/echo', { body => to_json($data), # make sure to stringify # Specifying this content_type is redundant but dancer_response # has a bug in that it does not take the Content-Type of the # headers before falling back to # application/x-www-form-urlencoded :( content_type => 'application/json; charset=utf-8', headers => [ 'Content-Type' => 'application/json; charset=utf-8', 'Accept' => 'text/x-yaml; charset=utf-8', ] } ); is_deeply( from_yaml( $res->content ), $data ); is $res->header('Content-Type'), 'text/x-yaml; charset=utf-8'; libdancer-perl-1.3513+dfsg.orig/t/14_serializer/99_bugs.t0000644000175000017500000000603713614371230022235 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.3513+dfsg.orig/t/14_serializer/04_request_xml.t0000644000175000017500000000320213614371230023616 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.3513+dfsg.orig/t/14_serializer/03_request_yaml.t0000644000175000017500000000322013614371230023757 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':tests'; use Dancer::Test; plan tests => 10; SKIP: { if ( Dancer::ModuleLoader->load('YAML::XS') ) { config->{engines}->{YAML}->{module} = 'YAML::XS'; set serializer => 'YAML', show_errors => 1; } elsif ( Dancer::ModuleLoader->load('YAML') ) { set serializer => 'YAML', show_errors => 1; } else { skip 'YAML::XS or YAML is needed to run this test', 10; } 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.3513+dfsg.orig/t/14_serializer/18_mutable_template_or_serialize.t0000644000175000017500000000121713614371230027352 0ustar gregoagregoause strict; use warnings; use Test::More; plan skip_all => "need JSON" unless Dancer::ModuleLoader->load('JSON'); plan tests => 2; use Dancer ':tests'; use Dancer::Test; use Dancer::Serializer::Mutable qw/ template_or_serialize /; set serializer => 'Mutable'; no warnings 'redefine'; sub Dancer::template { return $_[0]; } get '/' => sub { template_or_serialize 'index', { a => 1 }; }; my $resp = dancer_response GET => '/'; like $resp->content => qr/"a"\s*:\s*1/, "serialized to JSON"; $resp = dancer_response GET => '/', { params => { content_type => 'text/html' } }; is $resp->content => 'index', 'use the template'; libdancer-perl-1.3513+dfsg.orig/t/14_serializer/02_request_json.t0000644000175000017500000000320213614371230023765 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.3513+dfsg.orig/t/05_views/0000755000175000017500000000000013614562017017552 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/05_views/views/0000755000175000017500000000000013614562017020707 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/05_views/views/index.tt0000644000175000017500000000005713614371230022364 0ustar gregoagregoain view index.tt: number="<% params.number %>" libdancer-perl-1.3513+dfsg.orig/t/05_views/views/vars.tt0000644000175000017500000000001713614371230022224 0ustar gregoagregoa<% vars.foo %> libdancer-perl-1.3513+dfsg.orig/t/05_views/views/layouts/0000755000175000017500000000000013614562017022407 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/05_views/views/layouts/main.tt0000644000175000017500000000003013614371230023670 0ustar gregoagregoastart <% content %>stop libdancer-perl-1.3513+dfsg.orig/t/05_views/views/layouts/custom.tt0000644000175000017500000000004413614371230024263 0ustar gregoagregoacustomstart <% content %>customstop libdancer-perl-1.3513+dfsg.orig/t/05_views/views/t03.tt0000644000175000017500000000000513614371230021654 0ustar gregoagregoaview libdancer-perl-1.3513+dfsg.orig/t/05_views/views/clock.tt0000644000175000017500000000001313614371230022340 0ustar gregoagregoa<% time %> libdancer-perl-1.3513+dfsg.orig/t/05_views/views/request.tt0000644000175000017500000000003013614371230022734 0ustar gregoagregoa<% request.path_info %> libdancer-perl-1.3513+dfsg.orig/t/05_views/03_layout.t0000644000175000017500000000524613614371230021560 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.3513+dfsg.orig/t/05_views/002_view_rendering.t0000644000175000017500000000250513614371230023324 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.3513+dfsg.orig/t/pod.t0000644000175000017500000000052413614371230017054 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.3513+dfsg.orig/t/10_template/0000755000175000017500000000000013614562017020224 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/10_template/views/0000755000175000017500000000000013614562017021361 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/10_template/views/index.tt0000644000175000017500000000002113614371230023025 0ustar gregoagregoafoo => <% foo %> libdancer-perl-1.3513+dfsg.orig/t/10_template/views/layouts/0000755000175000017500000000000013614371230023054 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/10_template/views/layouts/main.tt0000644000175000017500000000004613614371230024351 0ustar gregoagregoalayout:<%foo%> content:<% content %> libdancer-perl-1.3513+dfsg.orig/t/10_template/views/layouts/main.ts0000644000175000017500000000004613614371230024350 0ustar gregoagregoalayout:<%foo%> content:<% content %> libdancer-perl-1.3513+dfsg.orig/t/10_template/views/index.ts0000644000175000017500000000002113614371230023024 0ustar gregoagregoabar => <% bar %> libdancer-perl-1.3513+dfsg.orig/t/10_template/template.t0000644000175000017500000000066113614371230022222 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.3513+dfsg.orig/t/10_template/extension.t0000644000175000017500000000115313614371230022420 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.3513+dfsg.orig/t/10_template/05_template_toolkit.t0000644000175000017500000000714213614371230024274 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 => 17; 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"; $engine->set_wrapper(outer => \'>'); $result = $engine->render(\$template, { one => 1, two => 2, three => 3}); is $result, '', "processed a template given as a scalar ref with outer wrapper"; $engine->set_wrapper(inner => \'--<% content %>--'); $result = $engine->render(\$template, { one => 1, two => 2, three => 3}); is $result, '', "processed a template given as a scalar ref with outer and inner wrapper"; $engine->set_wrapper(\'-#-<% content %>-#-'); $result = $engine->render(\$template, { one => 1, two => 2, three => 3}); is $result, '-#-'.$expected.'-#-', "processed a template given as a scalar ref with single wrapper"; $engine->reset_wrapper; $result = $engine->render(\$template, { one => 1, two => 2, three => 3}); is $result, '', "processed a template given as a scalar ref with resetted wrapper"; is ${$engine->unset_wrapper('outer')}, '>', 'unset outer wrapper'; $result = $engine->render(\$template, { one => 1, two => 2, three => 3}); is $result, '--'.$expected.'--', "processed a template given as a scalar ref with inner wrapper"; is ${$engine->unset_wrapper('inner')}, '--<% content %>--', 'unset inner wrapper'; $result = $engine->render(\$template, { one => 1, two => 2, three => 3}); is $result, $expected, "processed a template given as a scalar ref with no wrapper"; eval { $engine->set_wrapper(nonsense => 'nothing') }; is $@, "core - template - 'nonsense' isn't a valid identifier", 'wrong identifier for set_wrapper'; eval { $engine->unset_wrapper('nonsense') }; is $@, "core - template - 'nonsense' isn't a valid identifier", 'wrong identifier for unset_wrapper'; libdancer-perl-1.3513+dfsg.orig/t/10_template/05_template_toolkit_fromdata.t0000644000175000017500000000053313614371230026146 0ustar gregoagregoause strict; use warnings; use lib 't/lib'; use Test::More; BEGIN { plan skip_all => 'module Template::Provider::FromDATA required' unless eval "use Template::Provider::FromDATA; 1"; } use FromDataApp; use Dancer::Test; plan tests => 1; response_content_like '/' => qr/Hello embedded world!/, 'embedded template work'; libdancer-perl-1.3513+dfsg.orig/t/10_template/02_abstract_class.t0000644000175000017500000000075413614371230023703 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.3513+dfsg.orig/t/10_template/000_create_fake_env.t0000644000175000017500000000052413614371230024065 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.3513+dfsg.orig/t/10_template/index.txt0000644000175000017500000000015713614371230022072 0ustar gregoagregoathis is var1="<% var1 %>" and var2=<% var2 %> another line <% foo%> <%bar %> <%baz%> <% var1 %>/<% var1 %> libdancer-perl-1.3513+dfsg.orig/t/10_template/03_simple.t0000644000175000017500000000523313614371230022202 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.3513+dfsg.orig/t/10_template/01_factory.t0000644000175000017500000000137013614371230022354 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.3513+dfsg.orig/t/07_apphandlers/0000755000175000017500000000000013614562017020720 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/07_apphandlers/02_apache2_plack.t0000644000175000017500000000607713614371230024070 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.3513+dfsg.orig/t/07_apphandlers/01_base.t0000644000175000017500000000160613614371230022315 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.3513+dfsg.orig/t/07_apphandlers/05_psgi_api.t0000644000175000017500000000200313614371230023172 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.3513+dfsg.orig/t/07_apphandlers/04_standalone_app.t0000644000175000017500000000330313614371230024372 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 HTTP::Tiny::NoProxy; plan tests => 6; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = HTTP::Tiny::NoProxy->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_form("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, server => '127.0.0.1', startup_info => 0 ); Dancer->dance(); }, ); libdancer-perl-1.3513+dfsg.orig/t/07_apphandlers/000_create_fake_env.t0000644000175000017500000000052413614371230024561 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.3513+dfsg.orig/t/07_apphandlers/07_middleware_map.t0000644000175000017500000000321213614371230024356 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; use HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; foreach my $test (@tests) { my $res = $ua->get("http://127.0.0.1:$port" . $test->{path}); ok $res; if ( $test->{runtime} ) { ok $res->{headers}{'x-runtime'}; } else { ok !$res->{headers}{'x-runtime'}; } } }, server => sub { my $port = shift; use TestApp; Dancer::Config->load; set( environment => 'production', apphandler => 'PSGI', port => $port, server => '127.0.0.1', startup_info => 0, plack_middlewares_map => $confs ); my $app = Dancer::Handler->get_handler()->dance; Plack::Loader->auto( port => $port, server => '127.0.0.1' )->run($app); }, ); libdancer-perl-1.3513+dfsg.orig/t/07_apphandlers/05_middlewares.t0000644000175000017500000000267513614371230023716 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use Dancer::ModuleLoader; use HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; my $res = $ua->get("http://127.0.0.1:$port/"); ok $res; ok $res->{headers}{'x-runtime'}; }, server => sub { my $port = shift; use TestApp; Dancer::Config->load; set( environment => 'production', apphandler => 'PSGI', port => $port, server => '127.0.0.1', startup_info => 0, plack_middlewares => $c->[0] ); my $app = Dancer::Handler->get_handler()->dance; Plack::Loader->auto( port => $port, server => '127.0.0.1' )->run($app); }, ); } libdancer-perl-1.3513+dfsg.orig/t/07_apphandlers/03_psgi_app.t0000644000175000017500000000265213614371230023211 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 HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->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, server => '127.0.0.1')->run($app); }, ); libdancer-perl-1.3513+dfsg.orig/t/07_apphandlers/06_debug.t0000644000175000017500000000177313614371230022503 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 => 4; use Dancer; set startup_info => false, apphandler => 'Debug'; get '/' => sub { 42 }; get '/env' => sub { request->env->{HTTP_X_REQUESTED_WITH} }; 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"; subtest "env variables" => sub { plan tests => 2; @ARGV = (GET => '/env', 'foo=42', 'HTTP_X_REQUESTED_WITH=XMLHttpRequest'); Test::Output::stdout_like ( sub { $psgi = Dancer->start }, qr{X-Powered-By: Perl Dancer.*XMLHttpRequest}sm, "output looks good" ); is $psgi->[0], 200, "psgi response is ok"; }; libdancer-perl-1.3513+dfsg.orig/t/07_apphandlers/08_is_text.t0000644000175000017500000000051213614371230023064 0ustar gregoagregoause strict; use warnings; use Test::More tests => 5; use Dancer::Handler; for ( 'text/xml', 'text/html', 'text/javascript', 'text/json' ) { ok Dancer::Handler::_is_text($_), $_; } # see issue #994 for ( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) { ok !Dancer::Handler::_is_text($_), $_; } libdancer-perl-1.3513+dfsg.orig/t/08_session/0000755000175000017500000000000013614562017020103 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/08_session/04_api.t0000644000175000017500000000204513614371230021340 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.3513+dfsg.orig/t/08_session/08_simple.t0000644000175000017500000000135113614371230022063 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.3513+dfsg.orig/t/08_session/01_load.t0000644000175000017500000000007713614371230021506 0ustar gregoagregoause Test::More tests => 1; BEGIN { use_ok 'Dancer::Session' } libdancer-perl-1.3513+dfsg.orig/t/08_session/06_abstract.t0000644000175000017500000000161313614371230022374 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.3513+dfsg.orig/t/08_session/09_session.t0000644000175000017500000000113313614371230022254 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer::Session; use Dancer::Cookies; plan tests => 6; my $session = Dancer::Session->init('Simple', {}); ok $session; is_deeply($session, Dancer::Session->engine); my $desc = Dancer::Session->get_current_session; ok $desc; ok( Dancer::Cookies->cookies->{'dancer.session'} ); # remove this delete Dancer::Cookies->cookies->{'dancer.session'}; # after this no cookie should get set ok( Dancer::Session->get_current_session( no_update => 1 ) ); # no session cookie for you! ok !exists Dancer::Cookies->cookies->{'dancer.session'}; libdancer-perl-1.3513+dfsg.orig/t/08_session/14_session_domain.t0000644000175000017500000000134713614371230023606 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.3513+dfsg.orig/t/08_session/000_create_fake_env.t0000644000175000017500000000052413614371230023744 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.3513+dfsg.orig/t/08_session/13_session_httponly.t0000644000175000017500000000376113614371230024221 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 HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; my $res = $ua->get("http://127.0.0.1:$port/set_session/test_13"); ok $res->{success}, 'req is success'; my $cookie = $res->{headers}{'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, server => '127.0.0.1', startup_info => 0 ); Dancer->dance(); }, ); } # clean up after ourselves rmtree($session_dir); libdancer-perl-1.3513+dfsg.orig/t/08_session/12_session_name.t0000644000175000017500000000261313614371230023252 0ustar gregoagregoa#!/usr/bin/env perl use strict; use warnings; use Test::More tests => 8; 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"; } { package Dancer::Session::TestOverrideName; use base 'Dancer::Session::Abstract'; sub session_name { "dr_seuss"; } } subtest 'session name overridable' => sub { plan tests => 2; # make sure that session code overrides session_name via object # instead of configuration, see GH#1004 # my $session = Dancer::Session::TestOverrideName->new; is $session->session_name, "dr_seuss", "session_name in driver"; $session->write_session_id(613); ok( Dancer::Cookies->cookies->{'dr_seuss'}, 'session name is used' ); } libdancer-perl-1.3513+dfsg.orig/t/08_session/10_filter.t0000644000175000017500000000061713614371230022054 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.3513+dfsg.orig/t/08_session/03_http_requests.t0000644000175000017500000001047013614371230023501 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 HTTP::Tiny::NoProxy; use HTTP::CookieJar; 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(Simple YAML); if ($ENV{DANCER_TEST_COOKIE}) { push @engines, "cookie"; setting(session_cookie_key => "secret/foo*@!"); } # Support testing with Dancer::Session::DBI if explictly told to by being # provided with DB connection details via env vars (the appropriate table would # have to have been created, too) if ($ENV{DANCER_TEST_SESSION_DBI_DSN}) { push @engines, "DBI"; setting( session_options => { dsn => $ENV{DANCER_TEST_SESSION_DBI_DSN}, user => $ENV{DANCER_TEST_SESSION_DBI_USER}, password => $ENV{DANCER_TEST_SESSION_DBI_PASS}, table => $ENV{DANCER_TEST_SESSION_DBI_TABLE}, } ); } plan tests => 11 * 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 = HTTP::Tiny::NoProxy->new(cookie_jar => HTTP::CookieJar->new); 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->{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"; $res = $ua->get("http://127.0.0.1:$port/session/after_hook/read"); ok($res->{success}, "Reading a session var in after hook worked"); is( $res->{content}, "Read value set in route", "Session var read in after hook and returned", ); $res = $ua->get("http://127.0.0.1:$port/session/after_hook/write"); ok($res->{success}, "writing a session var in after hook worked"); is( $res->{content}, "Read value changed in hook", "Session var set changed in hook successfully", ); # Now read once more, to make sure that the session var set in the # after hook in the last test was actually persisted: $res = $ua->get("http://127.0.0.1:$port/session/after_hook"); ok($res->{success}, "Fetched the session var"); is( $res->{content}, "value changed in hook", "Session var set in hook persisted", ); $res = $ua->get("http://127.0.0.1:$port/session/after_hook/send_file"); ok( $res->{success}, "after hook accessing session after send_file doesn't explode" . " (GH #1205)", ); is( $res->{content}, "Hi there, random person (after hook fired)", "send_file route sent expected content and no explosion", ); } }, 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"); setting(log => "debug"); setting(logger => "console"); set( show_errors => 1, startup_info => 0, environment => 'production', port => $port, server => '127.0.0.1' ); Dancer->dance(); }, ); } libdancer-perl-1.3513+dfsg.orig/t/08_session/02_dependency_check.t0000644000175000017500000000341113614371230024036 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 7; use Dancer ':syntax'; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; use Dancer::Session::YAML; { # 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"; # Test we can unmock stuff, too. mock 'Dancer::Session::YAML' => method 'yaml_file' => should sub { 'really big shoe' }; is( Dancer::Session::YAML::yaml_file(42), 'really big shoe', "Mocked a method successfully..." ); unmock 'Dancer::Session::YAML' => method 'yaml_file'; like( Dancer::Session::YAML::yaml_file(42), qr/42.yml/, "Unmocked method, original method works again", ); libdancer-perl-1.3513+dfsg.orig/t/08_session/11_session_secure.t0000644000175000017500000000124113614371230023613 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.3513+dfsg.orig/t/08_session/05_yaml.t0000644000175000017500000000352313614371230021534 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 = Dancer::Session::YAML::yaml_file($session->id); 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.3513+dfsg.orig/t/08_session/07_session_expires.t0000644000175000017500000000416713614371230024023 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 HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; my $res = $ua->get("http://127.0.0.1:$port/set_session/test"); ok $res->{success}, 'req is success'; my $cookie = $res->{headers}{'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, server => '127.0.0.1', startup_info => 0 ); Dancer->dance(); }, ); } # clean up after ourselves rmtree($session_dir); libdancer-perl-1.3513+dfsg.orig/t/22_hooks/0000755000175000017500000000000013614562017017537 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/22_hooks/05_layout.t0000644000175000017500000000120413614371230021535 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.3513+dfsg.orig/t/22_hooks/views/0000755000175000017500000000000013614562017020674 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/22_hooks/views/index.tt0000644000175000017500000000002113614371230022340 0ustar gregoagregoafoo => <% foo %> libdancer-perl-1.3513+dfsg.orig/t/22_hooks/views/layouts/0000755000175000017500000000000013614371230022367 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/22_hooks/views/layouts/main.tt0000644000175000017500000000004313614371230023661 0ustar gregoagregoastart <% time %> <% content %>stop libdancer-perl-1.3513+dfsg.orig/t/22_hooks/11_error_in_hook.t0000644000175000017500000000237713614371230023070 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.3513+dfsg.orig/t/22_hooks/10_error_in_hook.t0000644000175000017500000000067713614371230023070 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.3513+dfsg.orig/t/22_hooks/09_before_error_init.t0000644000175000017500000000067213614371230023732 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.3513+dfsg.orig/t/22_hooks/02_before.t0000644000175000017500000000300113614371230021454 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.3513+dfsg.orig/t/22_hooks/07_file.t0000644000175000017500000000173413614371230021151 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.3513+dfsg.orig/t/22_hooks/04_template.t0000644000175000017500000000150313614371230022034 0ustar gregoagregoause strict; use warnings; use Test::More tests => 6, import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; my @events; ok( hook before_template => sub { my $tokens = shift; $tokens->{foo} = 'bar'; push @events, 'before_template_hook'; } ); ok( hook after_template_render => sub { my $full_content = shift; like $$full_content, qr/foo => bar/; push @events, 'after_template_hook'; } ); setting views => path( 't', '22_hooks', 'views' ); get '/' => sub { push @events, 'route_handler'; template 'index', { foo => 'baz' }; }; route_exists [ GET => '/' ]; response_content_like( [ GET => '/' ], qr/foo => bar/ ); is_deeply( \@events, [ qw( route_handler before_template_hook after_template_hook ) ], "Hooks triggered as we expected", ); libdancer-perl-1.3513+dfsg.orig/t/22_hooks/01_api.t0000644000175000017500000000227413614371230020775 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.3513+dfsg.orig/t/22_hooks/06_serializer.t0000644000175000017500000000330013614371230022371 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.3513+dfsg.orig/t/22_hooks/00_syntax.t0000644000175000017500000000105613614371230021546 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.3513+dfsg.orig/t/22_hooks/08_error.t0000644000175000017500000000076713614371230021371 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.3513+dfsg.orig/t/22_hooks/03_after.t0000644000175000017500000000065013614371230021323 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.3513+dfsg.orig/t/21_dependents/0000755000175000017500000000000013614371230020537 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/21_dependents/Dancer-Session-Cookie.t0000755000175000017500000000421413614371230024754 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' ); diag "Loaded Dancer::Session::Cookie version " . $Dancer::Session::Cookie::VERSION; 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 tests=> 7; test_tcp( client => sub { my $port = shift; require HTTP::Tiny::NoProxy; require HTTP::CookieJar; my $ua = HTTP::Tiny::NoProxy->new; # Simulate two different browsers with two different jars my @jars = (HTTP::CookieJar->new, HTTP::CookieJar->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, server => '127.0.0.1', 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.3513+dfsg.orig/t/13_engines/0000755000175000017500000000000013614562017020044 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/13_engines/02_template_init.t0000644000175000017500000000112213614371230023357 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.3513+dfsg.orig/t/13_engines/00_load.t0000644000175000017500000000020613614371230021440 0ustar gregoagregoause Test::More tests => 3; use_ok 'Dancer::Engine'; eval { Dancer::Engine->build(); }; ok $@; like $@, qr/cannot build engine/; libdancer-perl-1.3513+dfsg.orig/t/09_cookies/0000755000175000017500000000000013614562017020055 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/09_cookies/04_secure.t0000644000175000017500000000115513614371230022030 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.3513+dfsg.orig/t/09_cookies/03_persistence.t0000644000175000017500000000276313614371230023073 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"); }; use HTTP::Tiny::NoProxy; use HTTP::CookieJar; use Dancer; use File::Spec; plan tests => 9; Test::TCP::test_tcp( client => sub { my $port = shift; foreach my $client (qw(one two three)) { my $ua = HTTP::Tiny::NoProxy->new(cookie_jar => HTTP::CookieJar->new); 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->{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"; } }, 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, server => '127.0.0.1' ); Dancer->dance(); }, ); libdancer-perl-1.3513+dfsg.orig/t/09_cookies/05_api.t0000644000175000017500000000530513614371230021315 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.3513+dfsg.orig/t/09_cookies/01_use.t0000644000175000017500000000007613614371230021334 0ustar gregoagregoause Test::More tests => 1; BEGIN { use_ok 'Dancer::Cookie' } libdancer-perl-1.3513+dfsg.orig/t/09_cookies/000_create_fake_env.t0000644000175000017500000000052413614371230023716 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.3513+dfsg.orig/t/09_cookies/02_cookie_object.t0000644000175000017500000000216513614371230023341 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.3513+dfsg.orig/t/09_cookies/06_expires.t0000644000175000017500000000344413614371230022226 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.3513+dfsg.orig/t/24_deployment/0000755000175000017500000000000013614371230020571 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/24_deployment/01_multi_webapp.t0000644000175000017500000000333713614371230023754 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 HTTP::Tiny::NoProxy; use HTTP::Server::Simple::PSGI; plan tests => 100; Test::TCP::test_tcp( client => sub { my $port = shift; my @apps = (qw/app1 app2/); my $ua = HTTP::Tiny::NoProxy->new(); for(1..100){ my $app = $apps[int(rand(scalar @apps - 1))]; my $res = $ua->get("http://127.0.0.1:$port/$app"); 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.3513+dfsg.orig/t/author-pod-syntax.t0000644000175000017500000000045413614371230021702 0ustar gregoagregoa#!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); libdancer-perl-1.3513+dfsg.orig/t/00-report-prereqs.t0000644000175000017500000001342613614371230021506 0ustar gregoagregoa#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.027 use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do './t/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; my $cpan_meta_error; if ( $source && $HAS_CPAN_META && (my $meta = eval { CPAN::Meta->load_file($source) } ) ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } else { $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( $cpan_meta_error || @dep_errors ) { diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; } if ( $cpan_meta_error ) { my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; } if ( @dep_errors ) { diag join("\n", "\nThe following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass; # vim: ts=4 sts=4 sw=4 et: libdancer-perl-1.3513+dfsg.orig/t/lib/0000755000175000017500000000000013614562017016657 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/lib/TestApp.pm0000644000175000017500000000646713614371230020605 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'" }; # Test routes for GH #1205 - avoiding "Too late to set another cookie..." # explosions if accessing the session in an after hook get '/session/after_hook/read' => sub { session after_hook => "value set in route"; return "Meh"; }; hook after => sub { my $response = shift; if (request->path eq '/session/after_hook/read') { $response->content("Read " . session('after_hook')); } }; get '/session/after_hook/write' => sub { session after_hook => "value set in route"; return "Meh"; }; hook after => sub { my $response = shift; if (request->path eq '/session/after_hook/write') { session after_hook => "value changed in hook"; $response->content("Read " . session('after_hook')); } }; get '/session/after_hook' => sub { session('after_hook'); }; get '/session/after_hook/send_file' => sub { my $name = session('person') || "random person"; my $content = "Hi there, $name"; return send_file(\$content, content_type => 'text/plain'); }; hook after => sub { my $response = shift; # If the request path is stringified to 'SCALAR(...)' then it was a # send_file(\$content,...) call; check we can still access session # contents without exploding (GH #1205) if (request->path =~ /^SCALAR/) { my $name = session('person'); my $session = session(); $response->content( $response->content . " (after hook fired)" ); } }; any['put','post'] => '/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 }; # TODO: will need to be made more Clever if we need to test changing # nested settings put '/setting/:setting_name/:new_value' => sub { set params->{setting_name} => params->{new_value}; return "OK"; }; get '/setting/:setting_name' => sub { return setting( params->{setting_name} ); }; true; libdancer-perl-1.3513+dfsg.orig/t/lib/TestPluginMRO.pm0000644000175000017500000000032513614371230021664 0ustar gregoagregoapackage TestPluginMRO; use strict; use warnings; use mro 'c3'; use Dancer ':syntax'; use Dancer::Plugin; use base qw(Data::Dumper); register some_other_plugin_keyword => sub { 42; }; register_plugin; 1; libdancer-perl-1.3513+dfsg.orig/t/lib/TestPlugin2.pm0000644000175000017500000000030413614371230021365 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.3513+dfsg.orig/t/lib/LinkBlocker.pm0000644000175000017500000000076113614371230021413 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.3513+dfsg.orig/t/lib/Hookee.pm0000644000175000017500000000035013614371230020420 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.3513+dfsg.orig/t/lib/TestUtils.pm0000644000175000017500000000145213614371230021152 0ustar gregoagregoapackage TestUtils; use base 'Exporter'; use vars '@EXPORT'; use File::Path qw(mkpath rmtree); use Dancer::Request; use HTTP::Tiny; @EXPORT = qw(http_request write_file clean_tmp_files); sub http_request { my ($port, $method, $path) = @_; my $url = "http://localhost:${port}${path}"; my $http = HTTP::Tiny->new; return $http->request($method => $url); } 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.3513+dfsg.orig/t/lib/Forum.pm0000644000175000017500000000047513614371230020306 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.3513+dfsg.orig/t/lib/FromDataApp.pm0000644000175000017500000000037013614371230021346 0ustar gregoagregoause strict; use warnings; use Dancer; set engines => { template_toolkit => { embedded_templates => 1, }, }; set template => 'template_toolkit'; get '/' => sub { template 'hello' }; 1; __DATA__ __hello__ Hello embedded world! libdancer-perl-1.3513+dfsg.orig/t/lib/EasyMocker.pm0000644000175000017500000000260313614371230021253 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 unmock 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 = {}; my %orig_coderef; sub mock { { no strict 'refs'; no warnings 'redefine', 'prototype'; if (@_ == 3) { my ($class, $method, $sub) = @_; $orig_coderef{"${class}::${method}"} = \&{ *{"${class}::${method}"} }; *{"${class}::${method}"} = $sub; } else { my ($method, $sub) = @_; $orig_coderef{$method} = \&$method; *$method = $sub; } } } sub unmock { { no strict 'refs'; no warnings 'redefine', 'prototype'; if (@_ == 2) { my ($class, $method) = @_; if (!defined $orig_coderef{"${class}::${method}"}) { die "Can't unmock ${class}::${method} " . "- it wasn't mocked?"; } *{"${class}::${method}"} = delete $orig_coderef{"${class}::${method}"}; } else { my ($method) = @_; *$method = $orig_coderef{$method}; } } } 1; libdancer-perl-1.3513+dfsg.orig/t/lib/TestAppUnicode.pm0000644000175000017500000000141713614371230022102 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'} }; get '/unicode-content-length' => sub { "\x{100}0123456789"; }; get '/unicode-content-length-json' => sub { { test => "\x{100}" }; }; 1; libdancer-perl-1.3513+dfsg.orig/t/lib/TestPlugin.pm0000644000175000017500000000024113614371230021303 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.3513+dfsg.orig/t/20_deprecation/0000755000175000017500000000000013614371230020702 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/20_deprecation/01_api.t0000644000175000017500000000301413614371230022136 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.3513+dfsg.orig/t/11_logger/0000755000175000017500000000000013614562017017671 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/11_logger/08_serialize.t0000644000175000017500000000201013614371230022340 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.3513+dfsg.orig/t/11_logger/11_runtime_file.t0000644000175000017500000000144413614371230023037 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.3513+dfsg.orig/t/11_logger/10_note.t0000644000175000017500000000117113614371230021316 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.3513+dfsg.orig/t/11_logger/06_null.t0000644000175000017500000000105513614371230021331 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.3513+dfsg.orig/t/11_logger/04_console.t0000644000175000017500000000211413614371230022014 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.3513+dfsg.orig/t/11_logger/01_abstract.t0000644000175000017500000000131213614371230022151 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.3513+dfsg.orig/t/11_logger/02_factory.t0000644000175000017500000000161213614371230022021 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use FindBin qw($Bin); use lib "$Bin/../../"; 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.3513+dfsg.orig/t/11_logger/07_diag.t0000644000175000017500000000117713614371230021271 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.3513+dfsg.orig/t/11_logger/unicode.t0000644000175000017500000000073713614371230021506 0ustar gregoagregoause strict; use warnings; use Test::More tests => 2; use Test::NoWarnings; my $smileys = '☺☺☺'; { package MyApp; use utf8; use Dancer; use Encode qw/ decode_utf8 is_utf8 /; set charset => 'UTF-8'; set logger => 'Capture'; get '/' => sub { my $text = decode_utf8 $smileys; debug "is_utf8: " . is_utf8($text); debug "text: $text"; return "$text"; }; } use Dancer::Test; response_status_is '/' => 200; libdancer-perl-1.3513+dfsg.orig/t/11_logger/000_create_fake_env.t0000644000175000017500000000052413614371230023532 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.3513+dfsg.orig/t/11_logger/03_file.t0000644000175000017500000000337713614371230021304 0ustar gregoagregoause Test::More import => ['!pass']; use strict; use warnings; use FindBin qw($Bin); use lib "$Bin/../../"; 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.3513+dfsg.orig/t/11_logger/09_capture.t0000644000175000017500000000106713614371230022030 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.3513+dfsg.orig/t/11_logger/05_format.t0000644000175000017500000000356213614371230021653 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.3513+dfsg.orig/t/15_plugins/0000755000175000017500000000000013614562017020077 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/15_plugins/05b_plugins_and_c3.t0000644000175000017500000000227213614371230023620 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; plan tests => 3; SKIP: { use Dancer ':syntax'; # This plugin already inherits from Data::Dumper use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); eval { require TestPluginMRO; TestPluginMRO->import }; if (my $error = $@) { diag($error); if ($error =~ /Can't locate mro\.pm/) { # normal error, skip 3 skip 'mro is not available on this machine', 3; } else { fail('plugins can be used under the C3 MRO'); skip 'no point in running the rest', 2; } } else { # this can't be pass because Dancer exports pass() :/ ok(1, 'plugins can be used under the C3 MRO'); # and the plugin otherwise behaves. these tests are cribbed # from the existing 05_plugins_and_OO.t # 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 = TestPluginMRO->new( [ 1, 2 ], [ qw(foo bar) ] ); is($d->Dump(), "\$foo = 1;\n\$bar = 2;\n"); } } libdancer-perl-1.3513+dfsg.orig/t/15_plugins/03_namespace.t0000644000175000017500000000065313614371230022521 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.3513+dfsg.orig/t/15_plugins/02_config.t0000644000175000017500000000377413614371230022040 0ustar gregoagregoause strict; use warnings; use Dancer::ModuleLoader; use Test::More import => ['!pass']; plan skip_all => "YAML or YAML::XS is needed for this test" unless Dancer::ModuleLoader->load('YAML::XS') or 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 Dancer::ModuleLoader->load('YAML::XS') and config->{engines}->{YAML}->{module} = 'YAML::XS'; 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.3513+dfsg.orig/t/15_plugins/07_ajax_plack_builder.t0000644000175000017500000000374613614371230024402 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::Tiny::NoProxy; 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 $ua = HTTP::Tiny::NoProxy->new(); ok my $res = $ua->get($url), 'Got GET result'; ok $res->{success}, 'Successful'; is $res->{content}, $js_content, 'Correct JS content'; my %headers = ( 'X-Requested-With' => 'XMLHttpRequest' ); ok( $res = $ua->post("${url}foo", { headers => \%headers }), 'Got POST result' ); ok( $res->{success}, 'Successful' ); is( $res->{content}, 'bar', 'Correct content' ); }, server => sub { my $port = shift; my $handler = sub { use Dancer; set port => $port, server => '127.0.0.1', 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.3513+dfsg.orig/t/15_plugins/000_create_fake_env.t0000644000175000017500000000052413614371230023740 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.3513+dfsg.orig/t/15_plugins/05_keywords.t0000644000175000017500000000104013614371230022425 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.3513+dfsg.orig/t/15_plugins/01_register.t0000644000175000017500000000060313614371230022402 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.3513+dfsg.orig/t/15_plugins/04_apps_and_plugins.t0000644000175000017500000000044013614371230024106 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.3513+dfsg.orig/t/15_plugins/06_hook.t0000644000175000017500000000155613614371230021533 0ustar gregoagregoause strict; use warnings; use Test::More import => ['!pass']; use Dancer ':syntax'; use Dancer::Test; use lib 't/lib'; use FindBin qw($Bin); use lib "$Bin/../../"; 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.3513+dfsg.orig/t/15_plugins/05_plugins_and_OO.t0000644000175000017500000000106113614371230023461 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.3513+dfsg.orig/t/03_route_handler/0000755000175000017500000000000013614562017021246 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/03_route_handler/04_routes_matching.t0000644000175000017500000001215013614371230025123 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.3513+dfsg.orig/t/03_route_handler/05_unicode.t0000644000175000017500000000062713614371230023365 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.3513+dfsg.orig/t/03_route_handler/12_response.t0000644000175000017500000000314613614371230023572 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.3513+dfsg.orig/t/03_route_handler/views/0000755000175000017500000000000013614562017022403 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/03_route_handler/views/foo/0000755000175000017500000000000013614562017023166 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/03_route_handler/views/foo/index.tt0000644000175000017500000000001213614371230024632 0ustar gregoagregoafoo/index libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/views/foo/bar.tt0000644000175000017500000000001013614371230024265 0ustar gregoagregoafoo/bar libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/views/hello.tt0000644000175000017500000000000613614371230024046 0ustar gregoagregoaHello libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/views/error.tt0000644000175000017500000000031413614371230024076 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.3513+dfsg.orig/t/03_route_handler/33_vars.t0000644000175000017500000000164313614371230022712 0ustar gregoagregoause strict; use warnings; # Test that vars are really reset between each request use Test::More; use HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; for (1..10) { my $res = $ua->get("http://127.0.0.1:$port/getvarfoo"); 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, server => '127.0.0.1'; get "/getvarfoo" => sub { return ++vars->{foo}; }; Dancer->dance; }, ); libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/29_redirect_immediately.t0000644000175000017500000000111013614371230026115 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.3513+dfsg.orig/t/03_route_handler/15_prefix.t0000644000175000017500000000476713614371230023246 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.3513+dfsg.orig/t/03_route_handler/06_redirect.t0000644000175000017500000000602713614371230023541 0ustar gregoagregoause Test::More; use Dancer ':tests', ':syntax'; use Dancer::Test; plan tests => 17; # 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"; local $ENV{X_FORWARDED_PROTO} = "proto"; response_headers_include [GET => '/bounce'] => [Location => 'proto://nice.host.name/'], "Test X_FORWARDED_PROTO"; $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.3513+dfsg.orig/t/03_route_handler/public/0000755000175000017500000000000013614562017022524 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/03_route_handler/public/utf8file.txt0000644000175000017500000000003613614371230025005 0ustar gregoagregoa⋄ ⋄ ⋄ Hello ⋄ ⋄ ⋄ libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/public/404.html0000644000175000017500000000002013614371230023704 0ustar gregoagregoathis is an errorlibdancer-perl-1.3513+dfsg.orig/t/03_route_handler/29_forward.t0000644000175000017500000000451113614371230023405 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.3513+dfsg.orig/t/03_route_handler/16_embedded_prefixes.t0000644000175000017500000000166013614371230025375 0ustar gregoagregoause strict; use warnings; use Test::More tests => 10; use Dancer ':tests'; use Dancer::Test; prefix '/a' => sub { prefix '/1' => sub { get '/A' => sub { '/a/1/A' }; }; }; prefix '/b' => sub { prefix '/1' => sub { get '/A' => sub { '/b/1/A' }; }; prefix '/2' => sub { get '/A' => sub { '/b/2/A' }; get '/B' => sub { '/b/2/B' }; }; }; prefix '/c' => sub { prefix '/1' => sub { get '/A' => sub { '/c/1/A' }; }; prefix '/2' => sub { get '/A' => sub { '/c/2/A' }; get '/B' => sub { '/c/2/B' }; }; prefix '/3' => sub { get '/A' => sub { '/c/3/A' }; get '/B' => sub { '/c/3/B' }; get '/C' => sub { '/c/3/C' }; }; }; response_content_is $_ => $_, $_ for qw# /a/1/A /b/1/A /b/2/A /b/2/B /c/1/A /c/2/A /c/2/B /c/3/A /c/3/B /c/3/C #; libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/23_filter_error_catching.t0000644000175000017500000000056513614371230026276 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.3513+dfsg.orig/t/03_route_handler/30_forward_session.t0000644000175000017500000000075313614371230025144 0ustar gregoagregoause strict; use warnings; use Test::More tests => 1; use Dancer ':tests'; use Dancer::Test; # failsafe my $level = 1; set session => 'Simple'; get "/index" => sub { session player => "Groo"; $level++; forward "/main"; }; get "/main" => sub { die "urrrgh" if $level > 10; forward("/index") unless session("player"); "Hello world, " . session("player") . "!"; }; response_content_is '/index' => 'Hello world, Groo!', 'session is maintained by the forward'; libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/05_filter.t0000644000175000017500000000441513614371230023223 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.3513+dfsg.orig/t/03_route_handler/01_http_methods.t0000644000175000017500000000122013614371230024423 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.3513+dfsg.orig/t/03_route_handler/24_multiple_params.t0000644000175000017500000000561113614371230025134 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.3513+dfsg.orig/t/03_route_handler/03_routes_api.t0000644000175000017500000000364013614371230024105 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 (don't 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.3513+dfsg.orig/t/03_route_handler/07_compilation_warning.t0000644000175000017500000000152613614371230026003 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.3513+dfsg.orig/t/03_route_handler/14_options.t0000644000175000017500000000271013614371230023425 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.3513+dfsg.orig/t/03_route_handler/18_auto_page.t0000644000175000017500000000210613614371230023701 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.3513+dfsg.orig/t/03_route_handler/31_infinite_loop.t0000644000175000017500000000122413614371230024566 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.3513+dfsg.orig/t/03_route_handler/99_bugs.t0000644000175000017500000000247313614371230022715 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.3513+dfsg.orig/t/03_route_handler/34_forward_body_post.t0000644000175000017500000000241313614371230025462 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 HTTP::Tiny::NoProxy; plan tests => 2; Test::TCP::test_tcp( client => sub { my $port = shift; my $url_base = "http://127.0.0.1:$port"; my $ua = HTTP::Tiny::NoProxy->new; my $res = $ua->post_form($url_base . "/foo", { data => 'foo'}); is($res->{content}, "data:foo"); $res = $ua->post_form($url_base . "/foz", { data => 'foo'}); is($res->{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, server => '127.0.0.1', show_errors => 1; Dancer->dance(); }, ); libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/28_plack_mount.t0000644000175000017500000000272113614371230024255 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::Tiny::NoProxy; 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 $ua = HTTP::Tiny::NoProxy->new(); ok my $res = $ua->get($url); ok $res->{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.3513+dfsg.orig/t/03_route_handler/08_errors.t0000644000175000017500000000337213614371230023256 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.3513+dfsg.orig/t/03_route_handler/16_caching.t0000644000175000017500000000743613614371230023342 0ustar gregoagregoa# testing caching mechanism use strict; use warnings; use Test::More tests => 55, 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'}; my $size_limit = $cache->parse_size('3K'); $cache->size_limit( $size_limit ); # Add lots of long routes to the cache, so we can then check that the size # didn't grow out of control: for (1..500) { my $path = "/" . join '', map { int rand 10 } (1..10_000); $cache->store_path( 'RETICULATE', $path, sub { 1 }, ); } cmp_ok($cache->route_cache_size, '<', $size_limit, "Cache size stayed below limit"); } libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/02_params.t0000644000175000017500000000421713614371230023216 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.3513+dfsg.orig/t/03_route_handler/24_named_captures.t0000644000175000017500000000151713614371230024731 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.3513+dfsg.orig/t/03_route_handler/12_response_halt.t0000644000175000017500000000051413614371230024576 0ustar gregoagregoause strict; use warnings; use Test::More tests => 2; use Dancer ':tests'; use Dancer::Test; my @custom_header = ( 'X-Fruity' => 'tropical' ); get '/' => sub { headers @custom_header; halt( 'ABORT!' ); }; response_headers_include [ GET => '/' ] => \@custom_header, "headers kept"; response_content_is( '/', 'ABORT!' ); libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/21_ajax.t0000644000175000017500000000575613614371230022670 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 HTTP::Tiny::NoProxy; plan tests => 33; 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 = HTTP::Tiny::NoProxy->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) { my %headers; $headers{'X-Requested-With'} = 'XMLHttpRequest' if ( $query->{ajax} == 1); ok my $res = $ua->get("http://127.0.0.1:$port/" . $query->{path}, { headers => \%headers }); if ( $query->{success} == 1) { ok $res->{success}; is $res->{content}, $query->{content}; like $res->{headers}{'content-type'}, qr/text\/xml/ if $query->{ajax} == 1; } else { ok !$res->{success}; } } # test ajax with content_type to json my %headers = ( 'X-Requested-With' => 'XMLHttpRequest' ); ok my $res = $ua->get("http://127.0.0.1:$port/ajax.json", { headers => \%headers }); like $res->{headers}{'content-type'}, qr/json/; }, server => sub { my $port = shift; use Dancer; use Dancer::Plugin::Ajax; set startup_info => 0, port => $port, server => '127.0.0.1', 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.3513+dfsg.orig/t/03_route_handler/35_no_further_routes.t0000644000175000017500000000072113614371230025511 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.3513+dfsg.orig/t/03_route_handler/36_false_routes.t0000644000175000017500000000050613614371230024432 0ustar gregoagregoause strict; use warnings; use Test::More tests => 3; use Dancer ':tests'; prefix '/foo'; get '0' => sub { '0' }; # useful when we have prefixes and want to # use the prefix url too. E.g., here /foo get '' => sub { '' }; get ' ' => sub { ' ' }; use Dancer::Test; response_content_is "/foo$_" => $_ for '', 0, ' '; libdancer-perl-1.3513+dfsg.orig/t/03_route_handler/04_wildcards_megasplat.t0000644000175000017500000000172213614371230025744 0ustar gregoagregoause Dancer ':tests'; use Test::More; use Dancer::Test; plan tests => 6; 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)'; # mixed tokens and splat my $route_code = sub { my $id = param 'id'; $id = 'undef' unless defined $id; my $splt = show_splat(); return "$id:$splt" }; get '/some/:id/**/*' => $route_code; response_content_is [ GET => '/some/where/to/run/and/hide' ] => 'where:(to,run,and):hide'; get '/some/*/**/:id?' => $route_code; response_content_is [ GET => '/some/one/to/say/boo/' ] => 'undef:one:(to,say,boo)'; sub show_splat { return join ':', map { ref $_ ? "(" . join( ',', @$_ ) . ")": $_ } splat; } libdancer-perl-1.3513+dfsg.orig/t/TestAppExt.pm0000644000175000017500000000022313614371230020500 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.3513+dfsg.orig/t/00-compile.t0000644000175000017500000001141313614371230020136 0ustar gregoagregoause 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058 use Test::More; plan tests => 72 + ($ENV{AUTHOR_TESTING} ? 1 : 0); my @module_files = ( 'Dancer.pm', 'Dancer/App.pm', 'Dancer/Config.pm', 'Dancer/Config/Object.pm', 'Dancer/Continuation.pm', 'Dancer/Continuation/Halted.pm', 'Dancer/Continuation/Route.pm', 'Dancer/Continuation/Route/ErrorSent.pm', 'Dancer/Continuation/Route/FileSent.pm', 'Dancer/Continuation/Route/Forwarded.pm', 'Dancer/Continuation/Route/Passed.pm', 'Dancer/Continuation/Route/Templated.pm', 'Dancer/Cookie.pm', 'Dancer/Cookies.pm', 'Dancer/Deprecation.pm', 'Dancer/Engine.pm', 'Dancer/Error.pm', 'Dancer/Exception.pm', 'Dancer/Exception/Base.pm', 'Dancer/Factory/Hook.pm', 'Dancer/FileUtils.pm', 'Dancer/GetOpt.pm', 'Dancer/HTTP.pm', 'Dancer/Handler.pm', 'Dancer/Handler/Debug.pm', 'Dancer/Handler/PSGI.pm', 'Dancer/Handler/Standalone.pm', 'Dancer/Hook.pm', 'Dancer/Hook/Properties.pm', 'Dancer/Logger.pm', 'Dancer/Logger/Abstract.pm', 'Dancer/Logger/Capture.pm', 'Dancer/Logger/Capture/Trap.pm', 'Dancer/Logger/Console.pm', 'Dancer/Logger/Diag.pm', 'Dancer/Logger/File.pm', 'Dancer/Logger/Note.pm', 'Dancer/Logger/Null.pm', 'Dancer/MIME.pm', 'Dancer/ModuleLoader.pm', 'Dancer/Object.pm', 'Dancer/Object/Singleton.pm', 'Dancer/Plugin.pm', 'Dancer/Plugin/Ajax.pm', 'Dancer/Renderer.pm', 'Dancer/Request.pm', 'Dancer/Request/Upload.pm', 'Dancer/Response.pm', 'Dancer/Route.pm', 'Dancer/Route/Cache.pm', 'Dancer/Route/Registry.pm', 'Dancer/Serializer.pm', 'Dancer/Serializer/Abstract.pm', 'Dancer/Serializer/Dumper.pm', 'Dancer/Serializer/JSON.pm', 'Dancer/Serializer/JSONP.pm', 'Dancer/Serializer/Mutable.pm', 'Dancer/Serializer/XML.pm', 'Dancer/Serializer/YAML.pm', 'Dancer/Session.pm', 'Dancer/Session/Abstract.pm', 'Dancer/Session/Simple.pm', 'Dancer/Session/YAML.pm', 'Dancer/SharedData.pm', 'Dancer/Template.pm', 'Dancer/Template/Abstract.pm', 'Dancer/Template/Simple.pm', 'Dancer/Template/TemplateToolkit.pm', 'Dancer/Test.pm', 'Dancer/Timer.pm', 'HTTP/Tiny/NoProxy.pm' ); my @scripts = ( 'bin/dancer' ); # no fake home requested my @switches = ( -d 'blib' ? '-Mblib' : '-Ilib', ); use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L my $stderr = IO::Handle->new; diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } $^X, @switches, '-e', "require q[$lib]")) if $ENV{PERL_COMPILE_TEST_DEBUG}; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ and not eval { +require blib; blib->VERSION('1.01') }; if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } foreach my $file (@scripts) { SKIP: { open my $fh, '<', $file or warn("Unable to open $file: $!"), next; my $line = <$fh>; close $fh and skip("$file isn't perl", 1) unless $line =~ /^#!\s*(?:\S*perl\S*)((?:\s+-\w*)*)(?:\s*#.*)?$/; @switches = (@switches, split(' ', $1)) if $1; close $fh and skip("$file uses -T; not testable with PERL5LIB", 1) if grep { $_ eq '-T' } @switches and $ENV{PERL5LIB}; my $stderr = IO::Handle->new; diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } $^X, @switches, '-c', $file)) if $ENV{PERL_COMPILE_TEST_DEBUG}; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-c', $file); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$file compiled ok"); shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ and not eval { +require blib; blib->VERSION('1.01') }; # in older perls, -c output is simply the file portion of the path being tested if (@_warnings = grep { !/\bsyntax OK$/ } grep { chomp; $_ ne (File::Spec->splitpath($file))[2] } @_warnings) { warn @_warnings; push @warnings, @_warnings; } } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; libdancer-perl-1.3513+dfsg.orig/t/23_dancer_tests/0000755000175000017500000000000013614562017021073 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/23_dancer_tests/02_tests_functions.t0000644000175000017500000000614613614371230025015 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.3513+dfsg.orig/t/23_dancer_tests/01_basic.t0000644000175000017500000000423213614371230022635 0ustar gregoagregoause Test::More import => ['!pass'], tests => 21; 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 [POST => '/jsondata', { body => 42 }], 42, "a POST request with a body looks good"; response_content_is [PUT => '/jsondata', { body => 42 }], 42, "a PUT 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.3513+dfsg.orig/t/23_dancer_tests/03_uris.t0000644000175000017500000000072013614371230022536 0ustar gregoagregoause strict; use warnings; use Test::More tests => 5; use Dancer ':tests'; use Dancer::Test; get '/uri_base' => sub { request->uri_base }; get '/uri' => sub { request->uri }; get '/path' => sub { request->path }; response_content_is '/uri_base' => 'http://localhost'; response_content_is '/uri' => '/uri'; response_content_is '/uri?with=params' => '/uri?with=params'; response_content_is '/path' => '/path'; response_content_is '/path?with=params' => '/path'; libdancer-perl-1.3513+dfsg.orig/t/00-report-prereqs.dd0000644000175000017500000001112313614371230021622 0ustar gregoagregoado { my $x = { 'configure' => { 'requires' => { 'ExtUtils::MakeMaker' => '0' }, 'suggests' => { 'JSON::PP' => '2.27300' } }, 'develop' => { 'requires' => { 'Test::CPAN::Meta' => '0', 'Test::Pod' => '1.41' } }, 'runtime' => { 'recommends' => { 'MIME::Types' => '2.17', 'YAML' => '0', 'YAML::XS' => '0' }, 'requires' => { 'Carp' => '0', 'Cwd' => '0', 'Data::Dumper' => '0', 'Encode' => '0', 'Exporter' => '0', 'Fcntl' => '0', 'File::Basename' => '0', 'File::Copy' => '0', 'File::Path' => '0', 'File::Spec' => '0', 'File::Spec::Functions' => '0', 'File::Temp' => '0', 'File::stat' => '0', 'FindBin' => '0', 'Getopt::Long' => '0', 'HTTP::Body' => '0', 'HTTP::Date' => '0', 'HTTP::Headers' => '0', 'HTTP::Server::Simple::PSGI' => '0', 'HTTP::Tiny' => '0.014', 'Hash::Merge::Simple' => '0', 'IO::File' => '0', 'MIME::Types' => '0', 'Module::Runtime' => '0', 'POSIX' => '0', 'Pod::Usage' => '0', 'Scalar::Util' => '0', 'Test::Builder' => '0', 'Test::More' => '0', 'Time::HiRes' => '0', 'Try::Tiny' => '0', 'URI' => '0', 'URI::Escape' => '0', 'base' => '0', 'bytes' => '0', 'constant' => '0', 'lib' => '0', 'overload' => '0', 'parent' => '0', 'strict' => '0', 'vars' => '0', 'warnings' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'Data::Dump' => '0', 'Devel::Hide' => '0', 'Digest::MD5' => '0', 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'HTTP::CookieJar' => '0.008', 'HTTP::Request' => '0', 'HTTP::Tiny' => '0.014', 'IO::Handle' => '0', 'IO::Socket::INET' => '0', 'IPC::Open3' => '0', 'JSON' => '2.90', 'Plack::Builder' => '0', 'Test::More' => '0', 'Test::NoWarnings' => '0', 'perl' => '5.006', 'utf8' => '0' } } }; $x; }libdancer-perl-1.3513+dfsg.orig/t/02_request/0000755000175000017500000000000013614562017020102 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/02_request/04_custom.t0000644000175000017500000000212413614371230022076 0ustar gregoagregoause Test::More tests => 8; use strict; use warnings FATAL => 'all'; use Dancer::Request; my $tmpdir = File::Spec->tmpdir; %ENV = ( 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/', 'PATH_INFO' => '/', 'QUERY_STRING' => 'foo=bar&number=42', 'TMPDIR' => $tmpdir, ); 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.3513+dfsg.orig/t/02_request/21_dancer_response_multiple_params.t0000644000175000017500000000062113614371230027213 0ustar gregoagregoause Test::More tests => 2; use strict; use warnings; use Dancer::Test; { package MyApp; use Dancer ':tests'; set logger => 'console'; use Data::Dump; post '/things' => sub { Data::Dump::dump(params()) }; } my $response = dancer_response POST => '/things', {body => { things => [ 'a', 'b' ] } }; is $response->status, 200; is $response->content, '("things", ["a", "b"])'; libdancer-perl-1.3513+dfsg.orig/t/02_request/01_load.t0000644000175000017500000000006613614371230021503 0ustar gregoagregoause Test::More tests => 1; use_ok 'Dancer::Request'; libdancer-perl-1.3513+dfsg.orig/t/02_request/19_json_body.t0000644000175000017500000000115313614371230022561 0ustar gregoagregoause strict; use warnings; no warnings 'uninitialized'; use Test::More qw(no_plan); use HTTP::Headers; use Dancer::Request; my $headers = HTTP::Headers->new; $headers->header('Content-Type' => 'application/json'); $headers->header('Accept' => 'application/json'); my $json_string = '{"json_thing":"whatever"}'; my $request = Dancer::Request->new_for_request( PATCH => '/some/url/or/another', undef, $json_string, $headers, { CONTENT_TYPE => 'application/json', HTTP_ACCEPT => 'application/json', REQUEST_URI => '/some/url/or/another', } ); is($request->body, $json_string); libdancer-perl-1.3513+dfsg.orig/t/02_request/07_raw_data.t0000644000175000017500000000354013614371230022354 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/cygwin" if ($^O eq 'MSWin32'or $^O eq 'cygwin'); plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); use HTTP::Tiny::NoProxy; use constant RAW_DATA => "var: 2; foo: 42; bar: 57\nHey I'm here.\r\n\r\n"; my $host = '127.0.0.1'; plan tests => 6; Test::TCP::test_tcp( client => sub { my $port = shift; my $rawdata = RAW_DATA; my $ua = HTTP::Tiny::NoProxy->new; my $headers = { 'Content-Length' => length($rawdata) }; my $res = $ua->put("http://$host:$port/jsondata", { headers => $headers, content => $rawdata }); ok $res->{success}, 'req is success'; is $res->{content}, $rawdata, "raw_data is OK"; # Now, turn off storing raw request body in RAM, check that it was # effective $res = $ua->put("http://$host:$port/setting/raw_request_body_in_ram/0"); is $res->{status}, 200, 'success changing setting'; diag($res->{content}); $res = $ua->get("http://$host:$port/setting/raw_request_body_in_ram"); is $res->{content}, "0", "setting change was stored"; $res = $ua->put("http://$host:$port/jsondata", { headers => $headers, content => $rawdata }); ok $res->{success}, 'req is success'; is $res->{content}, "", "request body was empty with raw_request_body_in_ram false"; }, server => sub { my $port = shift; use TestApp; Dancer::Config->load; set( environment => 'production', port => $port, server => $host, startup_info => 0); Dancer->dance(); }, ); libdancer-perl-1.3513+dfsg.orig/t/02_request/13_ajax.t0000644000175000017500000000305213614371230021510 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 HTTP::Tiny::NoProxy; use HTTP::Headers; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = HTTP::Tiny::NoProxy->new; my $headers = { 'X-Requested-With' => 'XMLHttpRequest' }; my $res = $ua->get("http://127.0.0.1:$port/req", { headers => $headers }); ok($res->{success}, "server responded"); is($res->{content}, 1, "content ok"); $res = $ua->get("http://127.0.0.1:$port/req"); ok($res->{success}, "server responded"); is($res->{content}, 0, "content ok"); }, server => sub { my $port = shift; use Dancer; set (port => $port, server => '127.0.0.1', 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.3513+dfsg.orig/t/02_request/16_delete.t0000644000175000017500000000051113614371230022027 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.3513+dfsg.orig/t/02_request/06_init_env.t0000644000175000017500000000335113614371230022404 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.3513+dfsg.orig/t/02_request/17_uri_base.t0000644000175000017500000000127513614371230022367 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.3513+dfsg.orig/t/02_request/18_param_accessor.t0000644000175000017500000000026213614371230023554 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.3513+dfsg.orig/t/02_request/08_params.t0000644000175000017500000000753413614371230022065 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.3513+dfsg.orig/t/02_request/12_base.t0000644000175000017500000000262713614371230021505 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.3513+dfsg.orig/t/02_request/05_cgi_pm_compat.t0000644000175000017500000000064713614371230023376 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.3513+dfsg.orig/t/02_request/000_create_fake_env.t0000644000175000017500000000052413614371230023743 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.3513+dfsg.orig/t/02_request/10_mixed_params.t0000644000175000017500000000311713614371230023235 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' or $^O eq 'cygwin'); plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); use HTTP::Tiny::NoProxy; plan tests => 2; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = HTTP::Tiny::NoProxy->new; my $res = $ua->post_form("http://127.0.0.1:$port/params/route?a=1&var=query", {var => 'post', b => 2}); ok $res->{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, server => '127.0.0.1', startup_info => 0); Dancer->dance(); }, ); libdancer-perl-1.3513+dfsg.orig/t/02_request/11_accessors.t0000644000175000017500000000254513614371230022556 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.3513+dfsg.orig/t/02_request/14_uploads.t0000644000175000017500000001550613614371230022244 0ustar gregoagregoause strict; use warnings; use Dancer ':syntax'; use Dancer::Request; use Dancer::Test; use Dancer::FileUtils; use Test::More 'import' => ['!pass']; use Digest::MD5; 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 => $ENV{TEST_LARGE_FILE_UPLOAD} ? 22 : 20; 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, "Uploaded file with right filename"; # Return the filename and MD5 hash of the content so we can # double-check we got what we expected: return join ":", 'test', Digest::MD5::md5_hex($file->content); } ); post( '/uploads', sub { my $content; my $uploads = request->uploads; return join ";", map { join ":", $_, Digest::MD5::md5_hex($uploads->{$_}->content) } sort keys %$uploads; } ); $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, 'test:acbd18db4cc2f85cedef654fccc4a4d8', "Expected response for a single file upload"; 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 $resp->content, join(';',"a:0cc175b9c0f1b6a831c399e269772661", "b:92eb5ffee6ae2fec3ad71c777531578f", "c:4a8a08f09d37b73795649038408b5f33"), "Expected response for multi uploads"; # Test for a request with a large file upload - not run by default as it # involves creating a large file to upload, which is a bit rude, and this test # may exhaust available RAM on small systems. if ($ENV{TEST_LARGE_FILE_UPLOAD}) { # create a file, 256MB of zeros $dest_file = File::Spec->catfile($dest_dir, "zeros"); system("dd if=/dev/zero of=$dest_file count=250000 bs=1024"); open(my $zerosfh, "<", $dest_file) or die "Failed to open $dest_file - $!"; my $digest = Digest::MD5->new; $digest->addfile($zerosfh); my $expect_md5 = $digest->hexdigest; undef $digest; close $zerosfh; my $bigf_resp = dancer_response( 'POST', '/upload', { files => [ { name => 'test', filename => $dest_file } ] } ); is( $bigf_resp->content, "test:$expect_md5", "Large file uploaded OK" ); } libdancer-perl-1.3513+dfsg.orig/t/02_request/15_headers.t0000644000175000017500000000362613614371230022211 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 HTTP::Tiny::NoProxy; 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 = HTTP::Tiny::NoProxy->new; my $headers = { 'X-User-Head1' => 42, 'X-User-Head2' => 43 }; my $res = $ua->get("http://127.0.0.1:$port/req", { headers => $headers }); ok($res->{success}, "$handler server responded"); is($res->{headers}{'x-foo'}, 2); is($res->{headers}{'x-bar'}, 3); is($res->{headers}{'content-type'}, 'text/plain'); }, server => sub { my $port = shift; use Dancer; set( apphandler => $handler, port => $port, server => '127.0.0.1', 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.3513+dfsg.orig/t/02_request/08_param_array.t0000644000175000017500000000123713614371230023072 0ustar gregoagregoause strict; use warnings; use Test::More tests => 6; use Dancer::Test; { package MyApp; use Dancer ':tests'; get '/' => sub { return join ':', map { "!$_!" } param_array( 'foo' ) }; get '/scalar_context' => sub { scalar param_array('foo'); } } response_content_is '/' => '', "no params whatsoever"; response_content_is '/?foo=one' => '!one!', "one parameter"; response_content_is '/?foo=one;foo=two' => '!one!:!two!', "two parameters"; response_content_is '/scalar_context' => 0, 'no params'; response_content_is '/scalar_context?foo=one' => 1, 'one param'; response_content_is '/scalar_context?foo=one;foo=two' => 2, 'two params'; libdancer-perl-1.3513+dfsg.orig/t/02_request/04_forward.t0000644000175000017500000000132313614371230022230 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.3513+dfsg.orig/t/02_request/20_body.t0000644000175000017500000000240413614371230021520 0ustar gregoagregoa# See Issue 1140 use Test::More import => ['!pass']; use strict; use warnings; use Dancer::ModuleLoader; use Dancer; use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use IO::Socket::INET; plan skip_all => "skip test with Test::TCP in win32/cygwin" if ($^O eq 'MSWin32'or $^O eq 'cygwin'); plan skip_all => "Test::TCP is needed for this test" unless Dancer::ModuleLoader->load("Test::TCP" => "1.30"); use HTTP::Tiny::NoProxy; use constant RAW_DATA => "foo=bar&bar=baz"; plan tests => 2; Test::TCP::test_tcp( client => sub { my $port = shift; my $rawdata = RAW_DATA; my $ua = HTTP::Tiny::NoProxy->new; my $headers = { 'Content-Length' => length($rawdata), 'Content-Type' => 'application/x-www-form-urlencoded' }; my $res = $ua->request(POST => "http://127.0.0.1:$port/jsondata", { headers => $headers, content => $rawdata }); ok $res->{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, server => '127.0.0.1', startup_info => 0); Dancer->dance(); }, ); libdancer-perl-1.3513+dfsg.orig/t/16_timer/0000755000175000017500000000000013614371230017532 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/16_timer/00_base.t0000644000175000017500000000067713614371230021142 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.3513+dfsg.orig/t/00_base/0000755000175000017500000000000013614562017017322 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/00_base/010_export_script.t0000644000175000017500000000031113614371230022762 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.3513+dfsg.orig/t/00_base/views/0000755000175000017500000000000013614371230020452 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/00_base/views/unicode.tt0000644000175000017500000000011413614371230022445 0ustar gregoagregoasigma: 'Ʃ' pure_token: '<% pure_token %>' param_token: '<% param_token %>' libdancer-perl-1.3513+dfsg.orig/t/00_base/12_utf8_charset.t0000644000175000017500000000337213614371230022410 0ustar gregoagregoause strict; use warnings; use utf8; use Encode; use Test::More import => ['!pass']; use Dancer::ModuleLoader; use HTTP::Tiny::NoProxy; use FindBin qw($Bin); use lib "$Bin/../../"; plan skip_all => "skip test with Test::TCP in win32/cygwin" if ($^O eq 'MSWin32' or $^O eq 'cygwin'); 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', host => '127.0.0.1', 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 = HTTP::Tiny::NoProxy->new; return $ua->request($method => "http://127.0.0.1:$port${path}"); } libdancer-perl-1.3513+dfsg.orig/t/00_base/13_dancer_singleton.t0000644000175000017500000000167513614371230023334 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.3513+dfsg.orig/t/00_base/004_args.t0000644000175000017500000000245413614371230021026 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'} }, ); 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.3513+dfsg.orig/t/00_base/15_dependent_modules.t0000644000175000017500000000130713614371230023506 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.3513+dfsg.orig/t/00_base/005_module_loader.t0000644000175000017500000000075713614371230022712 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.3513+dfsg.orig/t/00_base/007_load_syntax.t0000644000175000017500000000025613614371230022420 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.3513+dfsg.orig/t/00_base/11_file_utils.t0000644000175000017500000000135213614371230022143 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.3513+dfsg.orig/t/00_base/002_strict_and_warnings.t0000644000175000017500000000305313614371230024126 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/, '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 global_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.3513+dfsg.orig/t/00_base/09_load_app.t0000644000175000017500000000126313614371230021573 0ustar gregoagregoause Test::More tests => 5, import => ['!pass']; use strict; use warnings; use Dancer ':syntax'; use File::Basename; use lib dirname(__FILE__) . "/lib"; # 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.3513+dfsg.orig/t/00_base/000_create_fake_env.t0000644000175000017500000000057213614371230023166 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.3513+dfsg.orig/t/00_base/easymocker.t0000644000175000017500000000064113614371230021645 0ustar gregoagregoause Test::More tests => 3; use strict; use warnings; use Dancer qw(:tests); use File::Spec; use lib File::Spec->catdir( 't', 'lib' ); use EasyMocker; ok( Dancer->true, "Before mocking, get true", ); mock 'Dancer' => method 'true' => should sub { 0 }; ok( !Dancer->true, "Mocked, get false", ); unmock 'Dancer' => method 'true'; ok( Dancer->true, "Unmocked, get true again", ); libdancer-perl-1.3513+dfsg.orig/t/00_base/optional-module-versions.t0000644000175000017500000000176613614371230024472 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.3513+dfsg.orig/t/00_base/utf8.tt0000644000175000017500000000003413614371230020551 0ustar gregoagregoautf8: ’♣ ♤ ♥ ♦’ libdancer-perl-1.3513+dfsg.orig/t/00_base/lib/0000755000175000017500000000000013614562017020070 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/00_base/lib/AppWithError.pm0000644000175000017500000000016213614371230023006 0ustar gregoagregoapackage AppWithError; use Dancer ':syntax'; bogus_call_to_unkown_symbol; get '/webapp' => sub { 'webapp' }; 1; libdancer-perl-1.3513+dfsg.orig/t/00_base/lib/WorkingApp.pm0000644000175000017500000000011413614371230022476 0ustar gregoagregoapackage WorkingApp; use Dancer ':syntax'; get '/app' => sub { "app" }; 1; libdancer-perl-1.3513+dfsg.orig/t/00_base/06_dancer_object.t0000644000175000017500000000322013614371230022566 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 parent '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 parent -norequire => '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 parent -norequire => '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.3513+dfsg.orig/t/00_base/17_globalwarnings_config_on.t0000644000175000017500000000113213614371230025040 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.3513+dfsg.orig/t/00_base/08_pod_coverage_dancer.t0000644000175000017500000000114213614371230023760 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.3513+dfsg.orig/t/00_base/009_syntax_export.t0000644000175000017500000000061113614371230023017 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.3513+dfsg.orig/t/00_base/normalize_path.t0000644000175000017500000000124613614371230022521 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.3513+dfsg.orig/t/00_base/001_load.t0000644000175000017500000000027513614371230021005 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.3513+dfsg.orig/t/00_base/uri_for.t0000644000175000017500000000041113614371230021143 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.3513+dfsg.orig/t/00_base/config.t0000644000175000017500000000052613614371230020752 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.3513+dfsg.orig/t/00_base/003_syntax.t0000644000175000017500000000161513614371230021415 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.3513+dfsg.orig/t/00_base/008_export.t0000644000175000017500000000061713614371230021416 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.3513+dfsg.orig/t/04_static_file/0000755000175000017500000000000013614562017020702 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/04_static_file/secretfile0000644000175000017500000000017413614371230022747 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.3513+dfsg.orig/t/04_static_file/02_dir_traversal.t0000644000175000017500000000117213614371230024225 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.3513+dfsg.orig/t/04_static_file/01_mime_types.t0000644000175000017500000000427313614371230023543 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.3513+dfsg.orig/t/04_static_file/003_mime_types_reinit.t0000644000175000017500000000233313614371230025172 0ustar gregoagregoause strict; use warnings; use Config; use IO::Handle; use Dancer::MIME; use Dancer ':syntax'; use Dancer::ModuleLoader; use Test::More import => ['!pass']; plan skip_all => "fork not supported on this platform" unless $Config::Config{d_fork} || $Config::Config{d_pseudofork} || (($^O eq 'MSWin32' || $^O eq 'NetWare') and $Config::Config{useithreads} and $Config::Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/); 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.3513+dfsg.orig/t/04_static_file/static/0000755000175000017500000000000013614371230022164 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/t/04_static_file/static/hello.foo0000644000175000017500000000001213614371230023765 0ustar gregoagregoaHello Foo libdancer-perl-1.3513+dfsg.orig/t/04_static_file/static/hello.txt0000644000175000017500000000001413614371230024023 0ustar gregoagregoahello there libdancer-perl-1.3513+dfsg.orig/t/04_static_file/001_base.t0000644000175000017500000000450313614371230022356 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::Tiny::NoProxy; Test::TCP::test_tcp( client => sub { my $port = shift; my $ua = HTTP::Tiny::NoProxy->new(); my $res = $ua->get("http://127.0.0.1:$port/hello%00.txt"); ok !$res->{success}; is $res->{status}, 400; }, server => sub { my $port = shift; setting apphandler => 'PSGI'; Dancer::Config->load; my $app = Dancer::Handler->psgi_app; Plack::Loader->auto( port => $port, host => '127.0.0.1' )->run($app); Dancer->dance(); } ); Test::TCP::test_tcp( client => sub { my $port = shift; my $headers = { 'If-Modified-Since' => $date }; my $ua = HTTP::Tiny::NoProxy->new(); my $res = $ua->get("http://127.0.0.1:$port/hello.txt", { headers => $headers }); ok !$res->{success}; is $res->{status}, 304; }, server => sub { my $port = shift; setting apphandler => 'PSGI'; Dancer::Config->load; my $app = Dancer::Handler->psgi_app; Plack::Loader->auto( port => $port, host => '127.0.0.1' )->run($app); Dancer->dance(); } ); libdancer-perl-1.3513+dfsg.orig/t/TestPlugin.pm0000644000175000017500000000023513614371230020540 0ustar gregoagregoapackage TestPlugin; use strict; use warnings; use Dancer::Plugin; register 'test_plugin_symbol' => sub { "test_plugin_symbol"; }; register_plugin; 1; libdancer-perl-1.3513+dfsg.orig/lib/0000755000175000017500000000000013614562017016414 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/lib/Dancer/0000755000175000017500000000000013614562017017610 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/lib/Dancer/Request.pm0000644000175000017500000007207113614371230021600 0ustar gregoagregoapackage Dancer::Request; our $AUTHORITY = 'cpan:SUKRIA'; #ABSTRACT: interface for accessing incoming requests $Dancer::Request::VERSION = '1.3513'; 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', '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 { setting('behind_proxy') ? $_[0]->forwarded_for_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')) { # PSGI specs say that X_FORWARDED_PROTO will # be converted into HTTP_X_FORWARDED_PROTO # but Dancer::Test doesn't use PSGI (for now) $scheme = $_[0]->env->{'HTTP_X_FORWARDED_PROTO'} || $_[0]->env->{'X_FORWARDED_PROTOCOL'} || $_[0]->env->{'HTTP_X_FORWARDED_PROTOCOL'} || $_[0]->env->{'HTTP_FORWARDED_PROTO'} || $_[0]->env->{'X_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]) } # We used to store the whole raw unparsed body; this was a big problem for large # file uploads (Issue 1129). # The original fix was to stop doing so, and replace the accessor with one that # would read it out of the temp file returned by HTTP::Body->body - but that # doesn't work for e.g. parsed form submissions, only certain types. # So, back to the older way - we may have a request body squirreled away # in memory if the config included the raw_request_body_in_ram boolean sub body { $_[0]->{body} } # 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->{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->{body} = ''; # default, because we might not store it now. $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 }; $env->{CONTENT_LENGTH} = defined($body) ? length($body) : 0 if !exists $env->{CONTENT_LENGTH}; my $req = $class->new(env => $env); $req->{params} = {%{$req->{params}}, %{$params}}; $req->_build_params(); $req->{_query_params} = $req->{params}; my $store_raw_body = setting('raw_request_body_in_ram'); $store_raw_body = defined $store_raw_body ? $store_raw_body : 1; if ($store_raw_body) { $req->{body} = $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->{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}; $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 = shift; return unless $self->_has_something_to_read; if ( $self->content_length > 0 ) { my $body = ''; my $store_raw_body = setting('raw_request_body_in_ram'); $store_raw_body = defined $store_raw_body ? $store_raw_body : 1; while ( my $buffer = $self->_read ) { $self->{_http_body}->add($buffer); # Only keep a copy of the raw request body in RAM if the user has # asked us to if ($store_raw_body) { $self->{body} .= $buffer; } } } return $self->{_http_body}; } sub _has_something_to_read { defined $_[0]->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 =encoding UTF-8 =head1 NAME Dancer::Request - interface for accessing incoming requests =head1 VERSION version 1.3513 =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 is_forward Flag that will be set to true if the request has been L. =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, return a list with its values if called in list context, or the first one if called in scalar context. =head2 headers() Returns the L object used to store all the headers. =head2 body() Return the raw body of the request, unparsed. NOTE: the behaviour of this keyword has changed. Originally, the entire raw request body was kept in RAM for this accessor, but that's not ideal if you handle large requests (file uploads, etc), so in 1.3143 that was ditched, and the body accessor replaced by a convenience method which would get the temp file handle that HTTP::Body uses, read it for you and return the content, so that if you did want the raw body, it was there. However, HTTP::Body only creates a temp file for certain types of request, leading to unpredictable behaviour and confusion - see issue #1140. So, handling of the raw request body is now controlled by a configuration setting, raw_request_body_in_ram, which controls whether or not the raw request body will be kept in RAM when it's parsed; if this is set to a false value, then I, giving you lower memory usage, at the cost of not having access to the raw (unparsed) request body. =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/ host perldancer.org uri_base http://perldancer.org:5000 uri /request-methods?a=1 request_uri /request-methods?a=1 path /request-methods path_info /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 Looks for HTTP_X_FORWARDED_FOR if X_FORWARDED_FOR is not there. =item C =item C =item C If you app is on a non-standard port, you can expect this to return the hostname and port, e.g. 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 =head1 AUTHOR Dancer Core Developers =head1 COPYRIGHT AND LICENSE This software is copyright (c) 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. =cut libdancer-perl-1.3513+dfsg.orig/lib/Dancer/Handler.pm0000644000175000017500000001450313614371230021521 0ustar gregoagregoapackage Dancer::Handler; our $AUTHORITY = 'cpan:SUKRIA'; # ABSTRACT: Dancer request handler $Dancer::Handler::VERSION = '1.3513'; 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; Dancer::App->reload_apps if Dancer::Config::setting('auto_reload'); 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/; } if (!defined $response->header('Content-Length')) { use bytes; # turn off character semantics $response->header( 'Content-Length' => length($content) ); } $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 =~ /(\bx(?:ht)?ml\b|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; __END__ =pod =encoding UTF-8 =head1 NAME Dancer::Handler - Dancer request handler =head1 VERSION version 1.3513 =head1 AUTHOR Dancer Core Developers =head1 COPYRIGHT AND LICENSE This software is copyright (c) 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. =cut libdancer-perl-1.3513+dfsg.orig/lib/Dancer/Hook/0000755000175000017500000000000013614371230020503 5ustar gregoagregoalibdancer-perl-1.3513+dfsg.orig/lib/Dancer/Hook/Properties.pm0000644000175000017500000000262413614371230023201 0ustar gregoagregoapackage Dancer::Hook::Properties; our $AUTHORITY = 'cpan:SUKRIA'; #ABSTRACT: Properties attached to a hook $Dancer::Hook::Properties::VERSION = '1.3513'; 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; __END__ =pod =encoding UTF-8 =head1 NAME Dancer::Hook::Properties - Properties attached to a hook =head1 VERSION version 1.3513 =head1 SYNOPSIS =head1 DESCRIPTION Properties attached to a hook =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. =head1 AUTHOR Dancer Core Developers =head1 COPYRIGHT AND LICENSE This software is copyright (c) 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. =cut libdancer-perl-1.3513+dfsg.orig/lib/Dancer/GetOpt.pm0000644000175000017500000000503113614371230021342 0ustar gregoagregoapackage Dancer::GetOpt; our $AUTHORITY = 'cpan:SUKRIA'; # ABSTRACT: Process command-line options for Dancer scripts $Dancer::GetOpt::VERSION = '1.3513'; 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(@_) }, ) || 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 <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; __END__ =pod =encoding UTF-8 =head1 NAME Dancer::Handler::Standalone - Web server wrapper for Dancer =head1 VERSION version 1.3513 =head1 AUTHOR Dancer Core Developers =head1 COPYRIGHT AND LICENSE This software is copyright (c) 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. =cut libdancer-perl-1.3513+dfsg.orig/lib/Dancer/Handler/Debug.pm0000644000175000017500000000631113614371230022545 0ustar gregoagregoapackage Dancer::Handler::Debug; our $AUTHORITY = 'cpan:SUKRIA'; #ABSTRACT: a debug handler for easy tracing $Dancer::Handler::Debug::VERSION = '1.3513'; 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, @env ) = @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/", map { /=/ ? split /=/, $_, 2 : () } @env }; $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 =encoding UTF-8 =head1 NAME Dancer::Handler::Debug - a debug handler for easy tracing =head1 VERSION version 1.3513 =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 arguments given on the command line, which must follow the pattern =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 arguments perl -d bin/app.pl GET '/some/path/to/test' 'with=parameters&other=42' # with environment variables perl -d bin/app.pl GET '/some/path/to/test' '' HTTP_X_REQUESTED_WITH=XMLHttpRequest SERVER_NAME=fake =head1 AUTHORS Dancer contributors =head1 AUTHOR Dancer Core Developers =head1 COPYRIGHT AND LICENSE This software is copyright (c) 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. =cut libdancer-perl-1.3513+dfsg.orig/lib/Dancer/Handler/PSGI.pm0000644000175000017500000000656613614371230022275 0ustar gregoagregoapackage Dancer::Handler::PSGI; our $AUTHORITY = 'cpan:SUKRIA'; #ABSTRACT: a PSGI handler for Dancer applications $Dancer::Handler::PSGI::VERSION = '1.3513'; 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 =encoding UTF-8 =head1 NAME Dancer::Handler::PSGI - a PSGI handler for Dancer applications =head1 VERSION version 1.3513 =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 =head1 AUTHOR Dancer Core Developers =head1 COPYRIGHT AND LICENSE This software is copyright (c) 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. =cut libdancer-perl-1.3513+dfsg.orig/lib/Dancer/Policy.pod0000644000175000017500000000733713614371230021560 0ustar gregoagregoa# PODNAME: Dancer::Policy # ABSTRACT: Dancer core and community policy and standards of conduct __END__ =pod =encoding UTF-8 =head1 NAME Dancer::Policy - Dancer core and community policy and standards of conduct =head1 VERSION version 1.3513 =head1 DESCRIPTION This document describes various policies (most notably, the standards of conduct) for the Dancer core developers and broad community. This is what we expect from our community and ourselves and these are the standards of behavior we set forth in order to make sure the community remains a safe space for all of its members, without exception. =head1 STANDARDS OF CONDUCT These standards applies anywhere the community comes together as a group. This includes, but is not limited to, the Dancer IRC channel, the Dancer mailing list, Dancer hackathons, and Dancer conferences. =over 4 =item * Always be civil. =item * Heed the moderators. =item * Abuse is not tolerated. =back Civility is simple: stick to the facts while avoiding demeaning remarks and sarcasm. It is not enough to be factual. You must also be civil. Responding in kind to incivility is not acceptable. If the list moderators tell you that you are not being civil, carefully consider how your words have appeared before responding in any way. You may protest, but repeated protest in the face of a repeatedly reaffirmed decision is not acceptable. Unacceptable behavior will result in a public and clearly identified warning. Repeated unacceptable behavior will result in removal from the mailing list and revocation of any commit bit. The first removal is for one month. Subsequent removals will double in length. After six months with no warning, a user's ban length is reset. Removals, like warnings, are public. The list of moderators consists of all active core developers. This includes, in alphabetical order, Alberto Simões, David Precious, Mickey Nasriachi, Russell Jenkins, Sawyer X, Stefan Hornburg (Racke), Steven Humphrey, and Yanick Champoux. This list might additionally grow to active members of the community who have stepped up to help handle abusive behavior. If this should happen, this document would be updated to include their names. Additionally, it's important to understand the self-regulating nature we foster at the Dancer community. This means anyone and everyone in the community - in the channel, on the list, at an event - has the ability to call out unacceptable behavior and incivility to others in the community. Moderators are responsibe for issuing warnings and take disciplenary actions, but anyone may - and is encouraged - to publicly make note of unacceptable treatment of others. As a core principle, abuse is never tolerated. One cannot berate, insult, debase, deride, put-down, or vilify anyone, or act towards anyone in a way intending to hurt them. The community specifically considers as abuse any attempts to otherize anyone, whether by their technical skill, knowledge, gender, sexual orientation, or any other characteristic. The community aims to maintain a safe space for everyone, in any forum it has. If you ever feel this core principle has been compromised, you are strongly urged to contact a moderator. We are always here. Remember, this is B community, as much as it is anyone else's. =head1 CREDITS This policy has been adopted and adapted from the policy available for the Perl language development, provided by B (the Perl 5 Porters). The original inspiration policy document can be read at L. =head1 AUTHOR Dancer Core Developers =head1 COPYRIGHT AND LICENSE This software is copyright (c) 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. =cut libdancer-perl-1.3513+dfsg.orig/lib/Dancer/Config.pm0000644000175000017500000005516213614371230021357 0ustar gregoagregoapackage Dancer::Config; our $AUTHORITY = 'cpan:SUKRIA'; #ABSTRACT: how to configure Dancer to suit your needs $Dancer::Config::VERSION = '1.3513'; use strict; use warnings; use base 'Exporter'; use vars '@EXPORT_OK'; use Hash::Merge::Simple; 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"), settings()); }, 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 $module = load_yaml_module(); unless ($_LOADED{conffile()}) { load_settings_from_yaml(conffile, $module); $_LOADED{conffile()}++; } my $env = environment_file; # don't load the same env twice unless( $_LOADED{$env} ) { if (-f $env ) { load_settings_from_yaml($env, $module); $_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, $module) = @_; $module ||= load_yaml_module(); my $config; { no strict 'refs'; $config = eval { &{ $module . '::LoadFile' }($file) } or confess "Unable to parse the configuration file: $file: $@"; } $SETTINGS = Hash::Merge::Simple::merge( $SETTINGS, { map { $_ => Dancer::Config->normalize_setting( $_, $config->{$_} ) } keys %$config } ); return scalar keys %$config; } sub load_yaml_module { my ($module) = @_; $module ||= $SETTINGS->{engines}{YAML}{module} || 'YAML'; my ( $result, $error ) = Dancer::ModuleLoader->load($module); confess "Could not load $module: $error" unless $result; return $module; } 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_NO_STARTUP_INFO}; $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_NO_SERVER_TOKENS}; $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 =encoding UTF-8 =head1 NAME Dancer::Config - how to configure Dancer to suit your needs =head1 VERSION version 1.3513 =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. To fetch the available configuration values use the B keyword that returns a reference to a hash: my $port = config->{port}; my $appdir = config->{appdir}; By default, the module L will be used to parse the configuration files. If desired, it is possible to use L instead by changing the YAML engine configuration in the application code: config->{engines}{YAML}{module} = 'YAML::XS'; See L for more details. =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. Can also be set with environment variable L =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. Can also be set with environment variable L =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. Can also be enabled by setting environment variable L to a true value. =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. It will also cause L<< Dancer::Request->address|Dancer::Request/address >> to return what L<< Dancer::Request->forwarded_for_address|Dancer::Request/forwarded_for_address >> would return, namely the content of the `HTTP_X_FORWARDED_FOR` env var/header, so that requests will appear to have come from the end user's IP and not the proxy's. Because of the above, you should *not* turn this on if your app isn't behind a proxy which will pass this information on appropriately, otherwise a malicious user could supply false information. =head2 Content type / character set =head3 content_type (string) The default content type of outgoing content. Default value is 'text/html'. Can also be set with environment variable L =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. Can also be set with environment variable L =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 an C folder with specific configuration files for different environments (usually development and production environments). They specify different kinds 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. Can also be set with environment variable L =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. Can also be set with environment variable L =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/layouts. Your can override the default layout using the third argument of the C