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 <srchulo@cpan.org>

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.

