[PATCH] implement a $location variable

David Gwynne david at gwynne.id.au
Mon Oct 15 01:22:00 UTC 2012


this patch is actually from piotr sikora, and is part of coolkit already. this is just a port of it to stock nginx.

this makes the part of the request uri that matches the locations name available as a variable within a block. eg if you have location /foo { } and request /foo/bar/foo, $location will have the value /foo. if you have location ^~ /(foo|bar) and request /foo/bar/foo, $location will still have /foo in it. think of it as $0 for regex locations, but it works for non-regex location names too.

im running this in production now and its working great. it allows me to treat the locations name as a parameter to an applications front end controller without having to repeat the value within a location block.

cheers,
dlg

--- src/http/ngx_http_variables.c.orig  Tue Jul  3 03:41:52 2012
+++ src/http/ngx_http_variables.c       Thu Aug 23 10:32:22 2012
@@ -65,6 +65,8 @@ static ngx_int_t ngx_http_variable_request_filename(ng
  ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r,
  ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_location(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
  ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
@@ -206,6 +208,10 @@ static ngx_http_variable_t  ngx_http_core_variables[] 

  { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },

+    { ngx_string("location"), NULL,
+      ngx_http_variable_location, 0,
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
  { ngx_string("request_method"), NULL,
    ngx_http_variable_request_method, 0,
    NGX_HTTP_VAR_NOCACHEABLE, 0 },
@@ -1382,6 +1388,39 @@ ngx_http_variable_server_name(ngx_http_request_t *r,
  v->no_cacheable = 0;
  v->not_found = 0;
  v->data = cscf->server_name.data;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_variable_location(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    ngx_http_core_loc_conf_t  *clcf;
+    ngx_int_t                  rc;
+    int                        captures[3];
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (clcf->regex) {
+        rc = ngx_regex_exec(clcf->regex->regex, &r->uri, captures, 3);
+
+        if (rc == NGX_REGEX_NO_MATCHED) {
+            return NGX_ERROR;
+        }
+
+        v->data = r->uri.data + captures[0];
+        v->len = captures[1] - captures[0];
+
+    } else {
+        v->data = clcf->name.data;
+        v->len = clcf->name.len;
+    }
+
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;

  return NGX_OK;
}


More information about the nginx-devel mailing list