Hack mason_hendler.fcgi to show images correctly

mason_handler.fcgi will currently try to parse and interpret every
file it’s asked to request sets the content type to text/html no
matter what. That doesn’t work too well with, for example, rt.jpg
:-).

The following patch fixes that, with the added feature that it looks
at the mime.types and Apache configuration file to find out what types
are currently supported and what extensions they have.

diff -uNr rt-2-0-8/bin/mason_handler.fcgi rt-2-0-8.hacked/bin/mason_handler.fcgi
— rt-2-0-8/bin/mason_handler.fcgi Mon Sep 10 08:11:29 2001
+++ rt-2-0-8.hacked/bin/mason_handler.fcgi Thu Oct 18 12:33:45 2001
@@ -37,6 +37,7 @@

#This drags in RT’s config.pm
use config;
+use mime_types;
use Carp;

{
@@ -115,8 +116,6 @@

Response loop

while ($RT::Mason::cgi = new CGI::Fast) {

  • $HTML::Mason::Commands::ContentType = ‘text/html’;

    This routine comes from ApacheHandler.pm:

    my (%args, $cookie);
    foreach my $key ( $cgi->param ) {
    @@ -195,12 +194,25 @@

    }}}

    $output = ‘’;

  • eval {

  • ($HTML::Mason::Commands::ContentType, my $dummy) = RT::by_suffix($comp);
  • if ($HTML::Mason::Commands::ContentType !~ m|^text/|io) {
  • my ($outlen,$readlen);
  • open FILE,"<$RT::MasonLocalComponentRoot$comp" ||
  •   open FILE,"<$RT::MasonComponentRoot$comp";
    
  • while ($readlen = read FILE,$output,8192,$outlen) {
  •   $outlen += $readlen;
    
  • }
  • close FILE;
  • } else {
  • eval {
    my $status = $interp->exec($comp, %args);
  • };
  • };
  • if ($@) {
  • $output = “
    $@
    ”;
  • if ($@) {

  •   $output = "<PRE>$@</PRE>";
    
  • }
    }

    print “Content-Type: $HTML::Mason::Commands::ContentType\r\n”;
    diff -uNr rt-2-0-8/etc/config.pm rt-2-0-8.hacked/etc/config.pm
    — rt-2-0-8/etc/config.pm Wed Sep 19 22:49:25 2001
    +++ rt-2-0-8.hacked/etc/config.pm Thu Oct 18 12:30:16 2001
    @@ -319,6 +319,11 @@

via the web interface)

$MasonSessionDir = “!!MASON_SESSION_PATH!!”;

+# RT needs to know the files to search for MIME types in, and what kind of
+# file it is. The currently defined types are “ApacheConf” and “MimeTypes”
+%MIMETypeFiles = ("/etc/apache/httpd.conf" => ApacheConf,

  •     "/etc/mime.types" => MimeTypes);
    

#This is from tobias’ prototype web search UI. it may stay and it may go.
diff -uNr rt-2-0-8/etc/mime_types.pm rt-2-0-8.hacked/etc/mime_types.pm
— rt-2-0-8/etc/mime_types.pm Thu Jan 1 01:00:00 1970
+++ rt-2-0-8.hacked/etc/mime_types.pm Thu Oct 18 12:34:25 2001
@@ -0,0 +1,85 @@
+package RT;
+# This works like MIME::Types, but loads the table from apache configuration
+# and the mime.types files.
+my %mime_types = ();
+print STDERR “DEBUG: MIMETypeFiles is empty!\n” if ! %MIMETypeFiles;
+foreach (keys %RT::MIMETypeFiles) {

  • open FILE,"<$_" || next;
  • print STDERR “DEBUG: Opened $_\n”;
  • if ($RT::MIMETypeFiles{$_} eq “ApacheConf”) {
  • while() {
  •   if (/\s*AddType\s+/) {
    
  •   s/\s*\#.*$//;
    
  •   my ($type,@extensions) = split(/\s+/,$');
    
  •   foreach (@extensions) {
    
  •       my $extension = $_;
    
  •       $extension =~ s/^\.//;
    
  •       $mime_types{$extension} = [ $type, '8bit' ];
    
  •   }
    
  •   }
    
  • }
  • } elsif ($RT::MIMETypeFiles{$_} eq “MimeTypes”) {
  • while() {
  •   s/\s*\#.*$//;
    
  •   next if /^\s*$/;
    
  •   my ($type,@extensions) = split(/\s+/,$_);
    
  •   foreach (@extensions) {
    
  •   $mime_types{$_} = [ $type, '8bit' ];
    
  •   }
    
  • }
  • } else {
  • warn “I have no idea what kind of file “,$RT::MIMETypeFiles{$}," is. Skipping ",$,”…\n”;
  • }
  • close FILE;
    +}
    +sub by_suffix {
  • my ($arg) = @_;
  • $arg ||= “”;
  • Look for a suffix on the file name

  • If there isn’t one, assume the argument is the suffix itself

  • my ($suffix) = $arg =~ / .(\w+)$ /x;
  • $suffix = $arg unless defined($suffix);
  • my $rv = $mime_types{lc($suffix)};
  • if (defined($rv)) {
  •   return @$rv;
    
  • } else {
  •   return ();
    
  • }
    +}
    +sub by_mediatype {
  • my ($type) = @_;
  • my ($key, $aref, $regexp, @rv);
  • @rv = ();
  • $type = lc($type);
  • if ($type =~ m#/#) {
  •   $regexp = "^${type}\$";
    
  • } else {
  •   $regexp = $type;
    
  • }
  • while (($key, $aref) = each %mime_types) {
  •   if ($aref->[0] =~ /$regexp/) {
    
  •   	push(@rv, [$key, $aref->[0], $aref->[1]]);
    
  •   }
    
  • }
  • return @rv;
    +}
    +1;

Richard Levitte \ Spannv�gen 38, II \ LeViMS@stacken.kth.se
Redakteur@Stacken \ S-168 35 BROMMA \ T: +46-8-26 52 47
\ SWEDEN \ or +46-733-72 88 11
Procurator Odiosus Ex Infernis – poei@bofh.se
Member of the OpenSSL development team: http://www.openssl.org/
Software Engineer, GemPlus: http://www.gemplus.com/

Unsolicited commercial email is subject to an archival fee of $400.
See http://www.stacken.kth.se/~levitte/mail/ for more info.

nod I’ve actually been in the process of going the other way with this one,
moving everything that’s not actually supposed to be parsed to URLs that
don’t have to be processed by the fastcgi handler. It gets somewhat
better performance (since the server can dtrt with caching images)
and doesn’t add the complexity of having to parse mime types files, etc.

Does that sound like it makes sense?

-jOn Thu, Oct 18, 2001 at 12:42:47PM +0200, Richard Levitte - VMS Whacker wrote:

mason_handler.fcgi will currently try to parse and interpret every
file it’s asked to request sets the content type to text/html no
matter what. That doesn’t work too well with, for example, rt.jpg
:-).

The following patch fixes that, with the added feature that it looks
at the mime.types and Apache configuration file to find out what types
are currently supported and what extensions they have.

diff -uNr rt-2-0-8/bin/mason_handler.fcgi rt-2-0-8.hacked/bin/mason_handler.fcgi
— rt-2-0-8/bin/mason_handler.fcgi Mon Sep 10 08:11:29 2001
+++ rt-2-0-8.hacked/bin/mason_handler.fcgi Thu Oct 18 12:33:45 2001
@@ -37,6 +37,7 @@

#This drags in RT’s config.pm
use config;
+use mime_types;
use Carp;

{
@@ -115,8 +116,6 @@

Response loop

while ($RT::Mason::cgi = new CGI::Fast) {

  • $HTML::Mason::Commands::ContentType = ‘text/html’;

  • This routine comes from ApacheHandler.pm:

    my (%args, $cookie);
    foreach my $key ( $cgi->param ) {
    @@ -195,12 +194,25 @@

    }}}

    $output = ‘’;

  • eval {

  • ($HTML::Mason::Commands::ContentType, my $dummy) = RT::by_suffix($comp);
  • if ($HTML::Mason::Commands::ContentType !~ m|^text/|io) {
  • my ($outlen,$readlen);
  • open FILE,"<$RT::MasonLocalComponentRoot$comp" ||
  • open FILE,"<$RT::MasonComponentRoot$comp";
    
  • while ($readlen = read FILE,$output,8192,$outlen) {
  • $outlen += $readlen;
    
  • }
  • close FILE;
  • } else {
  • eval {
    my $status = $interp->exec($comp, %args);
  • };
  • };
  • if ($@) {
  • $output = “
    $@
    ”;
  • if ($@) {

  • $output = "<PRE>$@</PRE>";
    
  • }
    }

    print “Content-Type: $HTML::Mason::Commands::ContentType\r\n”;
    diff -uNr rt-2-0-8/etc/config.pm rt-2-0-8.hacked/etc/config.pm
    — rt-2-0-8/etc/config.pm Wed Sep 19 22:49:25 2001
    +++ rt-2-0-8.hacked/etc/config.pm Thu Oct 18 12:30:16 2001
    @@ -319,6 +319,11 @@

via the web interface)

$MasonSessionDir = “!!MASON_SESSION_PATH!!”;

+# RT needs to know the files to search for MIME types in, and what kind of
+# file it is. The currently defined types are “ApacheConf” and “MimeTypes”
+
+%MIMETypeFiles = ("/etc/apache/httpd.conf" => ApacheConf,

  •   "/etc/mime.types" => MimeTypes);
    

#This is from tobias’ prototype web search UI. it may stay and it may go.
diff -uNr rt-2-0-8/etc/mime_types.pm rt-2-0-8.hacked/etc/mime_types.pm
— rt-2-0-8/etc/mime_types.pm Thu Jan 1 01:00:00 1970
+++ rt-2-0-8.hacked/etc/mime_types.pm Thu Oct 18 12:34:25 2001
@@ -0,0 +1,85 @@
+package RT;
+
+# This works like MIME::Types, but loads the table from apache configuration
+# and the mime.types files.
+
+my %mime_types = ();
+
+print STDERR “DEBUG: MIMETypeFiles is empty!\n” if ! %MIMETypeFiles;
+
+foreach (keys %RT::MIMETypeFiles) {

  • open FILE,"<$_" || next;
  • print STDERR “DEBUG: Opened $_\n”;
  • if ($RT::MIMETypeFiles{$_} eq “ApacheConf”) {
  • while() {
  • if (/\s*AddType\s+/) {
    
  • s/\s*\#.*$//;
    
  • my ($type,@extensions) = split(/\s+/,$');
    
  • foreach (@extensions) {
    
  •     my $extension = $_;
    
  •     $extension =~ s/^\.//;
    
  •     $mime_types{$extension} = [ $type, '8bit' ];
    
  • }
    
  • }
    
  • }
  • } elsif ($RT::MIMETypeFiles{$_} eq “MimeTypes”) {
  • while() {
  • s/\s*\#.*$//;
    
  • next if /^\s*$/;
    
  • my ($type,@extensions) = split(/\s+/,$_);
    
  • foreach (@extensions) {
    
  • $mime_types{$_} = [ $type, '8bit' ];
    
  • }
    
  • }
  • } else {
  • warn “I have no idea what kind of file “,$RT::MIMETypeFiles{$}," is. Skipping ",$,”…\n”;
  • }
  • close FILE;
    +}

+sub by_suffix {
+

  • my ($arg) = @_;
  • $arg ||= “”;
  • Look for a suffix on the file name

  • If there isn’t one, assume the argument is the suffix itself

  • my ($suffix) = $arg =~ / .(\w+)$ /x;
  • $suffix = $arg unless defined($suffix);
  • my $rv = $mime_types{lc($suffix)};
  • if (defined($rv)) {
  • return @$rv;
    
  • } else {
  • return ();
    
  • }
    +}

+sub by_mediatype {
+

  • my ($type) = @_;
  • my ($key, $aref, $regexp, @rv);
  • @rv = ();
  • $type = lc($type);
  • if ($type =~ m#/#) {
  • $regexp = "^${type}\$";
    
  • } else {
  • $regexp = $type;
    
  • }
  • while (($key, $aref) = each %mime_types) {
  • if ($aref->[0] =~ /$regexp/) {
    
  • 	push(@rv, [$key, $aref->[0], $aref->[1]]);
    
  • }
    
  • }
  • return @rv;
    +}

+1;


Richard Levitte \ Spannvägen 38, II \ LeViMS@stacken.kth.se
Redakteur@Stacken \ S-168 35 BROMMA \ T: +46-8-26 52 47
\ SWEDEN \ or +46-733-72 88 11
Procurator Odiosus Ex Infernis – poei@bofh.se
Member of the OpenSSL development team: http://www.openssl.org/
Software Engineer, GemPlus: http://www.gemplus.com/

Unsolicited commercial email is subject to an archival fee of $400.
See http://www.stacken.kth.se/~levitte/mail/ for more info.


rt-devel mailing list
rt-devel@lists.fsck.com
http://lists.fsck.com/mailman/listinfo/rt-devel

http://www.bestpractical.com/products/rt – Trouble Ticketing. Free.

jesse> nod I’ve actually been in the process of going the other way with this one,
jesse> moving everything that’s not actually supposed to be parsed to URLs that
jesse> don’t have to be processed by the fastcgi handler. It gets somewhat
jesse> better performance (since the server can dtrt with caching images)
jesse> and doesn’t add the complexity of having to parse mime types files, etc.
jesse>
jesse> Does that sound like it makes sense?

Yup, except for the following two backdraws:

  • you force users to have two document trees, one for text files and
    one for non-text files. Some might find that conveniant, some
    not.
  • you lose the feature of baing able to replace standard
    installation non-text files with your own by placing it in the
    local mason component root.

Anything I missed?

Richard Levitte \ Spannv�gen 38, II \ LeViMS@stacken.kth.se
Redakteur@Stacken \ S-168 35 BROMMA \ T: +46-8-26 52 47
\ SWEDEN \ or +46-733-72 88 11
Procurator Odiosus Ex Infernis – poei@bofh.se
Member of the OpenSSL development team: http://www.openssl.org/
Software Engineer, GemPlus: http://www.gemplus.com/

Unsolicited commercial email is subject to an archival fee of $400.
See http://www.stacken.kth.se/~levitte/mail/ for more info.