[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/Corion/HTTP-Request-Generator?branch=master&svg=true)](https://ci.appveyor.com/project/Corion/HTTP-Request-Generator)
[![Windows](https://github.com/Corion/HTTP-Request-Generator/workflows/windows/badge.svg)](https://github.com/Corion/HTTP-Request-Generator/actions?query=workflow%3Awindows)
[![MacOS](https://github.com/Corion/HTTP-Request-Generator/workflows/macos/badge.svg)](https://github.com/Corion/HTTP-Request-Generator/actions?query=workflow%3Amacos)
[![Linux](https://github.com/Corion/HTTP-Request-Generator/workflows/linux/badge.svg)](https://github.com/Corion/HTTP-Request-Generator/actions?query=workflow%3Alinux)

# NAME

HTTP::Request::Generator - generate HTTP requests

# SYNOPSIS

    use HTTP::Request::Generator 'generate_requests';

    @requests = generate_requests(
        method  => 'GET',
        pattern => 'https://example.com/{bar,foo,gallery}/[00..99].html',
    );

    # generates 300 requests from
    #     https://example.com/bar/00.html to
    #     https://example.com/gallery/99.html

    @requests = generate_requests(
        method => 'POST',
        host   => ['example.com','www.example.com'],
        path   => '/profiles/:name',
        url_params => {
            name => ['Corion','Co-Rion'],
        },
        query_params => {
            stars => [2,3],
        },
        body_params => {
            comment => ['Some comment', 'Another comment, A++'],
        },
        headers => [
            {
                "Content-Type" => 'text/plain; encoding=UTF-8',
                Cookie => 'my_session_id',
            },
            {
                "Content-Type" => 'text/plain; encoding=Latin-1',
                Cookie => 'my_session_id',
            },
        ],
    );
    # Generates 32 requests out of the combinations

    for my $req (@requests) {
        $ua->request( $req );
    };

## `expand_curl_pattern`

    my %res = expand_curl_pattern( 'https://' );
    #

Expands a curl-style pattern to a pattern using positional placeholders.
See the `curl` documentation on the patterns.

## `generate_requests( %options )`

    my $g = generate_requests(
        url => '/profiles/:name',
        url_params => ['Mark','John'],
        wrap => sub {
            my( $req ) = @_;
            # Fix up some values
            $req->{headers}->{'Content-Length'} = 666;
            return $req;
        },
    );
    while( my $r = $g->()) {
        send_request( $r );
    };

This function creates data structures that are suitable for sending off
a mass of similar but different HTTP requests. All array references are expanded
into the cartesian product of their contents. The above example would create
two requests:

      url => '/profiles/Mark,
      url => '/profiles/John',

`generate_requests` returns an iterator in scalar context. In list context, it
returns the complete list of requests:

    my @requests = generate_requests(
        url => '/profiles/:name',
        url_params => ['Mark','John'],
        wrap => sub {
            my( $req ) = @_;
            # Fix up some values
            $req->{headers}->{'Content-Length'} = 666;
            return $req;
        },
    );
    for my $r (@requests) {
        send_request( $r );
    };

Note that returning a list instead of the iterator will use up quite some memory
quickly, as the list will be the cartesian product of the input parameters.

There are helper functions
that will turn that data into a data structure suitable for your HTTP framework
of choice.

    {
      method => 'GET',
      url => '/profiles/Mark',
      scheme => 'http',
      port => 80,
      headers => {},
      body_params => {},
      query_params => {},
    }

As a shorthand for creating lists, you can use the `pattern` option, which
will expand a string into a set of requests. `{}` will expand into alternatives
while `[xx..yy]` will expand into the range `xx` to `yy`. Note that these
lists will be expanded in memory.

### Options

- **pattern**

        pattern => 'https://example.{com,org,net}/page_[00..99].html',

    Generate URLs from this pattern instead of `query_params`, `url_params`
    and `url`.

- **url**

    URL template to use.

- **url\_params**

    Parameters to replace in the `url` template.

- **body\_params**

    Parameters to replace in the POST body.

- **query\_params**

    Parameters to replace in the GET request.

- **host**

    Hostname(s) to use.

- **port**

    Port(s) to use.

- **headers**

    Headers to use. Currently, no templates are generated for the headers. You have
    to specify complete sets of headers for each alternative.

- **limit**

    Limit the number of requests generated.

## `as_http_request`

    generate_requests(
        method => 'POST',
        url    => '/feedback/:item',
        wrap => \&HTTP::Request::Generator::as_http_request,
    )

Converts the request data to a [HTTP::Request](https://metacpan.org/pod/HTTP::Request) object.

## `as_dancer`

    generate_requests(
        method => 'POST',
        url    => '/feedback/:item',
        wrap => \&HTTP::Request::Generator::as_dancer,
    )

Converts the request data to a [Dancer::Request](https://metacpan.org/pod/Dancer::Request) object.

During the creation of Dancer::Request objects, `%ENV` will be empty except
for `$ENV{TMP}` and `$ENV{TEMP}`.

This function needs and dynamically loads the following modules:

[Dancer::Request](https://metacpan.org/pod/Dancer::Request)

[HTTP::Request](https://metacpan.org/pod/HTTP::Request)

## `as_plack`

    generate_requests(
        method => 'POST',
        url    => '/feedback/:item',
        wrap => \&HTTP::Request::Generator::as_plack,
    )

Converts the request data to a [Plack::Request](https://metacpan.org/pod/Plack::Request) object.

During the creation of Plack::Request objects, `%ENV` will be empty except
for `$ENV{TMP}` and `$ENV{TEMP}`.

This function needs and dynamically loads the following modules:

[Plack::Request](https://metacpan.org/pod/Plack::Request)

[HTTP::Headers](https://metacpan.org/pod/HTTP::Headers)

[Hash::MultiValue](https://metacpan.org/pod/Hash::MultiValue)

# SEE ALSO

[The Curl Manpage](https://curl.haxx.se/docs/manpage.html) for the pattern syntax

# REPOSITORY

The public repository of this module is
[https://github.com/Corion/HTTP-Request-Generator](https://github.com/Corion/HTTP-Request-Generator).

# SUPPORT

The public support forum of this module is [https://perlmonks.org/](https://perlmonks.org/).

# BUG TRACKER

Please report bugs in this module via the RT CPAN bug queue at
[https://rt.cpan.org/Public/Dist/Display.html?Name=HTTP-Request-Generator](https://rt.cpan.org/Public/Dist/Display.html?Name=HTTP-Request-Generator)
or via mail to [HTTP-Request-Generator-Bugs@rt.cpan.org](mailto:HTTP-Request-Generator-Bugs@rt.cpan.org).

# AUTHOR

Max Maischein `corion@cpan.org`

# COPYRIGHT (c)

Copyright 2017-2019 by Max Maischein `corion@cpan.org`.

# LICENSE

This module is released under the same terms as Perl itself.