Bug #2597


Concatenation operator and conditions are order-dependent in a non-obvious way

Added by romanrm over 9 years ago. Updated almost 8 years ago.

Target version:


In this config:

$HTTP["host"] =~ "example\.com" {
  alias.url += (
    "/1" => "/tmp/1",

alias.url += (
  "/2" => "/tmp/2",

Of these, only the first mapping will actually work. That's because the parser transforms this into:

    alias.url                      = (
        "/2" => "/tmp/2",

    $SERVER["socket"] == "[::]:80" {
        # block 1

    } # end of $SERVER["socket"] == "[::]:80" 

    $HTTP["host"] =~ "example\.com" {
        # block 2
        alias.url = (
            "/1" => "/tmp/1",

    } # end of $HTTP["host"] =~ "example\.com" 

So the "/2" mapping that was supposed to be unconditional, instead gets clobbered by the "/1", because it's moved to be the first, and then both alias.url directives are transformed from "+=" into "=".

Moving the "/2" in front of the conditional block avoids the issue.

However the expected behavior is that both mappings should work when the condition matches, and the order of these blocks should not matter. That it actually does, seems to be caused by some implementation detail, and leads to a nasty "gotcha", where just about the simplest and most clean-cut example of trying to using conditions and concatenations blows up right into your (my) face.

If such behavior is for some reason unfeasible to implement, then at the very least, some sort of a log warning should be printed, e.g. that some of the unconditional values actually get overwritten by a condition.

Actions #1

Updated by darix over 9 years ago

It doesnt get clobbered. when you enter the conditional for your hostname we copy the alias.url list, which at this point is empty.
We append your alias for /1 to an empty list. Later on you append to the original alias.url list the /2 alias.

Actions #2

Updated by stbuehler over 9 years ago

  • Status changed from New to Invalid
  • Target version deleted (1.4.x)

Sorry, as much as I agree with your intuition of how it should work, this is just not how it is. And we certainly won't change such basic behaviour in a stable branch.
As such configs are not wrong itself a warning doesn't seem appropriate.

lighttpd2 has a complete new config scheme, and doesn't have this problem (it has its own "misunderstandings" :) ).

Actions #3

Updated by gstrauss about 8 years ago

Perhaps the documentation could be more explicit.

The current implementation treats the directives in each condition as independent from directives in other conditions, even those in nested condition scopes. In other words '+=' is limited to within the same exact condition, and not the condition scope plus sub-conditions.

At runtime, arrays/list in the request config are replaced in the request config for each condition that matches; arrays/lists are not duplicated and merged (from different conditions) at runtime for each request.

Actions #4

Updated by stbuehler about 8 years ago

Explaining what += does exactly is difficult (I don't think your description is helping for example); I usually recommend using lighttpd -p to see how lighty actually sees the config, but romanrm already knew that (he posted the output of that command).

Actions #5

Updated by gstrauss almost 8 years ago

FYI: tried again to explain same thing for different question:


Also available in: Atom