Project

General

Profile

Lighttpd setenv.add-response-header not working for host condition

Added by brunyalo about 8 years ago

Dear Lighty team, et all,

I have issues with adding response headers using setenv.add-response-header under any host condition section.

I tested the following versions (Debian): 1.4.35-4 (Jessie), 1.4.31-4+deb7u4 (Wheezy)

What I want: Simply to add a CORS header specific to a host defined by domain name. I have SSL and HSTS enabled.

My configuration:

lighttpd.conf


...

# Let's add some header value for testing
setenv.add-response-header += (
  "X-Secret-Message" => "HELLO" 
)

# Host condition
$HTTP["host"] == "mydomain.example.com" {
  server.document-root = "/var/www/..." 
  setenv.add-response-header += (
    "Access-Control-Allow-Origin" => "https://mydomain2.example.com" 
  )
}

./config-enabled/50-forcehttps.conf: enable STS


$HTTP["scheme"] == "https" {
    setenv.add-response-header += (
        "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload" 
    )
}

./config-enabled/10-ssl.conf:


$SERVER["socket"] == "10.1.1.1:443" {
  ...
  $HTTP["host"] == "mydomain.example.com" {
    setenv.add-response-header += ( "X-Secret-Message2" => "SSLENABLED" )
  }
}

So, this config should add an STS header, if SSL enabled a secret message is shown plus a general "HELLO" is shown for all the hosts. Simple enough. This happens:

1. Only STS and HELLO header fields are added, CORS and SSL response headers are vanished:


Strict-Transport-Security:max-age=63072000; includeSubdomains; preload
X-Secret-Message:OUTER

2. Host conditional access is met, I debugged this, so setenv.add-response-header should do what is should.

3. If I turn off STS then message in SSL config is added:


X-Secret-Message:HELLO
X-Secret-Message2:SSLENABLED

4. Nothing specific is shown in error.log. Configuration is parsed correctly.

This is a bit weird for me and driving me crazy. Please help. Thanks a lot indeed.


Replies (4)

RE: Lighttpd setenv.add-response-header not working for host condition - Added by stbuehler about 8 years ago

+= isn't doing what you think. Use lighttpd -p to see how lighttpd sees your config file.

RE: Lighttpd setenv.add-response-header not working for host condition - Added by gstrauss about 8 years ago

lighttpd 1.4.x configuration is parsed at startup. At runtime (i.e. for each request), lighttpd does not dynamically combine directive values for the same directive defined in different conditional blocks. For a given directive, lighttpd uses the last value seen in a matched condition. This can definitely be considered a shortcoming, but this is how it currently behaves.

I try to explain that another way: In each block that you define a directive, what you assign in that block is the value for that directive in that block. If you define a directive, no values for that directive are inherited from outer scopes or from previously matched blocks. If you do not define a directive, then the request inherits the directive value from the last matched block which defines that directive, or else from the global scope, or else the default value for that directive.

Below is a partial workaround, applicable only in some simple use cases, which uses the existing config directives. As stbuehler recommended, please use lighttpd -p to report the results of lighttpd parsing the config file.

Use variables to collect common headers, and then repeat the variables in each scope that you define additional headers. You can do this instead of repeating all of the directives in each scope. This works well when you have a top-level config and then there is only one condition you expect to match per request, in which you put the combined set of directives.

var.common-response-headers = ( "a" => "b", "c" => "d" )

var.common-response-headers += (
  "X-Secret-Message" => "HELLO" 
)

var.strict-transport-security = (
  "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload" 
)

setenv.add-response-header = var.common-response-headers

$SERVER["socket"] == "127.0.0.1:8080" {
  setenv.add-response-header = var.common-response-headers
  setenv.add-response-header += ("e" => "f")
}

# Host condition
$HTTP["host"] == "mydomain.example.com" {
  server.document-root = "/var/www/..." 
  setenv.add-response-header  = var.common-response-headers
  setenv.add-response-header += (
    "Access-Control-Allow-Origin" => "https://mydomain2.example.com" 
  )
}

#./config-enabled/50-forcehttps.conf: enable STS

$HTTP["scheme"] == "https" {
    setenv.add-response-header  = var.common-response-headers
    setenv.add-response-header += var.strict-transport-security
}

#./config-enabled/10-ssl.conf:

$SERVER["socket"] == "10.1.1.1:443" {
  $HTTP["host"] == "mydomain.example.com" {
    setenv.add-response-header  = var.common-response-headers
    setenv.add-response-header += var.strict-transport-security
    setenv.add-response-header += ( "X-Secret-Message2" => "SSLENABLED" )
  }
}

RE: Lighttpd setenv.add-response-header not working for host condition - Added by brunyalo about 8 years ago

It helps a lot.

Is this behavious documented anywhere? A short note on doc page of setenv.add-response-header could be useful.

Thank you very much, and thanks for the example.

RE: Lighttpd setenv.add-response-header not working for host condition - Added by stbuehler about 8 years ago

This is the generic config behavior; it doesn't make sense to document this on every "array" option.

    (1-4/4)