daemon off;
error_log stderr;
worker_processes auto;

events {
    multi_accept on;
    worker_connections 10000;
}

http {
    server_tokens off;
    client_body_timeout 3;
    client_header_timeout 3;

    client_body_buffer_size 256k;
    client_max_body_size 256k;

    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    log_format json_combined "{"
    '"timestamp":"$time_iso8601",'
    '"remote_addr":"$remote_addr",'
    '"request":"$request",'
    '"status":$status,'
    '"body_bytes_sent":$body_bytes_sent,'
    '"request_time":$request_time,'
    '"http_referrer":"$http_referer",'
    '"http_user_agent":"$http_user_agent",'
    '"x_amzn_trace_id":"$http_x_amzn_trace_id",'
    '"x_forwarded_for":"$http_x_forwarded_for",'
    '"x_jussi_cache_hit":"$upstream_http_x_jussi_cache_hit",'
    '"x_jussi_request_id":"$upstream_http_x_jussi_request_id",'
    '"x_jussi_response_time":"$upstream_http_x_jussi_response_time",'
    '"x_jussi_namespace":"$upstream_http_x_jussi_namespace",'
    '"x_jussi_api":"$upstream_http_x_jussi_api",'
    '"x_jussi_method":"$upstream_http_x_jussi_method",'
    '"x_jussi_params":"$upstream_http_x_jussi_params",'
    '"x_jussi_success":"$upstream_http_x_jussi_success",'
    '"upstream_connect_time":$upstream_connect_time,'
    '"upstream_response_time":$upstream_response_time,'
    '"upstream_header_time":$upstream_header_time,'
    '"upstream_response_length":$upstream_response_length,'
    '"gzip_ratio":"$gzip_ratio"'
    '}';

    access_log /dev/stdout json_combined buffer=32k flush=5s;

    keepalive_timeout 150;
    keepalive_requests 2000;

    tcp_nopush       on;
    tcp_nodelay      on;

    proxy_redirect off;
    proxy_buffering on;

    proxy_buffers 32 8k;

    proxy_ignore_client_abort on;

    proxy_max_temp_file_size 0;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_connect_timeout 1;
    proxy_read_timeout 100;

    proxy_hide_header x-jussi-response-time;
    proxy_hide_header x-jussi-namespace;
    proxy_hide_header x-jussi-api;
    proxy_hide_header x-jussi-method;
    proxy_hide_header x-jussi-params;

    gzip_types application/json;
    gzip_min_length 1000;
    gzip on;

    upstream jussi_upstream {
        server 127.0.0.1:9000;
        keepalive 1000;
    }

    server {
        listen 7777;
        server_name jussi_monitor;

        # nginx status only from localhost
        location = /nginx_status {
            limit_except GET HEAD OPTIONS {
                deny all;
            }
            access_log off;
            stub_status on;
        }

        # jussi monitor only from localhost
        location = /monitor {
            limit_except GET HEAD OPTIONS {
                deny all;
            }
            access_log off;
            set_by_lua_block $x_jussi_request_id {
                string.format('%018d',math.random(999999999999999999))
            }
            proxy_set_header x-jussi-request-id $x_jussi_request_id;
            proxy_pass http://jussi_upstream/monitor;
        }
    }

    server {
        listen  8080 backlog=16384;
        server_name jussi;

        add_header Access-Control-Allow-Origin "*";
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
        add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range";
        add_header Strict-Transport-Security "max-age=31557600; includeSubDomains; preload" always;
        add_header 'Content-Security-Policy' 'upgrade-insecure-requests';

        # catch all
        location / {
            access_log off;
            return 403;
        }

        # redirect to health
        location = /.well-known/healthcheck.json {
            limit_except GET {
                deny all;
            }
            rewrite ^.+ /health last;
        }

        # proxy GET /health requests to jussi
        location = /health {
            access_log off;
            limit_except GET HEAD {
                deny all;
            }
            add_header Access-Control-Allow-Origin "*";
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
            add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range";
            add_header Strict-Transport-Security "max-age=31557600; includeSubDomains; preload" always;
            add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
            proxy_pass http://jussi_upstream;

        }

        # redirect GET / requests to /health
        location = /GET {
            limit_except GET {
                deny all;
            }
            rewrite ^.+ /health last;
        }

        # handle HEAD requests in nginx
        location = /HEAD {
            access_log off;
            limit_except HEAD {
                deny all;
            }
            add_header Access-Control-Allow-Origin "*";
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
            add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range";
            add_header Strict-Transport-Security "max-age=31557600; includeSubDomains; preload" always;
            add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
            add_header x-jussi-request-id $x_jussi_request_id;
            return 200;
        }

        # handle OPTIONS requests in nginx
        location = /OPTIONS {
            access_log off;
            limit_except OPTIONS {
                deny all;
            }
            add_header 'Allow' 'GET,HEAD,OPTIONS,POST';
            add_header Access-Control-Allow-Origin "*";
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
            add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range";
            add_header Strict-Transport-Security "max-age=31557600; includeSubDomains; preload" always;
            add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
            add_header x-jussi-request-id $x_jussi_request_id;
            return 200;
        }

        # proxy JSONRPC requests to jussi
        location = /POST {
            limit_except POST {
                deny all;
            }
            add_header Access-Control-Allow-Origin "*";
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
            add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range";
            add_header Strict-Transport-Security "max-age=31557600; includeSubDomains; preload" always;
            add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
            proxy_set_header x-jussi-request-id $x_jussi_request_id;
            proxy_pass http://jussi_upstream/;

            set $max_chunk_size 10240;  # Chunks of 10 KB
            set $max_body_size 262144;  # Max inflated body size of 256 KB
            rewrite_by_lua_file /etc/service/nginx/inflate_body.lua;
        }

        # redirect / requests to /<HTTP METHOD>
        location = / {
            limit_except GET POST HEAD OPTIONS {
                deny all;
            }
            set_by_lua_block $x_jussi_request_id {
                string.format('%018d',math.random(999999999999999999))
            }
            rewrite ^/$ /$request_method last;
        }
    }
}
