How to detect ssl in shared 80 / 443 ssl nginx server config?

When nginx server is configured this way:

server {
  listen 80;
  listen 443 ssl;
  server_name www.example.org;
  ...
}

how can be detected that the request came via HTTP or HTTPS?

(E.g. $http_port is unusable, because the port is not specified explicitly, therefore it's empty)


Solution 1:

http://nginx.org/en/docs/http/ngx_http_core_module.html#variables

  • $https — “on” if connection operates in SSL mode, or an empty string otherwise
  • $scheme — request scheme, “http” or “https”

For example, if you want to limit a location to https and only:

location /admin {
    if ($https = "") {
        return 404;
    }
    # ... and so on
}

Solution 2:

Why not separate each into their own server directive and specify a log per server context:

server {
  listen           80;
  server_name      www.nginx.org;
  log_format gzip '$remote_addr - $remote_user [$time_local]  '
                  '"$request" $status $bytes_sent '
                  '"$http_referer" "$http_user_agent" "$gzip_ratio"';

  access_log  /spool/logs/nginx-access.log  gzip  buffer=32k;
  error_log /var/log/nginx/nginx-error.log error;
}

server {
  listen           443 default_server ssl;
  server_name      secure.nginx.org;
  log_format gzip '$remote_addr - $remote_user [$time_local]  '
                  '"$request" $status $bytes_sent '
                  '"$http_referer" "$http_user_agent" "$gzip_ratio"';

  access_log  /var/log/nginx/nginx_ssl-access.log  gzip  buffer=32k;
  error_log /var/log/nginx/nginx_ssl-error.log error;
}

You could then view each log separately to see where the access or error came from.