use

António P. P. Almeida appa at perusio.net
Sat Jul 23 19:42:12 UTC 2011


On 23 Jul 2011 19h47 WEST, gmm at csdoc.com wrote:


>> Bear in mind that I've just browsed some begginer docs on Nginx
>> internals. But wouldn't that make the all process of merging the
>> configurations when inheriting handlers too complex?
>
> 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? 

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.

## 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.

location ^~ /img {
   define static_images {
     ## For static images log 404s here nd make the expire be 1d.
     expires 1d;
   }

   location ~* /img/icons/.*\.(?:jpe?g|png|gif|ico)$ {
       static_images;
   }

   location = /img/banners/large_banner.png {
      static_images;
   } 
}  


>> I would be happy with a "simple" define or defmacro that uses C
>> like syntax. I prefer defmacro just to distinguish it from the C
>> preprocessor directive. It avoids hypothetical confusions between C
>> source and Nginx configuration.
>
> I think this is bad idea. because nginx already use 'include'
> directive, which looks like C preprocessor #include directive.  also
> if new nginx directive will be named 'define' - no problems.  new
> nginx directive 'define' and C preprocessor directive '#define'
> distinguish one from another very well. same as 'include' and
> '#include'
>
>> defmacro static_images {
>> ## For static images don't log 404s and make the expire be maximal.
>> expires max;
>> log_not_found off;
>> }
> ...
>> 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.

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

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. Having a 'use' keyword puts the burden on you to do
that manually. It's less clean IMHO.

> define static_images {
> ## For static images don't log 404s and make the expire be maximal.
> expires max;
> log_not_found off;
> }
>
> location ^~ /other/img/ {
> use static_images;
> }
>
> also - 'defmacro' - this is not C-like syntax.
>
> because textwihoutspaceshasverybadreadability.

It comes from Lisp.

> 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. It's your responsibility to
be aware of redefinitions and unwanted side effects due to namespace
collisions.

> 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.

> also look full list:
>
> # python -c "import this"
>
> The Zen of Python, by Tim Peters
>
> Beautiful is better than ugly.  Explicit is better than implicit.
> Simple is better than complex.  Complex is better than complicated.
> Flat is better than nested.  Sparse is better than dense.
> Readability counts.  Special cases aren't special enough to break
> the rules.  Although practicality beats purity.  Errors should never
> pass silently.  Unless explicitly silenced.  In the face of
> ambiguity, refuse the temptation to guess.  There should be one--
> and preferably only one --obvious way to do it.  Although that way
> may not be obvious at first unless you're Dutch.  Now is better than
> never.  Although never is often better than *right* now.  If the
> implementation is hard to explain, it's a bad idea.  If the
> implementation is easy to explain, it may be a good idea.
> Namespaces are one honking great idea -- let's do more of those!
>
> I think these ideas also good for nginx config synax.

Yes. Indeed.

>> 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. 
 
--- appa



More information about the nginx-devel mailing list