Let's say an upstream, proxied by nginx, sets a cookie foo=bar in its HTTP response. To use this cookie name as a variable in nginx configuration, use the magic prefix $cookie_ and the variable becomes $cookie_foo. But how did a cookie become a variable? I call it a magic variable. It could also be called an arbitrary variable.
nginx publishes its complete list of variables. Notice how some variables end in an underscore, which as of writing are,
- $arg_ (ngx_http_core_module)
- $cookie_ (ngx_http_core_module)
- $http_ (ngx_http_core_module)
- $jwt_claim_ (ngx_http_auth_jwt_module)
- $jwt_header_ (ngx_http_auth_jwt_module)
- $sent_http_ (ngx_http_core_module)
- $sent_trailer_ (ngx_http_core_module)
- $upstream_cookie_ (ngx_http_upstream_module)
- $upstream_http_ (ngx_http_upstream_module)
- $upstream_trailer_ (ngx_http_upstream_module)
These are variable name prefixes (for want of a better terminology). Their respective modules create magic or arbitrary variables from the suffix, which has a special meaning to the module.
In our example, the cookie name foo becomes the suffix which ngx_http_core_module uses to create the variable $cookie_foo. We don't have to explicitly create or set this variable; it is available for us to use.
Both $upstream_header_time and $upstream_http_server are examples of embedded variables (provided by ngx_http_upstream_module). Since $upstream_http_ is in our list above, it is an embedded and a magic (arbitrary) variable. The "magic" part comes from the suffix server which is the value from the HTTP response header, Server. Meanwhile, $upstream_header_time is only an embedded variable.
Read the official documentation for more information.