Project

General

Profile

Mod setenv » History » Revision 20

Revision 19 (gstrauss, 2020-06-01 11:08) → Revision 20/30 (gstrauss, 2020-06-13 04:45)

h1. Conditional Request Headers 

 {{>toc}} 

 *Module: mod_setenv* 

 h2. Description 

 mod_setenv modifies request headers (from clients), response headers (to clients), and the environment (for CGI). 

 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+. e.g. #2946) 

 To set "Cache-Control" 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]] 

 To use mod_setenv: @server.modules += ( "mod_setenv" )@ 

 h2. Options 

 *setenv.add-response-header* 
 Adds a header to the HTTP response sent to the client: 
 <pre>setenv.add-response-header = ("My-Custom-Header" => "my-custom-value")</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 = (  
   "TRAC_ENV" => "lighttpd", 
   "RAILS_ENV" => "production" 
 ) 
 </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 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> 
 See also "Using setenv in multiple configuration conditions" below for setting HSTS along with other setenv directives. 

 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 
   "Content-Security-Policy" => "default-src https:" 
   "X-Frame-Options" => "SAMEORIGIN", 
   "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> 
 Some policy response headers should be sent in all responses, but some need not be sent in all responses, e.g. for images, scripts, stylesheets, etc.    You might save some bandwidth by omitting them.    Reference Scott Helme's: "Micro-optimisation for fun!":https://scotthelme.co.uk/micro-optimisation-for-fun/ 

 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>