use

Gena Makhomed gmm at csdoc.com
Sat Jul 23 20:49:16 UTC 2011


On 23.07.2011 22:42, António P. P. Almeida wrote:

>> require is just the same directive as include, with one exception -
>> require ignores all macro definitions during process of "including".
>> this is not too complex for implementation in nginx.

> Hmmm...but wouldn't that block any possibility of include defined
> macros to be used in require?

directive require need only for global config file /etc/nginx/nginx.conf
for "inclusion" in 'global' config all 'local' site config files.

require /etc/nginx/virtual/*.conf;

in /etc/nginx/virtual - separate 'local' config files for each site:

example.com.conf
example.net.conf
example.org.conf
...and so on


> include (global) ->  require (vhost) I think that the require/include
> issue could be circumvented with the possibility of defining macros
> inside locations and server blocks.

often need macros for multiple related sites,
wtich defined in one configuration file.
for example:

example.com
example.com via https
image.example.com
static.example.com
vip.example.com
...and so on

all these virtual hosts can be defined in one config example.com.conf

if macros forced to be defined only inside server`s and location`s -
we again need to copy/paste/paste/paste/paste configuration fragments
between diffenent server { ... } blocks. or move macro definitions
to external file and use multiple includes. and we got
the same problem, which try to solve by macros.

> ## Global scope.
> define static_images {
>       ## For static images don't log 404s and make the expire be maximal.
>       expires max;
>       log_not_found off;
> }
>
> server {
>
>    define static_images {
>       ## For static images don't log 404s and make the expire be 45d.
>       expires 45d;
>       log_not_found off;
>    }
>
>    (...)
> }
>
>
> Each redefinition overrides the previous. It should issue a warning
> when there's a reload.

in C all macros are global - from point of definition
to end of file. if we make C-like syntax and C-like directives
- behaviour of 'define' directive should be close to C preprocessor
'#define' directive.

if I define some macro at start of 'local' configuration file -
I can be sure what this macro will be same to end of this file.

if macro will be redefined multiple times in nested levels -
this is will be nightmage of support such nginx config files.

to make changes and sure that changes will be applied -
you will ned to re-read all config file from start to end.

================================================

define static_images { code1 }

server {
    define static_images { code2 }

    location / {
        define static_images { code3 }
        use static_images;                   [1]
        location /nested/ {
            use static_images;               [2]
            define static_images { code4 }
            location /one/more/ {
                use static_images;           [3]

================================================

can you easy say which codeX will
be used for each case [1], [2], [3] ?

...even if such config will contain 100 locations?

>>> defmacro static_images {
>> ...
>>> location ^~ /other/img/ {
>>> static_images;
>>> }
>>
>> and what happen with your configs if in future Igor implement in
>> nginx new first-class directive static_images ? may be better define
>> + use ?
>
> That can be solved by having an internal symbol table for macros. When
> the configuration is read, a symbol table is built that maps the user
> defined identifiers to internal identifiers and these internal symbols
> replace the user defined identifiers.

semantic of static_images will be unexpetedly
changed from macro to built-it nginx directive.

and this is will be nightmage of supporting
nginx config files with volatile semantics.

> Some Lisp implementations implemented that to avoid macro capture due
> to identifier
> collision. https://secure.wikimedia.org/wikipedia/en/wiki/Hygienic_macro

sorry, I can't understand this conglomeration of punctuation symbols:

(defmacro my-unless (condition &body body)
  `(if (funcall ',#'not ,condition)
     (progn
       , at body)))

==================================================

> This will introduce a new phase when reading the configuration. The
> first phase would be this internal symbol generation and replacement.
>
> Now if there's a new directive static_images and your config has a
> static_images macro, it wont matter because when reading the
> configuration:
>
> define static_images will be transformed to define :G23113. No chance
> of collision exists. Of course the parsing of the config will become
> more complex. But it's a clean process because syntactic substitutions
> are just that.

when I read config - how I cat understand which semanctic have

fragment of config

static_images /srv/www/img;

- this is new nginx directive or macro with different semactics ?

the same for all already existing nginx
directives, which overlaping with macros.

> Having a 'use' keyword puts the burden on you to do
> that manually. It's less clean IMHO.

use static_images;
- from first view I can understand: this is macro usage.

>> also - 'defmacro' - this is not C-like syntax.
>>
>> because textwihoutspaceshasverybadreadability.

> It comes from Lisp.

nginx config is not lisp-like, it is C-like!!!

defmacro isbad directivecandidate, ithave badreadability.

>> C-like synxax is text_with_underscopes_instead_of_spaces;

>>> The scope could continue to be global and thus it wouldn't touch on
>>> the location configuration merge process and preserve all the
>>> current capabilities of hooking into the multitude of aspects of
>>> nginx processing cycle when writing a module.
>>
>> this is dangerous.
>>
>> if in one local site config file you write
>>
>> define static_images { ... }
>>
>> and in other local site config file by mistake you write
>>
>> define static_inages { ... }
>>
>> - nginx will sliently use static_images from prevous local site
>> config file and sliently ignone all your changes in current file.
>>
>> this is bad approach.
>
> I don't think so. If there's a scope for the define directive. Meaning
> that the more specific wins. It's clear.

this is break rule "Errors should never pass silently".

> It's your responsibility to
> be aware of redefinitions and unwanted side effects due to namespace
> collisions.

do it manually in nginx configurations with 100-200-300 config files?

thank you.

>> this is break rule "Errors should never pass silently".
>>
>> I think better - add one more 'require' directive with
>> fail-safe behaviour - and make all errors are not silent.

> It's not silent. It issues a warning when the config is read.

no.

none warnings, none errors.

example1.com.conf:

define static_images { ... }
use static_images;

example2.com.conf:

define static_inages { ... }
use static_images;

nginx.conf:

include example1.com.conf;
include example2.com.conf;

==============================

in config file example2.com.conf
use static_images; - will use
definitions from example1.com.conf
and silently ignore definitions
from example2.com.conf

this is break rule "Errors should never pass silently".

>>> Your proposal is great, but in the meantime a stopgap solution like
>>> the above would be great. Potentially it can make the
>>> configurations shorter, less prone to errors, and above all: avoid
>>> repetition.

>> and what about backward compatibility ?

> See above. OTOH I find that software that is obsessed with backward
> compatibility becomes sooner or later a maintenance and development
> nightmare. Sometimes is better to make a clean cut and state
> explicitly that the new version isn't backward compatible. It's a way
> to keep the code base lean and clean. Of course that's just my
> unsolicited opinion. It's Igor, Maxim et al. call to decide the
> development policy and strategy.

it will be clean code base and easy life for few nginx developers,
but this will be support nightmare for few million of nginx users.

-- 
Best regards,
  Gena



More information about the nginx-devel mailing list