NAME

   Plack::App::HostMap - Map multiple Plack apps by host

SYNOPSIS

       use Plack::App::HostMap;

       my $foo_app = sub { ... };
       my $bar_app = sub { ... };
       my $baz_app = sub { ... };
       my $foo_bar_app= sub { ... };

       my $host_map = Plack::App::HostMap->new;

       #map different hosts to different apps
       $host_map->map("www.foo.com" => $foo_app);
       $host_map->map("bar.com" => $bar_app);
       $host_map->map("test.baz.com" => $baz_app);

       #map multiple hosts to same app conveniently
       $host_map->map(["www.foo.com", "foo.com", "beta.foo.com"] => $foo_app);

       #map all subdomains of a host to an app
       $host_map->map("*.foo.com" => $foo_app); #will match www.foo.com, foo.com, beta.foo.com, test.foo.com, beta.test.foo.com, etc...

       #map multilevel subdomains of a host to an app
       $host_map->map("*.foo.bar.com" => $foo_bar_app); #will match test.foo.bar.com, beta.foo.bar.com, beta.test.foo.bar.com, etc...

       my $app = $host_map->to_app;


DESCRIPTION

   Plack::App::HostMap is a PSGI application that can dispatch multiple
   applications based on host name (a.k.a "virtual hosting").
   Plack::App::URLMap can also dispatch applications based on host name.
   However, it also more versatile and can dispatch applications based on
   URL paths. Because of this, if you were to use Plack::App::URLMap to
   map applications based on host name it would take linear time to find
   your app. So if you had N host name entries to map to apps, you might
   have to search through N mappings before you find the right one.
   Because Plack::App::HostMap is simpler and only dispatches based on
   host name, it can be much more efficient for this use case.
   Plack::App::HostMap uses a hash to look up apps by host name, and thus
   instead of a linear time lookup is constant time. So if you had 2 apps
   to dispatch by host name or 10,000, there shouldn't be a difference in
   terms of performance since hashes provide constant time lookup.

METHODS

map

       $host_map->map("www.foo.com" => $foo_app);
       $host_map->map("bar.com" => $bar_app);


   Maps a host name to a PSGI application. You can also map multiple host
   names to one application at once by providing an array reference:

       $host_map->map(["www.foo.com", "foo.com", "beta.foo.com"] => $foo_app);

   If you need all subdomains of a host name to map to the same app,
   instead of listing them all out you can do so like this:

       $host_map->map("*.foo.com" => $foo_app); #will match www.foo.com, foo.com, beta.foo.com, test.foo.com, beta.test.foo.com, etc...

   This will map any subdomain of foo.com to $foo_app. This way you can
   point new subdomains at your app without having to update your
   mappings. Also, Plack::App::HostMap will always match the most exact
   rule. For example, if you have the rules:

       $host_map->map("foo.com" => $foo_app);
       $host_map->map("*.foo.com" => $generic_foo_app);

   And you request foo.com, it will match the $foo_app, not the
   $generic_foo_app since there is an explicit rule for foo.com. Also, if
   Plack::App::HostMap cannot find an exact match for a host,
   Plack::App::HostMap will always match the first rule it finds. For
   instance, if you have these two rules:

       $host_map->map("*.beta.foo.com" => $beta_foo_app);
       $host_map->map("*.foo.com" => $foo_app);

   And you request beta.foo.com, it will match the $beta_foo_app, not the
   $foo_app because Plack::App::HostMap will find beta.foo.com before
   foo.com when looking for a match.

mount

   Alias for map.

to_app

     my $handler = $host_map->to_app;


   Returns the PSGI application code reference. Note that the
   Plack::App::HostMap object is callable (by overloading the code
   dereference), so returning the object itself as a PSGI application
   should also work.

no_cache

       $host_map->no_cache(1);

       #or
       my $host_map = Plack::App::HostMap->new(no_cache => 1);

   This method only applies if you are using the *. syntax. By default,
   Plack::App::HostMap will cache the corresponding mappings for a domain.
   For instance, if you have:

       #beta.foo.com maps to *.foo.com
       beta.foo.com -> *.foo.com

   Then after the first time that a url with the host beta.foo.com is
   requested, the domain beta.foo.com will be stored in a hash as a key
   with its value being *.foo.com, to specify that that's what it maps to.
   If you are using the *. syntax, it is strongly recommended that you do
   not turn this off because it could speed things up a lot since you
   avoid Domain::PublicSuffix's parsing logic, as well as some regex and
   logic that Plack::App::HostMap does to map the host to the right rule.
   However, one particular reason why you might want to disable caching
   would be if you were pointing A LOT of domains at your app. For
   instance, if you have the rule:

       $host_map->map("*.foo.com" => $foo_app);

   And you request many urls with different foo.com subdomains. This would
   take up a lot of memory since each host you requested to your app would
   be stored as a key in a hash. Keep in mind this would need to be very
   many, since even 1,000 domains wouldn't take up much memory in a perl
   hash. Another possible reason to disable this would be that someone
   could potentially use it to crash your application/server. If you had
   this rule:

       $host_map->map("*.foo.com" => $foo_app);

   And someone were to request many foo.com domains:

       test.foo.com
       test1.foo.com
       test2.foo.com
       ...

   Then each one would be cached as a key with its value being foo.com. If
   you are really worried about someone crashing your app, you could set
   "no_cache" to 1, or instead of using the *. syntax you could list out
   each individual host. Note: This only applies if you are using the *.
   syntax. If you do not use the *. syntax, the hash that is used for
   caching is never even used. Also, in order to avoid letting the memory
   of your app grow uncontrollably, Plack::App::HostMap only caches hosts
   that actually map to a rule that you set. This way even if caching is
   on, someone can not make tons of requests with different hosts to your
   server and crash it.

PERFORMANCE

   Note: This only applies if "no_cache" is set to 1. As mentioned in the
   DESCRIPTION, Plack::App::HostMap should perform much more efficiently
   than Plack::App::URLMap when being used for host names. One caveat
   would be with the *. syntax that can be used with map. If you have even
   just one mapping with a *. in it:

       $host_map->map("*.foo.com" => $foo_app);

   Then on every request where the host is not an exact match for a rule
   (meaning that the host either matches a *. syntax rule or no rule),
   Plack::App::HostMap must call Domain::PublicSuffix's get_root_domain
   subroutine to parse out the root domain of the host. I can't imagine
   that this is very costly, but maybe if you are receiving a lot of
   requests this could make a difference. Also, Plack::App::HostMap does
   some additional logic to map your hosts. If you find that it is the
   case that it is affecting your performance, instead of using the *.
   syntax you could list out each individual possibility:

       $host_map->map("beta.foo.com" => $foo_app);
       $host_map->map("www.foo.com" => $foo_app);
       $host_map->map("foo.com" => $foo_app);

       #or
       $host_map->map(["beta.foo.com", "www.foo.com", "foo.com"] => $foo_app);

   And the result would be that lookup is back to constant time. However,
   you might never see a performance hit and it might be more worth it to
   use the convenient syntax.

AUTHOR

   Adam Hopkins <[email protected]>

COPYRIGHT

   Copyright 2019- Adam Hopkins

LICENSE

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