nginx_config/
ast.rs

1//! Abstract Syntax Tree types
2
3#![allow(missing_docs)] // structures are meant to be self-descriptive
4use std::path::PathBuf;
5use std::net::{SocketAddr, IpAddr};
6
7pub use value::{Value};
8use position::Pos;
9use visitors::{DirectiveIter};
10
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Main {
14    pub directives: Vec<Directive>,
15}
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct Directive {
19    pub position: Pos,
20    pub item: Item,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum WorkerProcesses {
25    Auto,
26    Exact(u32),
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Http {
31    pub position: (Pos, Pos),
32    pub directives: Vec<Directive>,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
36pub struct Server {
37    pub position: (Pos, Pos),
38    pub directives: Vec<Directive>,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub enum IfCondition {
43    NonEmpty(Value),
44    Eq(Value, String),
45    Neq(Value, String),
46    RegEq(Value, String, bool),
47    RegNeq(Value, String, bool),
48    Exists(Value),
49    NotExists(Value),
50    FileExists(Value),
51    FileNotExists(Value),
52    DirExists(Value),
53    DirNotExists(Value),
54    Executable(Value),
55    NotExecutable(Value),
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct If {
60    pub position: (Pos, Pos),
61    pub condition: IfCondition,
62    pub directives: Vec<Directive>,
63}
64
65#[derive(Debug, Clone, PartialEq, Eq)]
66pub enum Address {
67    Ip(SocketAddr),
68    StarPort(u16),
69    Port(u16),
70    Unix(PathBuf),
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
74pub enum HttpExt {
75    Http2,
76    Spdy,
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct Listen {
81    pub address: Address,
82    pub default_server: bool,
83    pub ssl: bool,
84    pub ext: Option<HttpExt>,
85    pub proxy_protocol: bool,
86    pub setfib: Option<i32>,
87    pub fastopen: Option<u32>,
88    pub backlog: Option<i32>,
89    pub rcvbuf: Option<u64>,
90    pub sndbuf: Option<u64>,
91    // TODO(tailhook) Not sure
92    // accept_filter: String,
93    pub deferred: bool,
94    pub bind: bool,
95    pub ipv6only: Option<bool>,
96    pub reuseport: bool,
97    // TODO(tailhook) requires complex parser
98    // so_keepalive: Option<KeepAlive>,
99}
100
101impl Listen {
102    pub fn new(address: Address) -> Listen {
103        Listen {
104            address,
105            default_server: false,
106            ssl: false,
107            ext: None,
108            proxy_protocol: false,
109            setfib: None,
110            fastopen: None,
111            backlog: None,
112            rcvbuf: None,
113            sndbuf: None,
114            deferred: false,
115            bind: false,
116            ipv6only: None,
117            reuseport: false,
118        }
119    }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
123pub enum LocationPattern {
124    Prefix(String),
125    Exact(String),
126    FinalPrefix(String),
127    Regex(String),
128    RegexInsensitive(String),
129    Named(String),
130}
131
132#[derive(Debug, Clone, PartialEq, Eq)]
133pub struct Location {
134    pub position: (Pos, Pos),
135    pub pattern: LocationPattern,
136    pub directives: Vec<Directive>,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq, Copy)]
140pub enum GzipStatic {
141    On,
142    Off,
143    Always,
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, Copy)]
147pub enum GzipProxied {
148    Off,
149    Expired,
150    NoCache,
151    NoStore,
152    Private,
153    NoLastModified,
154    NoEtag,
155    Auth,
156    Any,
157}
158
159
160#[derive(Debug, Clone, PartialEq, Eq)]
161pub struct AddHeader {
162    pub field: Value,
163    pub value: Value,
164    pub always: bool,
165}
166
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub enum ServerName {
169    Exact(String),
170    Suffix(String),
171    StarSuffix(String),
172    StarPrefix(String),
173    Regex(String),
174}
175
176#[derive(Debug, Clone, PartialEq, Eq)]
177pub enum MapPattern {
178    Exact(String),
179    Suffix(String),
180    StarSuffix(String),
181    StarPrefix(String),
182    Regex(String),
183}
184
185#[derive(Debug, Clone, PartialEq, Eq)]
186pub struct Map {
187    pub variable: String,
188    pub expression: Value,
189    pub default: Option<Value>,
190    pub hostnames: bool,
191    pub volatile: bool,
192    pub includes: Vec<String>,
193    pub patterns: Vec<(MapPattern, Value)>,
194}
195
196#[derive(Debug, Clone, PartialEq, Eq)]
197pub enum ErrorPageResponse {
198    /// The response code of a target uri
199    Target,
200    /// Replace with a specified value
201    Replace(u32),
202    /// Replace with a specified redirect (`=` with codes 301,302,303,307,308)
203    Redirect(u32),
204    /// Keep original (bare `=`)
205    Keep,
206}
207
208#[derive(Debug, Clone, PartialEq, Eq)]
209pub struct ErrorPage {
210    pub codes: Vec<u32>,
211    pub response_code: ErrorPageResponse,
212    pub uri: Value,
213}
214
215#[derive(Debug, Clone, PartialEq, Eq)]
216pub enum Return {
217    Redirect { code: Option<u32>, url: Value },
218    Text { code: u32, text: Option<Value> },
219}
220
221#[derive(Debug, Clone, PartialEq, Eq)]
222pub enum RewriteFlag {
223    Last,
224    Break,
225    Redirect,
226    Permanent,
227}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
230pub struct Rewrite {
231    pub regex: String,
232    pub replacement: Value,
233    pub flag: Option<RewriteFlag>,
234}
235
236#[derive(Debug, Clone, PartialEq, Eq)]
237pub enum TryFilesLastOption {
238    Uri(Value),
239    NamedLocation(String),
240    Code(u32),
241}
242
243#[derive(Debug, Clone, PartialEq, Eq)]
244pub struct TryFiles {
245    pub options: Vec<Value>,
246    pub last_option: TryFilesLastOption,
247}
248
249#[derive(Debug, Clone, PartialEq, Eq)]
250pub struct Expires {
251    pub modified: bool,
252    pub value: Value,
253}
254
255#[derive(Debug, Clone, PartialEq, Eq)]
256pub enum Source {
257    All,
258    Unix,
259    Ip(IpAddr),
260    Network(IpAddr, u8),
261}
262
263#[derive(Debug, Clone, PartialEq, Eq, Copy)]
264pub enum ProxyHttpVersion {
265    V1_0,
266    V1_1,
267}
268
269#[derive(Debug, Clone, PartialEq, Eq)]
270pub enum ProxyCacheValid {
271    Normal(Value),
272    Specific(Vec<u32>, Value),
273    Any(Value),
274}
275
276#[derive(Debug, Clone, PartialEq, Eq)]
277pub enum ProxyNextUpstreamFlag {
278    Error,
279    Timeout,
280    InvalidHeader,
281    Http500,
282    Http502,
283    Http503,
284    Http504,
285    Http403,
286    Http404,
287    Http429,
288    NonIdempotent,
289    Off,
290}
291
292#[derive(Debug, Clone, PartialEq, Eq)]
293pub enum AccessLog {
294    Off,
295    On(AccessLogOptions),
296}
297
298#[derive(Debug, Clone, PartialEq, Eq)]
299pub struct AccessLogOptions {
300    pub path: Value,
301    pub format: Option<String>,
302    pub buffer: Option<String>,
303    pub gzip: Option<Option<u8>>,
304    pub flush: Option<String>,
305    pub condition: Option<Value>,
306}
307
308#[derive(Debug, Clone, PartialEq, Eq)]
309pub struct LimitExcept {
310    pub position: (Pos, Pos),
311    pub methods: Vec<String>,
312    pub directives: Vec<Directive>,
313}
314
315#[derive(Debug, Clone, PartialEq, Eq)]
316pub enum RealIpFrom {
317    Unix,
318    Ip(IpAddr),
319    Network(IpAddr, u8),
320}
321
322#[derive(Debug, Clone, Copy, PartialEq, Eq)]
323pub enum ErrorLevel {
324    Debug,
325    Info,
326    Notice,
327    Warn,
328    Error,
329    Crit,
330    Alert,
331    Emerg,
332}
333
334/// The enum which represents nginx config directive
335#[derive(Debug, Clone, PartialEq, Eq)]
336pub enum Item {
337    Daemon(bool),
338    MasterProcess(bool),
339    WorkerProcesses(WorkerProcesses),
340    Http(Http),
341    Server(Server),
342    Location(Location),
343    Listen(Listen),
344    ProxyPass(Value),
345    ProxySetHeader { field: Value, value: Value },
346    ProxyMethod(Value),
347    ProxyReadTimeout(Value),
348    ProxyConnectTimeout(Value),
349    ProxyHideHeader(Value),
350    ProxyPassHeader(Value),
351    ProxyPassRequestBody(bool),
352    ProxyPassRequestHeaders(bool),
353    ProxyHttpVersion(ProxyHttpVersion),
354    ProxyIgnoreHeaders(Vec<String>),
355    ProxyInterceptErrors(bool),
356    ProxyBuffering(bool),
357    ProxyCache(Value),
358    ProxyCacheKey(Value),
359    ProxyCacheValid(ProxyCacheValid),
360    ProxyNextUpstreamTries(Value),
361    ProxyNextUpstreamTimeout(Value),
362    ProxyNextUpstream(Vec<ProxyNextUpstreamFlag>),
363    Gzip(bool),
364    GzipStatic(GzipStatic),
365    GzipProxied(Vec<GzipProxied>),
366    AddHeader(AddHeader),
367    Expires(Expires),
368    Root(Value),
369    Alias(Value),
370    ErrorPage(ErrorPage),
371    DefaultType(Value),
372    ErrorLog { file: Value, level: Option<ErrorLevel>},
373    Rewrite(Rewrite),
374    Return(Return),
375    If(If),
376    TryFiles(TryFiles),
377    ServerName(Vec<ServerName>),
378    Set { variable: String, value: Value },
379    Map(Map),
380    ClientMaxBodySize(Value),
381    Include(Value),
382    EmptyGif,
383    Internal,
384    LimitExcept(LimitExcept),
385    Etag(bool),
386    RecursiveErrorPages(bool),
387    ChunkedTransferEncoding(bool),
388    KeepaliveTimeout(Value, Option<Value>),
389    ServerTokens(Value),
390    SslCertificate(Value),
391    SslCertificateKey(Value),
392    // openresty
393    RewriteByLuaFile(Value),
394    BalancerByLuaFile(Value),
395    AccessByLuaFile(Value),
396    HeaderFilterByLuaFile(Value),
397    ContentByLuaFile(Value),
398    BodyFilterByLuaFile(Value),
399    LogByLuaFile(Value),
400    LuaNeedRequestBody(Value),
401    SslCertificateByLuaFile(Value),
402    SslSessionFetchByLuaFile(Value),
403    SslSessionStoreByLuaFile(Value),
404    // access module
405    Allow(Source),
406    Deny(Source),
407    // log module
408    AccessLog(AccessLog),
409    // real_ip module
410    RealIpHeader(Value),
411    RealIpRecursive(bool),
412    SetRealIpFrom(RealIpFrom),
413    // index module
414    Index(Vec<Value>),
415}
416
417impl Item {
418
419    pub fn directive_name(&self) -> &'static str {
420        use self::Item::*;
421        match *self {
422            Daemon(..) => "daemon",
423            MasterProcess(..) => "master_process",
424            WorkerProcesses(..) => "worker_processes",
425            Http(..) => "http",
426            Server(..) => "server",
427            Location(..) => "location",
428            LimitExcept(..) => "limit_except",
429            Listen(..) => "listen",
430            ProxyPass(..) => "proxy_pass",
431            ProxySetHeader {..} => "proxy_set_header",
432            ProxyMethod {..} => "proxy_method",
433            ProxyReadTimeout {..} => "proxy_read_timeout",
434            ProxyConnectTimeout {..} => "proxy_connect_timeout",
435            ProxyHideHeader {..} => "proxy_hide_header",
436            ProxyPassHeader {..} => "proxy_pass_header",
437            ProxyPassRequestHeaders(..) => "proxy_pass_request_headers",
438            ProxyPassRequestBody(..) => "proxy_pass_request_body",
439            ProxyHttpVersion {..} => "proxy_http_version",
440            ProxyIgnoreHeaders(..) => "proxy_ignore_headers",
441            ProxyInterceptErrors(..) => "proxy_intercept_errors",
442            ProxyBuffering(..) => "proxy_buffering",
443            ProxyCache(..) => "proxy_cache",
444            ProxyCacheKey(..) => "proxy_cache_key",
445            ProxyCacheValid(..) => "proxy_cache_valid",
446            ProxyNextUpstreamTries(..) => "proxy_next_upstream_tries",
447            ProxyNextUpstreamTimeout(..) => "proxy_next_upstream_timeout",
448            ProxyNextUpstream(..) => "proxy_next_upstream",
449            Gzip(..) => "gzip",
450            GzipStatic(..) => "gzip_static",
451            GzipProxied(..) => "gzip_proxied",
452            AddHeader(..) => "add_header",
453            Expires(..) => "expires",
454            Root(..) => "root",
455            Alias(..) => "alias",
456            ErrorPage(..) => "error_page",
457            DefaultType(..) => "default_type",
458            ErrorLog {..} => "error_log",
459            Rewrite(..) => "rewrite",
460            Return(..) => "return",
461            If(..) => "if",
462            TryFiles(..) => "try_files",
463            ServerName(..) => "server_name",
464            Set { .. } => "set",
465            Map(..) => "map",
466            ClientMaxBodySize(..) => "client_max_body_size",
467            Include(..) => "include",
468            EmptyGif => "empty_gif",
469            Internal => "internal",
470            Etag(..) => "etag",
471            RecursiveErrorPages(..) => "recursive_error_pages",
472            ChunkedTransferEncoding(..) => "chunked_transfer_encoding",
473            KeepaliveTimeout(..) => "keepalive_timeout",
474            ServerTokens(..) => "server_tokens",
475            SslCertificate(..) => "ssl_certificate",
476            SslCertificateKey(..) => "ssl_certificate_key",
477            // openresty
478            RewriteByLuaFile(..) => "rewrite_by_lua_file",
479            BalancerByLuaFile(..) => "balancer_by_lua_file",
480            AccessByLuaFile(..) => "access_by_lua_file",
481            HeaderFilterByLuaFile(..) => "header_filter_by_lua_file",
482            ContentByLuaFile(..) => "content_by_lua_file",
483            BodyFilterByLuaFile(..) => "body_filter_by_lua_file",
484            LogByLuaFile(..) => "log_by_lua_file",
485            LuaNeedRequestBody(..) => "lua_need_request_body",
486            SslCertificateByLuaFile(..) => "ssl_certificate_by_lua_file",
487            SslSessionFetchByLuaFile(..) => "ssl_session_fetch_by_lua_file",
488            SslSessionStoreByLuaFile(..) => "ssl_session_store_by_lua_file",
489            // access module
490            Allow(..) => "allow",
491            Deny(..) => "deny",
492            // log module
493            AccessLog(..) => "access_log",
494            // real_ip module
495            RealIpHeader(..) => "real_ip_header",
496            RealIpRecursive(..) => "real_ip_recursive",
497            SetRealIpFrom(..) => "set_real_ip_from",
498            // index module
499            Index(..) => "index",
500        }
501    }
502
503    pub fn children(&self) -> Option<&[Directive]> {
504        use self::Item::*;
505        match *self {
506            Daemon(_) => None,
507            MasterProcess(_) => None,
508            WorkerProcesses(_) => None,
509            Http(ref h) => Some(&h.directives[..]),
510            Server(ref s) => Some(&s.directives[..]),
511            Location(ref l) => Some(&l.directives[..]),
512            LimitExcept(ref l) => Some(&l.directives[..]),
513            Listen(_) => None,
514            ProxyPass(_) => None,
515            ProxyPassRequestHeaders(..) => None,
516            ProxyPassRequestBody(..) => None,
517            ProxySetHeader {..} => None,
518            ProxyMethod {..} => None,
519            ProxyReadTimeout {..} => None,
520            ProxyConnectTimeout {..} => None,
521            ProxyHideHeader {..} => None,
522            ProxyPassHeader {..} => None,
523            ProxyHttpVersion {..} => None,
524            ProxyIgnoreHeaders(..) => None,
525            ProxyInterceptErrors(..) => None,
526            ProxyBuffering(..) => None,
527            ProxyCache(..) => None,
528            ProxyCacheKey(..) => None,
529            ProxyCacheValid(..) => None,
530            ProxyNextUpstreamTries(..) => None,
531            ProxyNextUpstreamTimeout(..) => None,
532            ProxyNextUpstream(..) => None,
533            Gzip(..) => None,
534            GzipStatic(..) => None,
535            GzipProxied(..) => None,
536            AddHeader(..) => None,
537            Expires(..) => None,
538            Root(..) => None,
539            Alias(..) => None,
540            ErrorPage(..) => None,
541            DefaultType(..) => None,
542            ErrorLog {..} => None,
543            Rewrite(..) => None,
544            Return(..) => None,
545            If(ref val) => Some(&val.directives),
546            TryFiles(..) => None,
547            ServerName(..) => None,
548            Set { .. } => None,
549            Map(..) => None,
550            ClientMaxBodySize(..) => None,
551            Include(..) => None,
552            EmptyGif => None,
553            Internal => None,
554            Etag(..) => None,
555            RecursiveErrorPages(..) => None,
556            ChunkedTransferEncoding(..) => None,
557            KeepaliveTimeout(..) => None,
558            ServerTokens(..) => None,
559            SslCertificate(..) => None,
560            SslCertificateKey(..) => None,
561            // openresty
562            RewriteByLuaFile(..) => None,
563            BalancerByLuaFile(..) => None,
564            AccessByLuaFile(..) => None,
565            HeaderFilterByLuaFile(..) => None,
566            ContentByLuaFile(..) => None,
567            BodyFilterByLuaFile(..) => None,
568            LogByLuaFile(..) => None,
569            LuaNeedRequestBody(..) => None,
570            SslCertificateByLuaFile(..) => None,
571            SslSessionFetchByLuaFile(..) => None,
572            SslSessionStoreByLuaFile(..) => None,
573            // access
574            Allow(..) => None,
575            Deny(..) => None,
576            // log module
577            AccessLog(..) => None,
578            // real_ip module
579            RealIpHeader(..) => None,
580            RealIpRecursive(..) => None,
581            SetRealIpFrom(..) => None,
582            // index module
583            Index(..) => None,
584        }
585    }
586
587    pub fn children_mut(&mut self) -> Option<&mut Vec<Directive>> {
588        use self::Item::*;
589        match *self {
590            Daemon(_) => None,
591            MasterProcess(_) => None,
592            WorkerProcesses(_) => None,
593            Http(ref mut h) => Some(&mut h.directives),
594            Server(ref mut s) => Some(&mut s.directives),
595            Location(ref mut l) => Some(&mut l.directives),
596            LimitExcept(ref mut l) => Some(&mut l.directives),
597            Listen(_) => None,
598            ProxyPass(_) => None,
599            ProxySetHeader {..} => None,
600            ProxyMethod {..} => None,
601            ProxyReadTimeout {..} => None,
602            ProxyConnectTimeout {..} => None,
603            ProxyHideHeader {..} => None,
604            ProxyPassHeader {..} => None,
605            ProxyPassRequestHeaders(_) => None,
606            ProxyPassRequestBody(_) => None,
607            ProxyHttpVersion {..} => None,
608            ProxyIgnoreHeaders {..} => None,
609            ProxyInterceptErrors {..} => None,
610            ProxyBuffering(..) => None,
611            ProxyCache {..} => None,
612            ProxyCacheKey {..} => None,
613            ProxyCacheValid {..} => None,
614            ProxyNextUpstreamTries(..) => None,
615            ProxyNextUpstreamTimeout(..) => None,
616            ProxyNextUpstream(..) => None,
617            Gzip(..) => None,
618            GzipStatic(..) => None,
619            GzipProxied(..) => None,
620            AddHeader(..) => None,
621            Expires(..) => None,
622            Root(..) => None,
623            Alias(..) => None,
624            ErrorPage(..) => None,
625            DefaultType(..) => None,
626            ErrorLog {..} => None,
627            Rewrite(..) => None,
628            Return(..) => None,
629            If(ref mut val) => Some(&mut val.directives),
630            TryFiles(..) => None,
631            ServerName(..) => None,
632            Set { .. } => None,
633            Map(..) => None,
634            ClientMaxBodySize(..) => None,
635            Include(..) => None,
636            EmptyGif => None,
637            Internal => None,
638            Etag(..) => None,
639            RecursiveErrorPages(..) => None,
640            ChunkedTransferEncoding(..) => None,
641            KeepaliveTimeout(..) => None,
642            ServerTokens(..) => None,
643            SslCertificate(..) => None,
644            SslCertificateKey(..) => None,
645            // openresty
646            RewriteByLuaFile(..) => None,
647            BalancerByLuaFile(..) => None,
648            AccessByLuaFile(..) => None,
649            HeaderFilterByLuaFile(..) => None,
650            ContentByLuaFile(..) => None,
651            BodyFilterByLuaFile(..) => None,
652            LogByLuaFile(..) => None,
653            LuaNeedRequestBody(..) => None,
654            SslCertificateByLuaFile(..) => None,
655            SslSessionFetchByLuaFile(..) => None,
656            SslSessionStoreByLuaFile(..) => None,
657            // access
658            Allow(..) => None,
659            Deny(..) => None,
660            // log module
661            AccessLog(..) => None,
662            // real_ip module
663            RealIpHeader(..) => None,
664            RealIpRecursive(..) => None,
665            SetRealIpFrom(..) => None,
666            // index module
667            Index(..) => None,
668        }
669    }
670
671    /// Executes function on all the Value things (not recursively)
672    ///
673    /// This is useful for substituting variables.
674    ///
675    /// The callback isn't called for directives inside the  `{ block }`, so
676    /// this function might be better used with [`visit_mutable`]
677    ///
678    /// [`visit_mutable`]: ../visitors/fn.visit_mutable.html
679    pub(crate) fn visit_values_mut<F>(&mut self, mut f: F)
680        where F: FnMut(&mut Value)
681    {
682        use self::Item::*;
683        match *self {
684            Daemon(_) => {},
685            MasterProcess(_) => {},
686            WorkerProcesses(_) => {},
687            Http(_) => {},
688            Server(_) => {},
689            Location(_) => {},
690            LimitExcept(_) => {},
691            Listen(_) => {},
692            ProxyPass(ref mut v) => f(v),
693            ProxySetHeader { ref mut field, ref mut value } => {
694                f(field);
695                f(value);
696            }
697            ProxyMethod(ref mut v) => f(v),
698            ProxyReadTimeout(ref mut v) => f(v),
699            ProxyConnectTimeout(ref mut v) => f(v),
700            ProxyHideHeader(ref mut v) => f(v),
701            ProxyPassHeader(ref mut v) => f(v),
702            ProxyCache(ref mut v) => f(v),
703            ProxyCacheKey(ref mut v) => f(v),
704            ProxyCacheValid(self::ProxyCacheValid::Normal(ref mut v)) => f(v),
705            ProxyCacheValid(self::ProxyCacheValid::Specific(_, ref mut v)) => f(v),
706            ProxyCacheValid(self::ProxyCacheValid::Any(ref mut v)) => f(v),
707            ProxyPassRequestHeaders(_) => {},
708            ProxyPassRequestBody(_) => {},
709            ProxyHttpVersion(..) => {},
710            ProxyIgnoreHeaders(..) => {},
711            ProxyInterceptErrors(..) => {},
712            ProxyBuffering(..) => {},
713            ProxyNextUpstreamTries(ref mut v) => f(v),
714            ProxyNextUpstreamTimeout(ref mut v) => f(v),
715            ProxyNextUpstream(_) => {},
716            Gzip(_) => {},
717            GzipStatic(_) => {},
718            GzipProxied(_) => {},
719            AddHeader(self::AddHeader { ref mut field, ref mut value, .. })
720            => {
721                f(field);
722                f(value);
723            }
724            Expires(self::Expires { ref mut value, .. }) => f(value),
725            Root(ref mut v) => f(v),
726            Alias(ref mut v) => f(v),
727            ErrorPage(::ast::ErrorPage { ref mut uri, .. }) => f(uri),
728            DefaultType(ref mut v) => f(v),
729            ErrorLog { ref mut file, .. } => f(file),
730            Rewrite(ref mut rw) => f(&mut rw.replacement),
731            Return(::ast::Return::Redirect { ref mut url, .. }) => f(url),
732            Return(::ast::Return::Text { text: Some(ref mut t), .. }) => f(t),
733            Return(::ast::Return::Text { text: None, .. }) => {},
734            If(self::If { ref mut condition, .. }) => {
735                use self::IfCondition::*;
736                match condition {
737                    NonEmpty(ref mut v) => f(v),
738                    Eq(ref mut v, _) => f(v),
739                    Neq(ref mut v, _) => f(v),
740                    RegEq(ref mut v, _, _) => f(v),
741                    RegNeq(ref mut v, _, _) => f(v),
742                    Exists(ref mut v) => f(v),
743                    NotExists(ref mut v) => f(v),
744                    FileExists(ref mut v) => f(v),
745                    FileNotExists(ref mut v) => f(v),
746                    DirExists(ref mut v) => f(v),
747                    DirNotExists(ref mut v) => f(v),
748                    Executable(ref mut v) => f(v),
749                    NotExecutable(ref mut v) => f(v),
750                }
751            },
752            TryFiles(ref mut tf) => {
753                for opt in &mut tf.options {
754                    f(opt);
755                }
756                match tf.last_option {
757                    TryFilesLastOption::Uri(ref mut v) => f(v),
758                    TryFilesLastOption::NamedLocation(..) => {},
759                    TryFilesLastOption::Code(..) => {},
760                }
761            },
762            Include(ref mut v) => f(v),
763            EmptyGif => {}
764            Internal => {}
765            Etag(..) => {}
766            RecursiveErrorPages(..) => {}
767            ChunkedTransferEncoding(..) => {}
768            KeepaliveTimeout(ref mut a, ref mut b) => {
769                f(a);
770                if let Some(b) = b {
771                    f(b);
772                }
773            }
774            ServerTokens(ref mut v) => f(v),
775            SslCertificate(ref mut v) => f(v),
776            SslCertificateKey(ref mut v) => f(v),
777            ServerName(_) => {},
778            Set { ref mut value, .. } => f(value),
779            Map(::ast::Map {
780                ref mut expression,
781                ref mut default,
782                ref mut patterns,
783                ..
784            }) => {
785                f(expression);
786                if let Some(ref mut def) = default {
787                    f(def);
788                }
789                for (_, v) in patterns {
790                    f(v);
791                }
792            }
793            ClientMaxBodySize(ref mut v) => f(v),
794            // openresty
795            RewriteByLuaFile(ref mut v) => f(v),
796            BalancerByLuaFile(ref mut v) => f(v),
797            AccessByLuaFile(ref mut v) => f(v),
798            HeaderFilterByLuaFile(ref mut v) => f(v),
799            ContentByLuaFile(ref mut v) => f(v),
800            BodyFilterByLuaFile(ref mut v) => f(v),
801            LogByLuaFile(ref mut v) => f(v),
802            LuaNeedRequestBody(ref mut v) => f(v),
803            SslCertificateByLuaFile(ref mut v) => f(v),
804            SslSessionFetchByLuaFile(ref mut v) => f(v),
805            SslSessionStoreByLuaFile(ref mut v) => f(v),
806            // access
807            Allow(..) => {},
808            Deny(..) => {},
809            // log module
810            AccessLog(::ast::AccessLog::Off) => {},
811            AccessLog(::ast::AccessLog::On(ref mut lg)) => {
812                f(&mut lg.path);
813                lg.condition.as_mut().map(f);
814            },
815            // real_ip module
816            RealIpHeader(ref mut v) => f(v),
817            RealIpRecursive(..) => {},
818            SetRealIpFrom(..) => {},
819            // index module
820            Index(ref mut items) => {
821                for v in items {
822                    f(v);
823                }
824            }
825        }
826    }
827}
828
829impl Directive {
830    /// Executes function on all the Value things (not recursively)
831    ///
832    /// This is useful for substituting variables.
833    ///
834    /// The callback isn't called for directives inside the  `{ block }`, so
835    /// this function might be better used with [`visit_mutable`]
836    ///
837    /// [`visit_mutable`]: ../visitors/fn.visit_mutable.html
838    pub fn visit_values_mut<F>(&mut self, f: F)
839        where F: FnMut(&mut Value)
840    {
841        self.item.visit_values_mut(f)
842    }
843}
844
845impl Main {
846    pub fn all_directives(&self) -> DirectiveIter {
847        DirectiveIter::depth_first(&self.directives)
848    }
849}