{{ range $server:=.Servers }}
server {
    {{ if .Listen }}listen    {{.Listen}};{{ end }}
    {{ if .Root }}root    {{.Root}};{{ end }}
    {{ if .ServerName }}server_name    {{.ServerName}};{{end}}
	{{ if .DefaultType }}default_type    {{.DefaultType}};{{end}}
    {{ if .Charset }}charset   {{.Charset}};{{end}}
    access_log off;
    {{ if gt .KeepaliveTimeout.Num 0 }}
    keepalive_timeout {{.KeepaliveTimeout.Num}}{{.KeepaliveTimeout.Unit}};
    {{ end }}

    {{ if .ServerTokens }}server_tokens on;{{ end }}

    {{ if .SSLCertificate }}
    # ssl
    ssl_certificate {{.SSLCertificate}};
    {{ if .SSLProtocols }}
    ssl_protocols {{.SSLProtocols}};
    {{ end }}
    {{ if .EnableSSLStapling }}
    ssl_stapling on;
    resolver 8.8.8.8 8.8.4.4 114.114.114.114 valid=300s;
    resolver_timeout 5s;
    {{ end }}
    {{ end }}
    {{ if .SSLCertificateKey }}ssl_certificate_key {{.SSLCertificateKey}};{{ end }}

    {{ if .ClientMaxBodySize.Unit }}
    client_max_body_size {{.ClientMaxBodySize.Num}}{{.ClientMaxBodySize.Unit}};
    {{ end }}
    {{ if .ChunkedTransferEncoding }}
    chunked_transfer_encoding on;
    {{ end }}

    {{ range $rewrite := .Rewrites }}
    rewrite {{$rewrite.Regex}} {{$rewrite.Replacement}}{{if $rewrite.Flag }} {{$rewrite.Flag}}{{ end }};
    {{ end }}

    {{ if ne .Return.Code 0 }}
    return {{ .Return.Code }} {{ if .Return.Text}} "{{ .Return.Text }}" {{ else if .Return.URL }} {{.Return.URL}} {{ end }};
    {{ end }}

    {{ if gt .ProxyConnectTimeout.Num 0 }}
    proxy_connect_timeout   {{.ProxyConnectTimeout.Num}}{{.ProxyConnectTimeout.Unit}};
    {{ end }}
    {{ if gt .ProxyTimeout.Num 0 }}
    proxy_timeout   {{.ProxyTimeout.Num}}{{.ProxyTimeout.Unit}};
    {{ end }}
    {{ if .ProxyPass }}
    proxy_pass {{.ProxyPass}};
    {{ end }}

    {{ range $loc := .Locations }}
    location {{$loc.Path}} {
        {{ range $rewrite := $loc.Rewrite.Rewrites }}
        rewrite {{$rewrite.Regex}} {{$rewrite.Replacement}}{{if $rewrite.Flag }} {{$rewrite.Flag}}{{ end }};
        {{ end }}
        set $pass_access_scheme  $scheme;
        set $best_http_host $http_host;
        set $pass_port $server_port;
        
        # custom proxy_set_header
        {{ range $k, $v := $loc.Proxy.SetHeaders }}
        proxy_set_header    {{$k}}    {{$v}};
        {{ end }}
        proxy_connect_timeout                   {{ $loc.Proxy.ConnectTimeout }}s;
        proxy_send_timeout                      {{ $loc.Proxy.SendTimeout }}s;
        proxy_read_timeout                      {{ $loc.Proxy.ReadTimeout }}s;

        proxy_buffering                         {{ $loc.Proxy.ProxyBuffering }};
        proxy_buffer_size                       {{ $loc.Proxy.BufferSize }};
        proxy_buffers                           {{ $loc.Proxy.BuffersNumber }} {{ $loc.Proxy.BufferSize }};
        proxy_request_buffering                 {{ $loc.Proxy.RequestBuffering }};

        proxy_http_version                      1.1;

        proxy_cookie_domain                     {{ $loc.Proxy.CookieDomain }};
        proxy_cookie_path                       {{ $loc.Proxy.CookiePath }};

        client_max_body_size        {{ $loc.Proxy.BodySize }}m;

        {{ if $loc.DisableAccessLog }}
        access_log off;
        {{ else if $loc.AccessLogPath }}
        access_log {{$loc.AccessLogPath}} proxy;
        {{ end }}
        
        {{ if $loc.ProxyRedirect }}
        proxy_redirect {{$loc.ProxyRedirect}};
        {{ end }}
        {{ if not $loc.DisableProxyPass }}
            set $target 'default';
            {{ if $server.OptionValue }}
                {{range $i, $v := $server.OptionValue}}
                    set ${{$i}} '{{$v}}';
                {{end}}
            {{ end }}
            {{ buildLuaHeaderRouter $loc }}
            {{ if $loc.PathRewrite }}
              proxy_pass http://upstream_balancer/;
            {{ else }}
              proxy_pass http://upstream_balancer;
            {{ end }}
        {{ end }}
        log_by_lua_block {
            balancer.log()
            {{ if $loc.EnableMetrics }}
            monitor.call()
            {{ end }}
        }
        {{ if $loc.Return.Code }}
        return {{$loc.Return.Code}} {{$loc.Return.Text}} {{$loc.Return.URL}};
        {{ end }}
    }
    {{ end }}
}
{{ end }}