{"id":18343467,"url":"https://github.com/cosimo/http-cuke","last_synced_at":"2026-04-02T02:07:19.187Z","repository":{"id":2290902,"uuid":"3248840","full_name":"cosimo/http-cuke","owner":"cosimo","description":"Cucumber-style HTTP frontends testing","archived":false,"fork":false,"pushed_at":"2020-02-28T13:58:14.000Z","size":55,"stargazers_count":9,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-29T12:39:16.144Z","etag":null,"topics":["cucumber","http","perl","testing","testing-tools"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cosimo.png","metadata":{"files":{"readme":"README.pod","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-01-23T17:53:39.000Z","updated_at":"2020-02-28T14:32:49.000Z","dependencies_parsed_at":"2022-09-07T02:23:47.106Z","dependency_job_id":null,"html_url":"https://github.com/cosimo/http-cuke","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cosimo/http-cuke","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosimo%2Fhttp-cuke","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosimo%2Fhttp-cuke/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosimo%2Fhttp-cuke/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosimo%2Fhttp-cuke/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cosimo","download_url":"https://codeload.github.com/cosimo/http-cuke/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosimo%2Fhttp-cuke/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31294398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T01:43:37.129Z","status":"online","status_checked_at":"2026-04-02T02:00:08.535Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cucumber","http","perl","testing","testing-tools"],"created_at":"2024-11-05T20:36:09.714Z","updated_at":"2026-04-02T02:07:19.165Z","avatar_url":"https://github.com/cosimo.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"=head1 NAME\n\nhttp-cuke - Cucumber-style HTTP configuration testing for the masses\n\n=head1 SYNOPSIS\n\nExample of test scenario:\n\n    Feature: Front page responds correctly\n    In order to avoid problems with caching logic and/or frontend configuration\n    As an operations ninja\n    I want to check that front page is served correctly and the frontends configuration is correct\n\n    Scenario: HTTP to HTTPS redirects are in place\n      When I go to \"http://my.example.server.lan/\"\n      Then I should be redirected to \"https://my.example.server.lan/\"\n      Then the final HTTP status code should be \"200\"\n\nPut that text in a C\u003cwhatever.test\u003e file, and point\nC\u003chttp-cuke\u003e to the directory that contains it with:\n\n    http-cuke --test-dir ./some-tests\n\nOr run just a single test file:\n\n    http-cuke --test ./single.test\n\nHave a look at the C\u003ctests\u003e directory where you will\nfind this example:\n\n    Feature: Google front page allows me to search\n    In order not to be stuck without being able to google something\n    As a curious person\n    I want to be check that Google is available\n\n    Scenario: Google frontpage is available\n      Given the HTTP request header \"Accept-Language\" is \"en\"\n      When I go to \"http://www.google.com/\"\n      Then the final HTTP status code should be \"200\"\n      Then the page should contain \"Google\"\n\nThis is a test you can actually run with:\n\n    cd bin\n    ./http-cuke --test ../tests/example.test\n\nYou can also use B\u003cvariables\u003e in your test files.\nSee the L\u003cVARIABLES SUPPORT\u003e chapter.\n\n=head1 DESCRIPTION\n\nRun cucumber style tests against any HTTP server.\n\nIf you are not familiar with cucumber, check it out\nat L\u003chttp://cukes.info/\u003e.\n\nWith this tool you can define set of tests (or B\u003cfeatures\u003e\nand B\u003cscenarios\u003e in cucumber-speak) and run them.\n\nThe type of tests that C\u003chttp-cuke\u003e can help you with\nare those that involve checking a HTTP server configuration,\nbehavior or plain responses.\n\nYou can check redirects, response headers, cookies,\nresponse bodies, inject custom HTTP headers in the requests,\ncheck Varnish responses, and more.\n\n\n=head1 OTHER SUPPORTED OPTIONS\n\n=over\n\n=item C\u003c--allow-insecure-ssl\u003e\n\nWhen this option is specified, C\u003chttp-cuke\u003e will silently connect to HTTPS hosts\nB\u003cwithout verifying SSL certificates validity!\u003e. This is B\u003cINSECURE\u003e, so only\ndo it if you are aware of the implications.\n\nThe typical use case is to connect to individual backends part of a bigger\ncluster typically behind a load balancer.\n\n=item C\u003c--useragent-timeout\u003e\n\nHow long should the user agent that makes the requests wait for backend\nrequests. This is using C\u003cLWP::UserAgent\u003e, so don't expect perfect control\nof client timeout. For example, this will usually not include eventual DNS\ntimeouts/slowdowns, so the actual timeout might be much longer than you\nspecify.\n\nUsage:\n\n    http-cuke --useragent-timeout 10 --test ...\n\n=item C\u003c--useragent-string\u003e\n\nOverride the default user agent string (C\u003chttp-cuke/version\u003e).\n\nUsage:\n\n    http-cuke --useragent-string 'MyWebSiteTesterFTW/0.01'\n\n=back\n\n=head1 MOTIVATION: THE WHY\n\nThis tool is B\u003cnot\u003e meant to replace tools like C\u003cWWW::Mechanize\u003e or similar\nones. It is meant to perform automated testing for frontends configuration\ntesting.\n\nBy frontend I mean Apache, Nginx, Varnish, and deadly combinations of the\nthree. It can be a nightmare to make sure you have all the correct redirects in\nplace, that pages are cached according to your own logic, etc...\n\nYes, but even then, after all, cucumber is pretty well established.\nSo why?\n\nBecause of the dependencies mess. I don't want to depend on too many packages,\nand Perl already has all the tools I needed to do this. I just glued them\ntogether, and there you have a TAP-compliant cucumber-style HTTP testing that\ncan easily be hooked up to B\u003cJenkins\u003e, B\u003cGitLab\u003e or your preferred CI/CD\nsystem.\n\nThe B\u003cmain advantage of this tool\u003e is that it opens up even complex HTTP\ntesting to a broader audience, not necessarily programmers. That is, btw, a\nmajor point of BDD testing, and that's Good(tm).\n\n=head1 VARIABLES SUPPORT\n\nHere's an example of test script in Cucumber style:\n\n    Feature: My service can be monitored correctly by Nagios\n    In order to make sure that Nagios alerts don't fire unnecessarily\n    As an operations ninja\n    I want to verify that the resources accessed by Nagios are always available\n\n    Scenario: ping.html page is served over http\n      When I go to \"http://my.server.local/ping.html\"\n      Then the final HTTP status code should be \"200\"\n      Then the page should contain \"I am alive\"\n\nIt is possible (and desirable) to embed variables in your test files.\nIn the example above, instead of hardcoding the C\u003chttp://my.server.local\u003e\naddress, you can use a variable like this:\n\n    Scenario: ping.html page is served over http\n      When I go to \"{{ SERVER_URL }}/ping.html\"\n      Then the final HTTP status code should be \"200\"\n      Then the page should contain \"I am alive\"\n\nTo run this test, you need to invoke C\u003chttp-cuke\u003e with the C\u003c-D\u003e\noption, to define variables. Example:\n\n    http-cuke --test ./nagios.test -D SERVER_URL=http://my.server.local\n\nIf you use variables in your test scripts, but omit to declare them\nwhen invoking C\u003chttp-cuke\u003e, you will be warned with a message:\n\n    Undefined variable 'SERVER_URL' in line:\n\n      When I go to \"{{ SERVER_URL }}/ping.html\"\n\n\n=head1 AVAILABLE TESTS\n\nSo what are the B\u003cmagic words\u003e that are available to build\nthe test cases?\n\nHere's a list:\n\n=over 4\n\n=item C\u003cGiven a max of (\\d+) redirects\u003e\n\n=item C\u003cGiven a timeout of (\\d+) seconds\u003e\n\n=item C\u003cGiven a \"(.+)\" user agent\u003e\n\n=item C\u003cGiven the HTTP request header \"(.+)\" is \"(.*)\"\u003e\n\n=item C\u003cGiven the client sends a cookie \"(.+)\" with value \"(.*)\"\u003e\n\n=item C\u003cWhen I go to \"(.+)\"\u003e\n\n=item C\u003cWhen I send a ([A-Z]+) request to \"([^\"]+)\"\u003e\n\n=item C\u003cWhen I send a ([A-Z]+) request to \"([^\"]+)\" with body \"(.*)\"\u003e\n\nA super-cheap hack, but it works for now. Examples:\n\n    When I send a GET request to \"http://somedomain.lan/\"\n    When I send a POST request to \"http://somedomain.lan/\" with body \"\"\n    When I send a PATCH request to \"http://somedomain.lan/some-api\" with body \"{\"hello\":\"there\"}\"\n\n=item C\u003cThen the page should be cached\u003e\n\n=item C\u003cThen the page should not be cached\u003e\n\n=item C\u003cThen I should be redirected to \"(.+)\"\u003e\n\n=item C\u003cThen I should not be redirected to \"(.+)\"\u003e\n\n=item C\u003cThen the HTTP response header \"(.+)\" should match \"(.*)\"\u003e\n\n=item C\u003cThen the HTTP status code should be \"(.+)\"\u003e\n\n=item C\u003cThen the HTTP status code should not be \"(.+)\"\u003e\n\n=item C\u003cThen the HTTP response header \"(.+)\" should not be there\u003e\n\n=item C\u003cThen the HTTP response header \"(.+)\" should be \"(.+)\"\u003e\n\n=item C\u003cThen the HTTP response header \"(.+)\" should match \"(.+)\"\u003e\n\n=item C\u003cThen the HTTP status line should match \"(.+)\"\u003e\n\n=item C\u003cThen the page should contain \"(.+)\"\u003e\n\n=item C\u003cThen the page should not contain \"(.+)\"\u003e\n\n=item C\u003cThen the server should send a CSRF token\u003e\n\n=item C\u003cThen the page MD5 checksum should be \"(.+)\"\u003e\n\n=item C\u003cThen the page should be a valid JSON document\u003e\n\n=item C\u003cThen the page should validate according to the external script \"(.+)\"\u003e\n\nIn this case, the specified external script, which must be executable,\nwill be invoked with the content of the downloaded document as STDIN stream.\n\nThe script must exit with code zero (e.g. C\u003cexit 0\u003e) if the document is valid.\nAny other exit code will be interpreted as if the document failed validation.\n\n=item C\u003cThen the json document should have a \"(.+)\" key\u003e\n\n=item C\u003cThen the json value for the \"(.+)\" key should not be empty\u003e\n\n=item C\u003cThen the json value for the \"(.+)\" key should be \"(.+)\"\u003e\n\n=item C\u003cThen the json value for the \"(.+)\" key should be (greater|lesser) than \"(.+)\"\u003e\n\n=item C\u003cThen the json value for the \"(.+)\" key should be a timestamp within (\\d+) (hours?|minutes?|seconds?|days?)\u003e\n\n=back\n\n=head1 AUTHOR\n\nCosimo Streppone, C\u003ccosimo@cpan.org\u003e\n\n=head1 LICENSE AND COPYRIGHT\n\nThis code is offered under the Open Source BSD license.\n\n    Copyright (c) 2012-2017, Opera Software. All rights reserved.\n    Copyright (c) 2018, Kahoot! AS. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n=over 4\n\n=item *\n\nRedistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer.\n\n=item *\n\nRedistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n\n=item *\n\nNeither the name of Opera Software, Kahoot! AS nor the names of its contributors\nmay be used to endorse or promote products derived from this software without\nspecific prior written permission.\n\n=back\n\n=head1 DISCLAIMER OF WARRANTY\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcosimo%2Fhttp-cuke","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcosimo%2Fhttp-cuke","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcosimo%2Fhttp-cuke/lists"}