Catalyst-Plugin-Static-File

 view release on metacpan or  search on metacpan

lib/Catalyst/Plugin/Static/File.pm  view on Meta::CPAN

package Catalyst::Plugin::Static::File;

use v5.14;

# ABSTRACT: Serve a specific static file

use Moose::Role;

use File::Spec;
use File::stat;
use IO::File;
use Plack::MIME;
use Plack::Util;
use Try::Tiny;

use namespace::autoclean;

our $VERSION = 'v0.2.4';


sub serve_static_file {
    my ( $c, $path, $type ) = @_;

    my $res = $c->res;

    my $abs = File::Spec->rel2abs("$path");

    try {

        # Ideally we could let the file open fail when a file does not exist, but this seems to cause the process to
        # exit in a way that try/catch cannot handle on some systems.  We can risk a potential race condition where the
        # file disappears between the existence check and opening: the worst case is that it would have the same effect
        # as not checking for file existence.

        die "No such file or directory" unless -e $abs;

        my $fh = IO::File->new( $abs, "r" ) or die $!;

        binmode($fh);
        Plack::Util::set_io_path( $fh, $abs );
        $res->body($fh);

        $type //= Plack::MIME->mime_type($abs);

        my $headers = $res->headers;
        $headers->content_type("$type");

        my $stat = stat($fh);
        $headers->content_length( $stat->size );
        $headers->last_modified( $stat->mtime );

    }
    catch {

        my $error = $_;
        Catalyst::Exception->throw("Unable to open ${abs} for reading: ${error}");

    };

    return 1;
}


1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Catalyst::Plugin::Static::File - Serve a specific static file

=head1 VERSION

version v0.2.4

=head1 SYNOPSIS

In your Catalyst class:

  use Catalyst qw/
      Static::File
    /;

In a controller method:

  $c->serve_static_file( $absolute_path, $type );

=head1 DESCRIPTION

This plugin provides a simple method for your L<Catalyst> app to send a specific static file.

Unlike L<Catalyst::Plugin::Static::Simple>,

=over

=item *

It only supports serving a single file, not a directory of static files. Use L<Plack::Middleware::Static> if you want to
serve multiple files.

=item *

It assumes that you know what you're doing. If the file does not exist, it will throw an fatal error.



( run in 1.151 second using v1.01-cache-2.11-cpan-39bf76dae61 )