Config directive inheritance: docs and rules (was: Config variable inheritance)

Hi all -

Problem with inheriting fastcgi params - NGINX - Ruby-Forum seems to contain some
information I’ve not found explicitly stated anywhere else: that
config directive inheritance is an all or nothing mechanism. Have I
missed some docs somewhere?

Following on from this, I’d like to understand if there’s anything I
can reliably determine from a directive’s name about the impact that
defining it will have on other directives’ inheritability.

Can I, for instance, assume that defining an xyx_ prefixed directive in
a sub-scope will affect only the inheritance of other xyz_ prefixed
directives? Or can there be inheritance side-effects between, say,
directive “abc” and “def” that I can’t possibly determine without
documentation or trial and error?

Equally, can I assume that all xyz_ prefixed directives will have
their inheritance affected by the sub-scope definition of any other
xyz_ prefixed directive? Or are there examples where defining
“xyz_foo” does not impact the inheritance of “xyz_bar”?

I’m thinking specifically of proxy_* directives, whereas the thread I
link to above is talking about multiple fastcgi_param directives.
Here, I’m interested in how, say, proxy_set_header affects the
inheritance of higher scope’s proxy_pass directive - i.e. where the
prefix matches but they’re not the same directive. Does nginx (core)
derive or imply anything relating to the name-spacing of directives
before (in my example) the proxy module sees the config, or is it
entirely down to how each module implements the configuration
aggregation/inheritance?

Many thanks,
Jonathan

Jonathan M.
London, Oxford, UK
http://www.jpluscplusm.com/contact.html

On Tue, Apr 03, 2012 at 06:20:13PM +0100, Jonathan M. wrote:

Hi there,

Problem with inheriting fastcgi params - NGINX - Ruby-Forum seems to contain some
information I’ve not found explicitly stated anywhere else: that
config directive inheritance is an all or nothing mechanism. Have I
missed some docs somewhere?

That refers to inheritance of a single directive.

Following on from this, I’d like to understand if there’s anything I
can reliably determine from a directive’s name about the impact that
defining it will have on other directives’ inheritability.

Yes: it will have no impact on other directives.

Can I, for instance, assume that defining an xyx_ prefixed directive in
a sub-scope will affect only the inheritance of other xyz_ prefixed
directives?

No. It will affect no other xyz_ prefixed directives.

It may make a difference to the applicability of other directives –
for example, if fastcgi_pass is not set, then it doesn’t really matter
whether fastcgi_param is inherited or not, because it’s not going to be
used. But fastcgi_pass does not affect whether fastcgi_param is
inherited.

Or can there be inheritance side-effects between, say,
directive “abc” and “def” that I can’t possibly determine without
documentation or trial and error?

No, it will have no impact on other directives.

Equally, can I assume that all xyz_ prefixed directives will have
their inheritance affected by the sub-scope definition of any other
xyz_ prefixed directive?

No: it will have no impact on other directives.

Or are there examples where defining
“xyz_foo” does not impact the inheritance of “xyz_bar”?

Yes: every example.

I’m thinking specifically of proxy_* directives, whereas the thread I
link to above is talking about multiple fastcgi_param directives.

Using a directive sets the value of that directive. It does not set the
value of different directives.

“Not using” a directive means the value of that directive is either
unset/default, or is the same value as the upper level.

Here, I’m interested in how, say, proxy_set_header affects the
inheritance of higher scope’s proxy_pass directive - i.e. where the
prefix matches but they’re not the same directive.

No impact at all.

Does nginx (core)
derive or imply anything relating to the name-spacing of directives
before (in my example) the proxy module sees the config, or is it
entirely down to how each module implements the configuration
aggregation/inheritance?

It’s entirely down to how each module implements it. But if a module
implements inheritance of a directive as something other than “replace”
or “no inheritance”, then that should probably be considered a bug.

f

Francis D. [email protected]

Hello!

On Wed, Apr 04, 2012 at 01:40:40PM +0100, Francis D. wrote:

No. It will affect no other xyz_ prefixed directives.
Not really, there are cases where it will. Examples include (not
sure if there are others):

  1. allow and deny directives of access module create an array of
    allow/deny rules, and this array is inherited as a whole;

  2. recently introduced xslt_param and xslt_string_param do the
    same thing with xslt parameters.

All such cases are more or less obvious though.

[…]

Maxim D.

On Wed, Apr 04, 2012 at 05:58:46PM +0400, Maxim D. wrote:

On Wed, Apr 04, 2012 at 01:40:40PM +0100, Francis D. wrote:

On Tue, Apr 03, 2012 at 06:20:13PM +0100, Jonathan M. wrote:

Hi there,

allow/deny rules, and this array is inherited as a whole;

  1. recently introduced xslt_param and xslt_string_param do the
    same thing with xslt parameters.

Ah, thank you for the correction.

For the original poster: I was wrong, you do need to check or test
each
time. So read “never” and “always” as “almost never” and “almost
always”.

Sorry about that.

I’ve done a quick analysis of the 1.1.18 codebase, to see if I can find
the current complete list (excluding 3rd party modules, of course).

The configuration directives are stored in a struct:

struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void
*conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};

“name” is the directive name; “*set” is the function to set the value
of the directive, and “offset” is the position relative to “conf” where
the value is stored.

I see 67 arrays of that struct (grep for “static ngx_command_t”).

I see 449 “ngx_string” within those arrays.

110 have unique *set values.

Of the ones with non-unique *set values, the few that have the same
“offset” value are:

ngx_event_connections - worker_connections, connections; one deprecated
ngx_mail_block - mail, imap; one deprecated
ngx_conf_set_sec_slot - open_file_cache_valid, open_file_cache_retest;
one deprecated

ngx_http_core_root - root, alias: single-valued, only one at a level
ngx_http_access_rule - allow, deny; both are valid
ngx_http_xslt_param - xslt_param, xslt_string_param; both are valid.

And separate from that, the directives which have a duplicate “offset”
value of “offsetof(something)” (as in, not-0 or a predefined constant),
are:

open_file_cache_valid, open_file_cache_retest - one deprecated
satisfy, satisfy_any - one deprecated
optimize_server_names, server_name_in_redirect - one deprecated

If that’s an adequate analysis, it suggests that

allow/deny and xslt_param/xslt_string_param

are the only distributed directives which don’t follow the
replace-or-inherit-this-directive-only method.

All such cases are more or less obvious though.

I wonder, is it worth having a note in the documentation for these
exceptions to the common case?

I see that there is such a note at

Module ngx_http_xslt_module,

but not (yet) at

http://nginx.org/en/docs/http/ngx_http_access_module.html#allow

Thanks,

f

Francis D. [email protected]

Hello!

On Wed, Apr 04, 2012 at 05:54:44PM +0100, Francis D. wrote:

[…]

If that’s an adequate analysis, it suggests that

allow/deny and xslt_param/xslt_string_param

are the only distributed directives which don’t follow the
replace-or-inherit-this-directive-only method.

Mechanical analisys of the codebase might miss some cases with
custom directive handlers used. But I suppose the result is
correct as it matches one from my memory. :slight_smile:

Module ngx_http_access_module

Yes, this surely deserves a note.

Maxim D.