/* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_lua_ndk.h" #include "ngx_http_lua_util.h" #if defined(NDK) && NDK static ndk_set_var_value_pt ngx_http_lookup_ndk_set_var_directive(u_char *name, size_t name_len); static int ngx_http_lua_ndk_set_var_get(lua_State *L); static int ngx_http_lua_ndk_set_var_set(lua_State *L); static int ngx_http_lua_run_set_var_directive(lua_State *L); int ngx_http_lua_ndk_set_var_get(lua_State *L) { ndk_set_var_value_pt func; size_t len; u_char *p; p = (u_char *) luaL_checklstring(L, 2, &len); dd("ndk.set_var metatable __index: %s", p); func = ngx_http_lookup_ndk_set_var_directive(p, len); if (func == NULL) { return luaL_error(L, "ndk.set_var: directive \"%s\" not found " "or does not use ndk_set_var_value", p); } lua_pushvalue(L, -1); /* table key key */ lua_pushvalue(L, -1); /* table key key key */ lua_pushlightuserdata(L, (void *) func); /* table key key key func */ lua_pushcclosure(L, ngx_http_lua_run_set_var_directive, 2); /* table key key closure */ lua_rawset(L, 1); /* table key */ lua_rawget(L, 1); /* table closure */ return 1; } int ngx_http_lua_ndk_set_var_set(lua_State *L) { return luaL_error(L, "Not allowed"); } int ngx_http_lua_run_set_var_directive(lua_State *L) { ngx_int_t rc; ndk_set_var_value_pt func; ngx_str_t res; ngx_http_variable_value_t arg; u_char *p; size_t len; ngx_http_request_t *r; if (lua_gettop(L) != 1) { return luaL_error(L, "expecting one argument"); } #if 1 ngx_memzero(&arg, sizeof(ngx_http_variable_value_t)); arg.valid = 1; #endif arg.data = (u_char *) luaL_checklstring(L, 1, &len); arg.len = len; r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request object found"); } p = (u_char *) luaL_checklstring(L, lua_upvalueindex(1), &len); dd("calling set_var func for %s", p); func = (ndk_set_var_value_pt) lua_touserdata(L, lua_upvalueindex(2)); rc = func(r, &res, &arg); if (rc != NGX_OK) { return luaL_error(L, "calling directive %s failed with code %d", p, (int) rc); } lua_pushlstring(L, (char *) res.data, res.len); return 1; } static ndk_set_var_value_pt ngx_http_lookup_ndk_set_var_directive(u_char *name, size_t name_len) { ndk_set_var_t *filter; ngx_uint_t i; ngx_module_t *module; ngx_module_t **modules; ngx_command_t *cmd; #if defined(nginx_version) && nginx_version >= 1009011 modules = ngx_cycle->modules; #else modules = ngx_modules; #endif for (i = 0; modules[i]; i++) { module = modules[i]; if (module->type != NGX_HTTP_MODULE) { continue; } cmd = modules[i]->commands; if (cmd == NULL) { continue; } for ( /* void */ ; cmd->name.len; cmd++) { if (cmd->set != ndk_set_var_value) { continue; } filter = cmd->post; if (filter == NULL) { continue; } if (cmd->name.len != name_len || ngx_strncmp(cmd->name.data, name, name_len) != 0) { continue; } return (ndk_set_var_value_pt)(filter->func); } } return NULL; } void ngx_http_lua_inject_ndk_api(lua_State *L) { lua_createtable(L, 0, 1 /* nrec */); /* ndk.* */ lua_newtable(L); /* .set_var */ lua_createtable(L, 0, 2 /* nrec */); /* metatable for .set_var */ lua_pushcfunction(L, ngx_http_lua_ndk_set_var_get); lua_setfield(L, -2, "__index"); lua_pushcfunction(L, ngx_http_lua_ndk_set_var_set); lua_setfield(L, -2, "__newindex"); lua_setmetatable(L, -2); lua_setfield(L, -2, "set_var"); lua_getglobal(L, "package"); /* ndk package */ lua_getfield(L, -1, "loaded"); /* ndk package loaded */ lua_pushvalue(L, -3); /* ndk package loaded ndk */ lua_setfield(L, -2, "ndk"); /* ndk package loaded */ lua_pop(L, 2); lua_setglobal(L, "ndk"); } #endif /* defined(NDK) && NDK */ /* vi:set ft=c ts=4 sw=4 et fdm=marker: */