Skip to content

Instantly share code, notes, and snippets.

@jberger
Last active July 14, 2017 19:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jberger/c24814e21d3fd16e03a1f444e42a3003 to your computer and use it in GitHub Desktop.
Save jberger/c24814e21d3fd16e03a1f444e42a3003 to your computer and use it in GitHub Desktop.
package Mojolicious::Plugin::FileHeaders;
use Mojo::Base 'Mojolicious::Plugin';
use File::MimeInfo::Magic qw(globs mimetype);
use Mojo::File;
use Mojo::Util 'quote';
sub register {
my ($plugin, $app, $config) = @_;
$app->helper(file_headers => \&_file_headers);
}
sub _file_headers {
my $c = shift;
my %opts = @_ == 1 ? %{ $_[0] } : @_;
my $content = $c->res->content;
die 'Cannot add headers to multipart content'
if $content->is_multipart;
my $asset = $content->asset;
my $headers = $c->res->headers;
my $name;
unless ($headers->content_disposition) {
my $disp = $opts{disposition} || 'attachment';
$name = $opts{name} // _name_from_asset($asset);
$disp .= '; filename=' . quote($name) if defined $name;
$headers->content_disposition($disp);
}
unless ($headers->content_type) {
my $type = $opts{type} // _type_from_asset($asset);
$type //= globs($name) if defined $name;
$headers->content_type($type) if defined $type;
}
return $c;
}
sub _name_from_asset {
my $asset = shift || return undef;
return undef unless $asset->is_file;
my $path = $asset->path // return undef;
return Mojo::File->new($path)->basename;
}
sub _type_from_asset {
my $asset = shift || return undef;
my $handle;
if ($asset->is_file) {
return mimetype($asset->path) if defined $asset->path;
$handle = $asset->handle;
} else {
open $handle, '<', \($asset->slurp) or die 'Cannot open scalar to memory asset';
}
return mimetype($handle);
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment