解析规则
- 精确匹配的路径 location = /{}
(exact_match = 1 )
- 抢占式前缀匹配的路径 location ^~ /{}
(noregex = 1)
- 命名路径,比如location @a {}
(named = 1)
普通前端匹配的路径,例如location / {}
无名路径,比如if {}或者limit_except {}生成的路径
noname = 1
正则路径 regex != NULL
解析之后格式
{
"http":{
"servers":[
{
"server_name":"www.didichuxing.com",
"port":80,
"locations":[
{
"location":"/index",
"upstream_name":"upstream_index_com",
"upstream_servers":"127.0.0.1:8000, 127.0.0.1:80001"
},
{
"location":"/home",
"upstream_name":"upstream_index_com",
"upstream_servers":"127.0.0.1:8000, 127.0.0.1:80001"
},
{
"location":"/test",
"upstream_name":"upstream_test_com",
"upstream_servers":"127.0.0.1:8000, 127.0.0.1:80001"
}
]
},
{
"server_name":"www.udache.com",
"port":80,
"locations":[
{
"location":"^/orderby",
"upstream_name":"upstream_test_com",
"upstream_servers":"127.0.0.1:8000, 127.0.0.1:80001"
},
{
"location":"^/list",
"upstream_name":"upstream_test_com",
"upstream_servers":"127.0.0.1:8000, 127.0.0.1:80001"
}
]
}
]
}
}
核心源码
static ngx_str_t HTTP_KEY = "http"
static ngx_str_t SERVERS_KEY = "servers"
static ngx_str_t SERVER_NAME_KEY = "server_name";
static ngx_str_t SERVER_PORT_KEY = "server_port";
static ngx_str_t LOCATIONS_KEY = "locations";
static ngx_str_t LOCATION_KEY = "location";
static void
ngx_http_lua_conf_get_static_locations(yajl_gen g, ngx_http_location_tree_node_t *node)
{
if ( node == NULL ) {
return;
}
yajl_gen_string(g, (const unsigned char *) LOCATION_KEY, strlen(LOCATION_KEY));
yajl_gen_string(g, (unsigned char *)node->name, node->len);
if ( node->left ) {
return ngx_http_lua_conf_get_static_locations(g, node->left);
}
if ( node->right ) {
return ngx_http_lua_conf_get_static_locations(g, node->right);
}
}
//获取正则locations
static void
ngx_http_lua_conf_get_regex_locations(yajl_gen g, ngx_http_core_loc_conf_t **clcfp)
{
if ( clcfp ) {
return;
}
for ( ; *clcfp; clcfp++) {
yajl_gen_string(g, (const unsigned char *) LOCATION_KEY, strlen(LOCATION_KEY));
yajl_gen_string(g, (unsigned char *)(*clcfp)->name.data , (*clcfp)->name.len);
}
}
/*
{
"http":{
"servers":[
{
"server_name": [
"www.didichuxing.com"
],
"port":80,
"locations":[
"location":"/index",
"location":"/home"
]
}
]
}
}
*/
//获取servers,server_name,server_port,location对应关系
static int
ngx_http_lua_ngx_get_conf(lua_State *L)
{
size_t s, i, j, n;
size_t len;
ngx_http_conf_addr_t *addr;
ngx_http_conf_port_t *port;
const unsigned char *buf;
ngx_http_request_t *r;
ngx_http_core_main_conf_t *cmcf;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t **server;
ngx_http_server_name_t *name;
yajl_gen g;
yajl_gen_status status;
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request object found");
}
g = yajl_gen_alloc(NULL);
if ( g == NULL ) {
return NGX_ERROR;
}
yajl_gen_config(g, yajl_gen_beautify, 0);
yajl_gen_map_open(g);
//http
yajl_gen_string(g, (unsigned char *)HTTP_KEY, strlen(HTTP_KEY));
yajl_gen_map_open(g);
//servers
yajl_gen_string(g, (unsigned char *)SERVERS_KEY, ngx_strlen(SERVERS_KEY));
yajl_gen_array_open(g);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
port = cmcf->ports->elts;
for (s = 0; s < cmcf->ports->nelts; s++) {
addr = port[s].addrs.elts;
for (i = 0; i < port[s].addrs.nelts; i++) {
server = addr[i].servers.elts;
for (j = 0; j < addr[i].servers.nelts; j++) {
yajl_gen_map_open(g);
name = server[j]->server_names.elts;
for (n = 0; n < server[j]->server_names.nelts; n++) {
//server_name
yajl_gen_string(g, (unsigned char *)SERVER_NAME_KEY, ngx_strlen(SERVER_NAME_KEY));
yajl_gen_string(g, (unsigned char *)name[n].name.data, name[n].name.len);
//server_port
yajl_gen_string(g, (unsigned char *) SERVER_PORT_KEY, strlen(SERVER_PORT_KEY));
yajl_gen_string(g, (unsigned char *) addr[i].opt.addr, ngx_strlen(addr[i].opt.addr));
}
clcf = server[j]->ctx->loc_conf[ngx_http_core_module.ctx_index];
yajl_gen_string(g, (unsigned char *) LOCATIONS_KEY, ngx_strlen(LOCATIONS_KEY));
yajl_gen_array_open(g);
ngx_http_lua_conf_get_static_locations(g, clcf->static_locations);
ngx_http_lua_conf_get_regex_locations(g, clcf->regex_locations);
yajl_gen_array_close(g);
yajl_gen_map_close(g);
}
}
}
yajl_gen_array_close(g);
yajl_gen_map_close(g);
yajl_gen_map_close(g);
status = yajl_gen_get_buf(g, &buf, &len);
if(status != yajl_gen_status_ok) {
yajl_gen_free(g);
lua_pushnil(L);
return 1;
}
lua_pushlstring(L, (char *) buf, len);
return 1;
}
//格式化后的结果
{
"http":{
"servers":[
{
"server_name":[
"localhost"
],
"server_port":"0.0.0.0:8012",
"locations":[
"/search"
]
},
{
"server_name":[
"www.test.com",
"www.test1.com"
],
"server_port":"0.0.0.0:80",
"locations":[
"/test"
]
},
{
"server_name":[
"www.baidu.com"
],
"server_port":"0.0.0.0:80",
"locations":[
"/didi/",
"/aaa",
"/baidu/",
"/cccc/"
]
}
]
}
}
测试配置
#nginx.conf
server {
listen 8012;
server_name localhost;
location /search {
content_by_lua_block {
local body = ngx.config.get_conf();
ngx.say(body);
}
}
}
upstream upstream_test_com {
server 111.13.101.208:80;
}
server {
listen 80;
server_name www.test.com www.test1.com;
location =/test {
proxy_pass http://upstream_test_com;
}
}
server {
listen 80;
server_name www.baidu.com;
location = /aaa {
proxy_pass http://111.13.101.208:80;
}
location ^~ /didi/ {
proxy_pass http://111.13.101.208:80;
}
location ~ /baidu/ {
proxy_pass http://111.13.101.208:80;
}
location ~* /cccc/ {
proxy_pass http://111.13.101.208:80;
}
}