Mod setenv » History » Revision 17
Revision 16 (gstrauss, 2019-05-04 22:30) → Revision 17/30 (gstrauss, 2020-05-31 23:29)
h1. Conditional Request Headers {{>toc}} *Module: mod_setenv* h2. Description mod_setenv modifies request headers (from clients), The setenv module allows influencing the environment external applications are spawned in and the response headers (to clients), and the environment (for CGI). server sends to the clients. Note: mod_setenv needs to be listed prior to mod_redirect in the @server.modules@ list in lighttpd.conf so that mod_setenv can set headers prior to the redirect. (Listing modules alphabetically is a +common mistake+. common mistake. e.g. #2946) To set "Cache-Control" h2. Automatic Decompression If you have a lot text-files compressed with gzip on disk and "Expires" caching response headers, prefer [[Docs_ModExpire|mod_expire]] instead of mod_setenv. To set "Content-Encoding", prefer [[Docs_ModDeflate|mod_deflate]] or [[Docs_ModCompress|mod_compress]] want that the browser is decompressing them on retrieval you can use setenv to inject the Content-Encoding header: To use mod_setenv: @server.modules += <pre> $HTTP["url"] =~ "(README|ChangeLog|\.txt)\.gz$" { setenv.add-response-header = ( "mod_setenv" )@ "Content-Encoding" => "gzip") mimetype.assign = ("" => "text/plain" ) } </pre> h2. Options *setenv.add-environment* Adds a value to the process environment (aka environment variables) that is passed to the external applications: <pre> setenv.add-environment = ( "TRAC_ENV" => "lighttpd", "RAILS_ENV" => "production" ) </pre> *setenv.add-response-header* Adds a header to the HTTP response sent to the client: <pre>setenv.add-response-header <pre> setenv.add-response-header = ("My-Custom-Header" ( "Content-Encoding" => "my-custom-value")</pre> "gzip" ) </pre> *setenv.add-request-header* Adds a header to the HTTP request that was received from the client: <pre>setenv.add-request-header = ("X-Proxy" => "my.server.name")</pre> *setenv.add-environment* Adds a value to the process environment (aka environment variables) that is passed to the external applications: <pre> setenv.add-environment setenv.add-request-header = ( "TRAC_ENV" "X-Proxy" => "lighttpd", "RAILS_ENV" => "production" server.name ) </pre> *setenv.set-request-header* (since 1.4.46) *setenv.set-response-header* (since 1.4.46) *setenv.set-environment* (since 1.4.46) These directives _set_ the given values, rather than appending the given values to the headers or environment. These directives take precedence over the setenv.add-* counterparts. Set a blank value for request or response header to cause remove the header to be removed. h2. HTTP Strict Transport Security (HSTS) A typical HSTS configuration sets max-age to 365 days (31536000 seconds). If testing, please use a shorter max-age (e.g. @max-age=600@) until you are more confident with your configuration. Do not append @; preload@ to the header value unless you understand the consequences. <pre> setenv.set-response-header = ("Strict-Transport-Security" => "max-age=31536000; includeSubDomains") </pre> h2. Using setenv in multiple configuration conditions The way that lighttpd processes its [[Docs_Configuration|configuration syntax]] may not be intuitive to some, but the results must be deterministic. lighttpd parses its configuration at startup. lighttpd does not merge lists from multiple matching conditions. For each specific configuration directive, the last condition that matches a client request and contains that specific directive is the configuration used for that specific directive for that client request. @setenv-add-response-header@ and @setenv-set-response-header@ are distinct configuration directives. For example: a request for "/abc/def/ghi" will match all three conditions, and even though the directive is @setenv-add-response-header@, only the last one will be used for the request, adding the response header "Custom-Header: value-C" <pre> $HTTP["url"] =~ "^/" { setenv.add-response-header = ("Custom-Header" => "value-A") } $HTTP["url"] =~ "^/abc/" { setenv.add-response-header = ("Custom-Header" => "value-B") } $HTTP["url"] =~ "^/abc/def/" { setenv.add-response-header = ("Custom-Header" => "value-C") } </pre> Order matters. The order in which you write the configuration matters. For the same request for "/abc/def/ghi" but with the configuration directives listed in a different order, again, the last matching condition will be used for the request, in this case adding the response header "Custom-Header: value-A" <pre> $HTTP["url"] =~ "^/abc/def/" { setenv.add-response-header = ("Custom-Header" => "value-C") } $HTTP["url"] =~ "^/abc/" { setenv.add-response-header = ("Custom-Header" => "value-B") } $HTTP["url"] =~ "^/" { setenv.add-response-header = ("Custom-Header" => "value-A") } </pre> The same is true for @+=@. The @+=@ applies only to the list within the current scope, within the current configuration condition. The @+=@ _does not_ have an effect across different configuration conditions. For the same request for "/abc/def/ghi" but with the configuration directives listed below, again, the last matching condition will be used for the request, in this case adding the response headers "Custom-Header1: value-C" and "Custom-Header2: value-C" <pre> $HTTP["url"] =~ "^/" { setenv.add-response-header = ("Custom-Header1" => "value-A") setenv.add-response-header+= ("Custom-Header2" => "value-A") } $HTTP["url"] =~ "^/abc/" { setenv.add-response-header = ("Custom-Header1" => "value-B") setenv.add-response-header+= ("Custom-Header2" => "value-B") } $HTTP["url"] =~ "^/abc/def/" { setenv.add-response-header = ("Custom-Header1" => "value-C") setenv.add-response-header+= ("Custom-Header2" => "value-C") } </pre> The following is one method to define a setenv set of policy headers into a variable and to reuse the set: <pre> var.response_header_policy = ( #"Strict-Transport-Security" => "max-age=31536000; includeSubDomains", # preferred for sites to designate HSTS "Strict-Transport-Security" => "max-age=300; includeSubDomains", # minimize damage for those who ignorantly cut-n-paste "X-Content-Type-Options" => "nosniff" ) $HTTP["url"] =~ "^/" { setenv.set-response-header = var.response_header_policy setenv.set-response-header+= ("Custom-Header" => "value-A") } $HTTP["url"] =~ "^/abc/" { setenv.set-response-header = var.response_header_policy setenv.set-response-header+= ("Custom-Header" => "value-B") } $HTTP["url"] =~ "^/abc/def/" { setenv.set-response-header = var.response_header_policy setenv.set-response-header+= ("Custom-Header" => "value-C") } </pre> h2. Automatic Decompression If you have a lot text-files compressed with gzip on disk and want the browser to decompress them on retrieval, you can use setenv to inject the Content-Encoding header, but should not do so unless all of your clients support @Accept-Encoding: gzip@. You should instead prefer [[Docs_ModCompress|mod_compress]], and pre-fill the mod_compress cache location with compressed content. <pre> $HTTP["url"] =~ "(README|ChangeLog|\.txt)\.gz$" { setenv.add-response-header = ( "Content-Encoding" => "gzip") mimetype.assign = ("" => "text/plain" ) } </pre> header.