Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Use alternatives instead of Plack::MIME #361

Merged
merged 3 commits into from

2 participants

@pstadt

I am a little unhappy with Plack::MIME content-types, especially when using Plack::Middleware::Static. Sometimes I want a improved MIME-type detection, like File::MimeInfo::Magic.

I added a content_type attribute to Plack::Middleware::Static, which can be a sub like
content_type => sub { mimetype($_[0]) },

The content_type is now handed to Plack::App::File, which is extended to evaluate the CODE reference if content_type is one. For the primary use of Plack::App::File it might be not necessary to handle code references for content_type, but I think it is the best place to deal with it and to provide this feature to other components reusing Plack::App::File.

@pstadt pstadt add handling of content_type code reference in App/File (readable cha…
…nge)

add attribute content_type to Middleware/Static which can be an callback
9036e90
@miyagawa
Owner

Can you add a documentation and test about it?

pstadt added some commits
@pstadt pstadt provide tests for content_type callback for Plack::App::File and Plac…
…k::Middleware::Static.

Using Plack::MIME with added mimetype and modify the returned mimetype to make sure it is not the Plack::MIME fallback which was called. This was done not to have a dependency to a different mimetype checker.
4ec9e77
@pstadt pstadt Documentation update c0ddf94
@miyagawa miyagawa merged commit 7b1ee71 into plack:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 4, 2013
  1. @pstadt

    add handling of content_type code reference in App/File (readable cha…

    pstadt authored
    …nge)
    
    add attribute content_type to Middleware/Static which can be an callback
Commits on Jan 5, 2013
  1. @pstadt

    provide tests for content_type callback for Plack::App::File and Plac…

    pstadt authored
    …k::Middleware::Static.
    
    Using Plack::MIME with added mimetype and modify the returned mimetype to make sure it is not the Plack::MIME fallback which was called. This was done not to have a dependency to a different mimetype checker.
  2. @pstadt

    Documentation update

    pstadt authored
This page is out of date. Refresh to see the latest.
View
6 lib/Plack/App/File.pm
@@ -86,6 +86,10 @@ sub serve_path {
my $content_type = $self->content_type || Plack::MIME->mime_type($file)
|| 'text/plain';
+ if ("CODE" eq ref $content_type) {
+ $content_type = $content_type->($file);
+ }
+
if ($content_type =~ m!^text/!) {
$content_type .= "; charset=" . ($self->encoding || "utf-8");
}
@@ -174,6 +178,8 @@ Set the file encoding for text files. Defaults to C<utf-8>.
Set the file content type. If not set L<Plack::MIME> will try to detect it
based on the file extension or fall back to C<text/plain>.
+Can be set to a callback which should work on $_[0] to check full path file
+name.
=back
View
15 lib/Plack/Middleware/Static.pm
@@ -4,7 +4,7 @@ use warnings;
use parent qw/Plack::Middleware/;
use Plack::App::File;
-use Plack::Util::Accessor qw( path root encoding pass_through );
+use Plack::Util::Accessor qw( path root encoding pass_through content_type );
sub call {
my $self = shift;
@@ -29,7 +29,7 @@ sub _handle_static {
return unless $matched;
}
- $self->{file} ||= Plack::App::File->new({ root => $self->root || '.', encoding => $self->encoding });
+ $self->{file} ||= Plack::App::File->new({ root => $self->root || '.', encoding => $self->encoding, content_type => $self->content_type });
local $env->{PATH_INFO} = $path; # rewrite PATH
return $self->{file}->call($env);
}
@@ -67,7 +67,7 @@ If the requested document is not within the C<root> or the file is there but
not readable, this middleware will return a 403 Forbidden response.
The content type returned will be determined from the file extension by using
-L<Plack::MIME>.
+L<Plack::MIME> or using C<content_type>.
=head1 CONFIGURATIONS
@@ -111,6 +111,15 @@ When this option is set to a true value, then this middleware will never
return a 404 if it cannot find a matching file. Instead, it will simply pass
the request on to the application it is wrapping.
+=item content_type
+
+The C<content_type> option can be used to provide access to a different MIME
+database than L<Plack::MIME>.
+L<Plack::MIME> works fast and good for a list of well known file endings,
+but if you need a more accurate content based checking you can use modules
+like L<File::MimeInfo> or L<File::MMagic> for example.
+The callback should work on $_[0] which is the filename of the file.
+
=back
=head1 AUTHOR
View
1  t/Plack-Middleware/static.foo
@@ -0,0 +1 @@
+bar
View
10 t/Plack-Middleware/static.t
@@ -11,6 +11,8 @@ use Plack::Test;
my $base = cwd;
+Plack::MIME->add_type(".foo" => "text/x-fooo");
+
my $handler = builder {
enable "Plack::Middleware::Static",
path => sub { s!^/share/!!}, root => "share";
@@ -18,6 +20,9 @@ my $handler = builder {
path => sub { s!^/share-pass/!!}, root => "share", pass_through => 1;
enable "Plack::Middleware::Static",
path => qr{\.(t|PL|txt)$}i, root => '.';
+ enable "Plack::Middleware::Static",
+ path => qr{\.foo$}i, root => '.',
+ content_type => sub { substr Plack::MIME->mime_type($_[0]),0,-1 } ;
sub {
[200, ['Content-Type' => 'text/plain', 'Content-Length' => 2], ['ok']]
};
@@ -70,6 +75,11 @@ my %test = (
my($ct, $charset) = $res->content_type;
is $charset, 'charset=utf-8';
}
+
+ {
+ my $res = $cb->(GET "http://localhost/t/Plack-Middleware/static.foo");
+ is $res->content_type, 'text/x-foo';
+ }
},
app => $handler,
);
Something went wrong with that request. Please try again.