.htaccess Error 500 in Apache 2.4 because of FilterProvider #1012

Closed
bchr opened this Issue Mar 7, 2012 · 22 comments

Projects

None yet
@bchr
bchr commented Mar 7, 2012

From http://httpd.apache.org/docs/2.4/upgrading.html:

mod_filter: FilterProvider syntax has changed and now uses a boolean expression to determine if a filter is applied.

From http://httpd.apache.org/docs/2.4/mod/mod_filter.html:

The FilterProvider directive has changed from httpd 2.2: the match and dispatch arguments are replaced with a single but more versatile expression. In general, you can convert a match/dispatch pair to the two sides of an expression [...].

@mathiasbynens
Member

So, this:

FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html

Would become something like this:

FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'text/html'"

Easy enough to change, but how do we detect which syntax should be used?

@bchr
bchr commented Mar 7, 2012

Thanks for your reaction. I'm no expert. In fact I signed up at github just to post this to help myself and others.

I think it should be noted in the Boilerplate Docs. Also, maybe a easy-to-see note at the Boilerplate front page to somewhere where people can copy the new syntax to their own .htaccess.

I guess it's a bad idea to provide the new syntax commented out in .htaccess right?

@adeelejaz
Contributor

Just posting here to keep track of this.. I'm partly to blame for this to land in the h5bp to begin with. Over a year and it's still keeping coming back up.. sheeshh... I'm going to dig into this and see what can be done about this.

@drublic
Member
drublic commented Apr 6, 2012

Is it enough if we add a comment in the .htaccess-file pointing to a wiki-post explaining to use the new syntax in 2.4?

@meglio
meglio commented Apr 7, 2012

I'm using 2.4 too, so what is the final correct syntax?

@meglio
meglio commented Apr 7, 2012

Ok, so if I'm using 2.4, what is the final and correct syntax?

@drublic
Member
drublic commented Apr 7, 2012

Looks like you have to use this, as @mathiasbynens already pointed out:

FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'text/html'"
@marisk
marisk commented Apr 7, 2012

You can use ifversion module for this or just copy needed lines from example below.

  # HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
  <IfModule version.c>
  <IfModule filter_module.c>
    <IfVersion >= 2.4>
      FilterDeclare   COMPRESS
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'text/html'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'text/css'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'text/plain'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'text/xml'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'text/x-component'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/javascript'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/json'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/xml'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/xhtml+xml'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/rss+xml'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/atom+xml'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/vnd.ms-fontobject'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'image/svg+xml'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'image/x-icon'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'application/x-font-ttf'"
      FilterProvider  COMPRESS  DEFLATE "%{CONTENT_TYPE} = 'font/opentype'"
      FilterChain     COMPRESS
      FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no
    </IfVersion>
    <IfVersion <= 2.2>
      FilterDeclare   COMPRESS
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/plain
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/xml
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/x-component
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/javascript
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/json
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xml
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xhtml+xml
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/rss+xml
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/atom+xml
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/vnd.ms-fontobject
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/svg+xml
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/x-icon
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/x-font-ttf
      FilterProvider  COMPRESS  DEFLATE resp=Content-Type $font/opentype
      FilterChain     COMPRESS
      FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no
    </IfVersion>
  </IfModule>
  </IfModule>
@mikealmond
Contributor

I think the <IfVersion> check is the way to go. I'm not sure what kind of performance impact this might have, but it will fix a big issue for early adopters of Apache 2.4.

@ghost
ghost commented Apr 13, 2012

This didn't work for me. It didn't compress some files.

The actually returned content type is not just 'text/html'. It's 'text/html; charset=utf-8'. Using "%{CONTENT_TYPE} = 'text/html'", i think it means that the content type must match 'text/html', which it doesn't. Changing it to an expression did the trick.

The solution that works for me:

FilterDeclare  COMPRESS
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/html|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/css|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/plain|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/xml|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/x-component|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/javascript|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/json|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/xml|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/xhtml+xml|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/rss+xml|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/atom+xml|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/vnd.ms-fontobject|"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'image/svg+xml'"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'image/x-icon'"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'application/x-font-ttf'"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'font/opentype'"
FilterChain    COMPRESS
FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no

I tried to combine some lines: "%{CONTENT_TYPE} =~ m|^text/(html|css)|", but that gave errors.

@ghost
ghost commented May 1, 2012

Maybe a fallback for those that don't have version module enabled. This should default to 2.2 in the absence of the version module. I used @gpeltink's code above for 2.4 and above. This is all untested.

# HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
<IfModule filter_module.c>
    <IfModule version.c>
        <IfVersion >= 2.4>
            FilterDeclare  COMPRESS
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/html|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/css|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/plain|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/xml|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^text/x-component|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/javascript|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/json|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/xml|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/xhtml+xml|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/rss+xml|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/atom+xml|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m|^application/vnd.ms-fontobject|"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'image/svg+xml'"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'image/x-icon'"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'application/x-font-ttf'"
            FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'font/opentype'"
            FilterChain    COMPRESS
            FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
        </IfVersion>
        <IfVersion < 2.4>
            FilterDeclare   COMPRESS
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/plain
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/xml
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/x-component
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/javascript
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/json
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xml
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xhtml+xml
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/rss+xml
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/atom+xml
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/vnd.ms-fontobject
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/svg+xml
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/x-icon
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/x-font-ttf
            FilterProvider  COMPRESS  DEFLATE resp=Content-Type $font/opentype
            FilterChain     COMPRESS
            FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no
        </IfVersion>
    </IfModule>
    <IfModule !version.c>
        FilterDeclare   COMPRESS
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/plain
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/xml
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/x-component
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/javascript
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/json
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xml
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xhtml+xml
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/rss+xml
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/atom+xml
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/vnd.ms-fontobject
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/svg+xml
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/x-icon
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/x-font-ttf
        FilterProvider  COMPRESS  DEFLATE resp=Content-Type $font/opentype
        FilterChain     COMPRESS
        FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no
    </IfModule>
</IfModule>
@ghost
ghost commented May 2, 2012

I've got a more compact code for apache 2.4:

# HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
<IfModule filter_module>
    FilterDeclare  COMPRESS
    FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^text/(html|css|plain|xml|x-component)#i"
    FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^application/(javascript|json|xml|xhtml+xml|rss+xml|atom+xml|vnd.ms-fontobject|x-font-ttf)#i"
    FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^image/(svg+xml|x-icon)#i"
    FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'font/opentype'"
    FilterChain    COMPRESS
    FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
</IfModule>
@karlpcrowley
Contributor

I think this should be wrapped in <IfModule mod_deflate.c>as well to rule out 500's if this isn't enabled

@ghost
ghost commented May 23, 2012

It already is.

@necolas
Member
necolas commented May 28, 2012

Thanks for the work you guys have put into this so far. Where are we at with a potential solution?

@ghost
ghost commented May 28, 2012

I believe the solution I posted (which really just merged @marisk's and @gpeltink's solutions) is probably the way to go if you don't mind its verbosity. The only issue with it would be if someone has Apache 2.4 and does not have the version module enabled. The version module is used to tell the difference between Apache 2.4 and "less than 2.4." The code simply assumes "less than 2.4" in the absence of the version module since 2.4 isn't common just yet.

   # HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
    <IfModule filter_module.c>
        <IfModule version.c>
            <IfVersion >= 2.4>
                FilterDeclare  COMPRESS
                FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^text/(html|css|plain|xml|x-component)#i"
                FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^application/(javascript|json|xml|xhtml+xml|rss+xml|atom+xml|vnd.ms-fontobject|x-font-ttf)#i"
                FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^image/(svg+xml|x-icon)#i"
                FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = 'font/opentype'"
                FilterChain    COMPRESS
                FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
            </IfVersion>
            <IfVersion < 2.4>
                FilterDeclare COMPRESS
                FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html
                FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css
                FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain
                FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml
                FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject
                FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml
                FilterProvider COMPRESS DEFLATE resp=Content-Type $image/x-icon
                FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf
                FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype
                FilterChain COMPRESS
                FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
            </IfVersion>
        </IfModule>
        <IfModule !version.c>
            FilterDeclare COMPRESS
            FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html
            FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css
            FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain
            FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml
            FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject
            FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml
            FilterProvider COMPRESS DEFLATE resp=Content-Type $image/x-icon
            FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf
            FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype
            FilterChain COMPRESS
            FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
        </IfModule>
    </IfModule>

I have not submitted a pull request because I don't feel like it's my work (again, I only merged the work of two other guys) and because I haven't tested it.

@MoOx
MoOx commented Jul 25, 2012

The last code posted works great for me.
(btw, thanks for all of you guys)

@necolas
Member
necolas commented Aug 16, 2012

We need more peer review on this change. It doesn't feel like it has been tested enough, and it seems a bit odd that you have to duplicate a whole chunk of code.

@alrra
Member
alrra commented Aug 21, 2012

I did a little bit of "digging" yesterday and it seems the legacy portion of the hypertext access file (with some additions) can be also used for Apache 2.2 - 2.4.


1) Information about AddOutputFilterByType

From the Apache 2.2 documentation:

Compatibility: Available in Apache 2.0.33 and later; deprecated in Apache 2.1 and later
...
Enabling filters with AddOutputFilterByType may fail partially or completely in some cases. For example, no filters are applied if the MIME-type could not be determined and falls back to the DefaultType setting, even if the DefaultType is the same.

However, if you want to make sure, that the filters will be applied, assign the content type to a resource explicitly, for example with AddType or ForceType. Setting the content type within a (non-nph) CGI script is also safe.

... so, it was considered deprecated at one point, but it was never removed from Apache, fact that is confirmed even by the Apache 2.4 documentation:

Compatibility: Version 2.0.33 and later; had severe limitations before being moved to mod_filter in version 2.3.7

As for the problem described in the Apache 2.2 documentation, I think we're covered. :)

2) Proposed solution:
<IfModule mod_filter.c>                                                   
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE application/atom+xml \
                                      application/javascript \
                                      application/json \
                                      application/rss+xml \
                                      application/vnd.ms-fontobject \
                                      application/x-font-ttf \
                                      application/xhtml+xml \
                                      application/xml \
                                      font/opentype \
                                      image/svg+xml \
                                      image/x-icon \
                                      text/css \
                                      text/html \
                                      text/plain \
                                      text/x-component \
                                      text/xml
    </IfModule>
</IfModule>
  • Tested on:
    • Apache 2.2.22 (Ubuntu) / Apache 2 (OpenRC) 0.8.2 (Gentoo)
    • Apache 2.4.2 (Ubuntu)
@necolas
Member
necolas commented Aug 21, 2012

Nice work @alrra! Do you want to make a pull request? Thanks

@necolas necolas added a commit that closed this issue Aug 22, 2012
@alrra @necolas alrra + necolas More general compression configuration for Apache
Works with Apache ≥ 2.1 and requires `mod_deflate` and `mod_filter` to
be enabled. However, use of Apache < 2.2 is no longer recommended.

For Apache ≥ 2.1 → 2.3.7, `mod_filter` isn't needed, but requiring it
and using this solution is the best way going forward (plus, it doesn't
introduce other dependencies to other modules like, for example,
`mod_version`).

Fix gh-1012
Ref gh-1173
a36b296
@necolas necolas closed this in a36b296 Aug 22, 2012
@paulirish
Member

huge! nice digging @alrra !

@necolas necolas added a commit to h5bp/server-configs that referenced this issue Nov 28, 2012
@alrra @necolas alrra + necolas More general compression configuration for Apache
Works with Apache ≥ 2.1 and requires `mod_deflate` and `mod_filter` to
be enabled. However, use of Apache < 2.2 is no longer recommended.

For Apache ≥ 2.1 → 2.3.7, `mod_filter` isn't needed, but requiring it
and using this solution is the best way going forward (plus, it doesn't
introduce other dependencies to other modules like, for example,
`mod_version`).

Fix h5bp/html5-boilerplate#1012
Ref h5bp/html5-boilerplate#1173
1ec4456
@alrra alrra added a commit to h5bp/server-configs-apache that referenced this issue Jul 26, 2013
@alrra @necolas alrra + necolas More general compression configuration for Apache
Works with Apache ≥ 2.1 and requires `mod_deflate` and `mod_filter` to
be enabled. However, use of Apache < 2.2 is no longer recommended.

For Apache ≥ 2.1 → 2.3.7, `mod_filter` isn't needed, but requiring it
and using this solution is the best way going forward (plus, it doesn't
introduce other dependencies to other modules like, for example,
`mod_version`).

Fix  h5bp/html5-boilerplate#1012
Ref  h5bp/html5-boilerplate#1173
957e060
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment