[![Travis Build Status](https://travis-ci.org/Corion/Test-HTTP-LocalServer.svg?branch=master)](https://travis-ci.org/Corion/Test-HTTP-LocalServer)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/Corion/Test-HTTP-LocalServer?branch=master&svg=true)](https://ci.appveyor.com/project/Corion/Test-HTTP-LocalServer)

# NAME

Test::HTTP::LocalServer - spawn a local HTTP server for testing

# SYNOPSIS

    use HTTP::Tiny;
    my $server = Test::HTTP::LocalServer->spawn(
        request_pause => 1, # wait one second before accepting the next request
    );

    my $res = HTTP::Tiny->new->get( $server->url );
    print $res->{content};

    $server->stop;

# DESCRIPTION

This module implements a tiny web server suitable for running "live" tests
of HTTP clients against it. It also takes care of cleaning `%ENV` from settings
that influence the use of a local proxy etc.

Use this web server if you write an HTTP client and want to exercise its
behaviour in your test suite without talking to the outside world.

# METHODS

## `Test::HTTP::LocalServer->spawn %ARGS`

    my $server = Test::HTTP::LocalServer->spawn;

This spawns a new HTTP server. The server will stay running until

    $server->stop

is called. Ideally, you explicitly call `->stop` or use

    undef $server

before the main program ends so that the program exit code reflects the
real exit code and not the chlid exit code.

Valid arguments are :

- `html =>` scalar containing the page to be served

    If this is not specified, an informative default page will be used.

- `request_pause =>` number of seconds to sleep before accepting the next
request

    If your system is slow or needs to wait some time before a socket connection
    is ready again, use this parameter to make the server wait a bit before
    handling the next connection.

- `file =>` filename containing the page to be served
- `debug => 1` to make the spawned server output debug information
- `eval =>` string that will get evaluated per request in the server

    Try to avoid characters that are special to the shell, especially quotes.
    A good idea for a slow server would be

        eval => sleep+10

All served HTML will have the first %s replaced by the current location.

The following entries will be removed from `%ENV` when making a request:

    HTTP_PROXY
    http_proxy
    HTTP_PROXY_ALL
    http_proxy_all
    HTTPS_PROXY
    https_proxy
    CGI_HTTP_PROXY
    ALL_PROXY
    all_proxy

## `$server->port`

This returns the port of the current server. As new instances
will most likely run under a different port, this is convenient
if you need to compare results from two runs.

## `$server->url`

This returns the [URI](https://metacpan.org/pod/URI) where you can contact the server. This url
is valid until the `$server` goes out of scope or you call

    $server->stop;

The returned object is a copy that you can modify at your leisure.

## `$server->server_url`

This returns the [URI](https://metacpan.org/pod/URI) object of the server URL. Use ["$server->url"](#server-url) instead.
Use this object if you want to modify the hostname or other properties of the
server object.

Consider this basically an emergency accessor. In about every case,
using `->url()` does what you want.

## `$server->stop`

This stops the server process by requesting a special
url.

## `$server->kill`

This kills the server process via `kill`. The log
cannot be retrieved then.

## `$server->get_log`

This returns the
output of the server process. This output will be a list of
all requests made to the server concatenated together
as a string.

## `$server->local`

    my $url = $server->local('foo.html');
    # file:///.../foo.html

Returns an URL for a local file which will be read and served
by the webserver. The filename must
be a relative filename relative to the location of the current
program.

# URLs implemented by the server

## arbitrary content `$server->content($html)`

    $server->content(<<'HTML');
        <script>alert("Hello World");</script>
    HTML

The URL will contain the HTML as supplied. This is convenient for supplying
Javascript or special URL to your user agent.

## download `$server->download($name)`

This URL will send a file with a `Content-Disposition` header and indicate
the suggested filename as passed in.

## 302 redirect `$server->redirect($target)`

This URL will issue a redirect to `$target`. No special care is taken
towards URL-decoding `$target` as not to complicate the server code.
You need to be wary about issuing requests with escaped URL parameters.

## 401 basic authentication challenge `$server->basic_auth($user, $pass)`

This URL will issue a 401 basic authentication challenge. The expected user
and password are encoded in the URL.

    my $challenge_url = $server->basic_auth('foo','secret');
    my $wrong_pw = URI->new( $challenge_url );
    $wrong_pw->userinfo('foo:hunter2');
    $res = HTTP::Tiny->new->get($wrong_pw);
    is $res->{status}, 401, "We get the challenge with a wrong user/password";

## 404 error `$server->error_notfound($target)`

This URL will response with status code 404.

## Timeout `$server->error_timeout($seconds)`

This URL will send a 599 error after `$seconds` seconds.

## Timeout+close `$server->error_close($seconds)`

This URL will send nothing and close the connection after `$seconds` seconds.

## Error in response content `$server->error_after_headers`

This URL will send headers for a successful response but will close the
socket with an error after 2 blocks of 16 spaces have been sent.

## Chunked response `$server->chunked`

This URL will return 5 blocks of 16 spaces at a rate of one block per second
in a chunked response.

## Surprisingly large bzip2 encoded response `$server->bzip2`

This URL will return a short HTTP response that expands to 16M body.

## Surprisingly large gzip encoded response `$server->gzip`

This URL will return a short HTTP response that expands to 16M body.

## Other URLs

All other URLs will echo back the cookies and query parameters.

# EXPORT

None by default.

# COPYRIGHT AND LICENSE

This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

Copyright (C) 2003-2021 Max Maischein

# AUTHOR

Max Maischein, <corion@cpan.org>

Please contact me if you find bugs or otherwise improve the module. More tests
are also very welcome !

# SEE ALSO

[WWW::Mechanize](https://metacpan.org/pod/WWW%3A%3AMechanize),[WWW::Mechanize::Shell](https://metacpan.org/pod/WWW%3A%3AMechanize%3A%3AShell),[WWW::Mechanize::Firefox](https://metacpan.org/pod/WWW%3A%3AMechanize%3A%3AFirefox)