package ExternalCatty;
use strict;
use warnings;
-use Catalyst qw/-Engine=HTTP/;
-our $VERSION = '0.01';
+use Catalyst;
+use IO::Socket::INET;
__PACKAGE__->config( name => 'ExternalCatty' );
__PACKAGE__->setup;
+__PACKAGE__->setup_engine('HTTP');
-sub default : Private {
- my ( $self, $c ) = @_;
- $c->response->content_type('text/html; charset=utf-8');
- $c->response->output( html( 'Root', 'Hello, test ☺!' ) );
-}
-
-# redirect to a redirect
-sub hello: Global {
- my ( $self, $context ) = @_;
- my $where = $context->uri_for('/');
- $context->response->redirect($where);
- return;
-}
-
-sub html {
- my ( $title, $body ) = @_;
- return qq[
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>$title</title>
-</head>
-<body>$body</body>
-</html>
-];
-}
+sub MAX_PORT_TRIES() { 5 }
# The Cat HTTP server background option is useless here :-(
# Thus we have to provide our own background method.
sub background {
my $self = shift;
my $port = shift;
+ $port = $self->assert_or_find_available_port($port);
my $child = fork;
die "Can't fork Cat HTTP server: $!" unless defined $child;
- return $child if $child;
+ return($child, $port) if $child;
if ( $^O !~ /MSWin32/ ) {
require POSIX;
POSIX::setsid() or die "Can't start a new session: $!";
}
- $self->run($port);
+ return($self->run($port), $port);
+}
+
+sub assert_or_find_available_port {
+ my($self, $port) = @_;
+ for my $i (1..MAX_PORT_TRIES) {
+ IO::Socket::INET->new(
+ LocalAddr => 'localhost',
+ LocalPort => $port,
+ Proto => 'tcp'
+ ) and return $port;
+ $port += int(rand 100) + 1;
+ }
+ die q{Can't find an open port to run external server on after }
+ . MAX_PORT_TRIES . q{tries};
}
1;