The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.


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


  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};



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.


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

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

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


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:



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.


This returns the URI where you can contact the server. This url is valid until the $server goes out of scope or you call


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


This returns the URI object of the server URL. Use "$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.


This stops the server process by requesting a special url.


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


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.


  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)

      <script>alert("Hello World");</script>

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 );
    $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.


None by default.


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

Copyright (C) 2003-2024 Max Maischein


Max Maischein, <>

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