Line data Source code
1 :
2 : /*
3 : * Copyright (C) Xiaozhe Wang (chaoslawful)
4 : * Copyright (C) Yichun Zhang (agentzh)
5 : */
6 :
7 :
8 : #ifndef DDEBUG
9 : #define DDEBUG 0
10 : #endif
11 : #include "ddebug.h"
12 :
13 :
14 : #include "ngx_http_lua_misc.h"
15 : #include "ngx_http_lua_ctx.h"
16 : #include "ngx_http_lua_util.h"
17 :
18 :
19 : static int ngx_http_lua_ngx_get(lua_State *L);
20 : static int ngx_http_lua_ngx_set(lua_State *L);
21 : static int ngx_http_lua_ngx_req_is_internal(lua_State *L);
22 :
23 :
24 : void
25 18 : ngx_http_lua_inject_misc_api(lua_State *L)
26 : {
27 : /* ngx. getter and setter */
28 18 : lua_createtable(L, 0, 2); /* metatable for .ngx */
29 18 : lua_pushcfunction(L, ngx_http_lua_ngx_get);
30 18 : lua_setfield(L, -2, "__index");
31 18 : lua_pushcfunction(L, ngx_http_lua_ngx_set);
32 18 : lua_setfield(L, -2, "__newindex");
33 18 : lua_setmetatable(L, -2);
34 18 : }
35 :
36 :
37 : void
38 18 : ngx_http_lua_inject_req_misc_api(lua_State *L)
39 : {
40 18 : lua_pushcfunction(L, ngx_http_lua_ngx_req_is_internal);
41 18 : lua_setfield(L, -2, "is_internal");
42 18 : }
43 :
44 :
45 : static int
46 0 : ngx_http_lua_ngx_req_is_internal(lua_State *L)
47 : {
48 : ngx_http_request_t *r;
49 :
50 0 : r = ngx_http_lua_get_req(L);
51 0 : if (r == NULL) {
52 0 : return luaL_error(L, "no request object found");
53 : }
54 :
55 0 : lua_pushboolean(L, r->internal == 1);
56 0 : return 1;
57 : }
58 :
59 :
60 : static int
61 0 : ngx_http_lua_ngx_get(lua_State *L)
62 : {
63 : int status;
64 : ngx_http_request_t *r;
65 : u_char *p;
66 : size_t len;
67 : ngx_http_lua_ctx_t *ctx;
68 :
69 0 : r = ngx_http_lua_get_req(L);
70 0 : if (r == NULL) {
71 0 : lua_pushnil(L);
72 0 : return 1;
73 : }
74 :
75 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
76 0 : if (ctx == NULL) {
77 0 : lua_pushnil(L);
78 0 : return 1;
79 : }
80 :
81 0 : p = (u_char *) luaL_checklstring(L, -1, &len);
82 :
83 : dd("ngx get %s", p);
84 :
85 0 : if (len == sizeof("status") - 1
86 0 : && ngx_strncmp(p, "status", sizeof("status") - 1) == 0)
87 : {
88 0 : ngx_http_lua_check_fake_request(L, r);
89 :
90 0 : if (r->err_status) {
91 0 : status = r->err_status;
92 :
93 0 : } else if (r->headers_out.status) {
94 0 : status = r->headers_out.status;
95 :
96 0 : } else if (r->http_version == NGX_HTTP_VERSION_9) {
97 0 : status = 9;
98 :
99 : } else {
100 0 : status = 0;
101 : }
102 :
103 0 : lua_pushinteger(L, status);
104 0 : return 1;
105 : }
106 :
107 0 : if (len == sizeof("ctx") - 1
108 0 : && ngx_strncmp(p, "ctx", sizeof("ctx") - 1) == 0)
109 : {
110 0 : return ngx_http_lua_ngx_get_ctx(L);
111 : }
112 :
113 0 : if (len == sizeof("is_subrequest") - 1
114 0 : && ngx_strncmp(p, "is_subrequest", sizeof("is_subrequest") - 1) == 0)
115 : {
116 0 : lua_pushboolean(L, r != r->main);
117 0 : return 1;
118 : }
119 :
120 0 : if (len == sizeof("headers_sent") - 1
121 0 : && ngx_strncmp(p, "headers_sent", sizeof("headers_sent") - 1) == 0)
122 : {
123 0 : ngx_http_lua_check_fake_request(L, r);
124 :
125 : dd("headers sent: %d", r->header_sent || ctx->header_sent);
126 :
127 0 : lua_pushboolean(L, r->header_sent || ctx->header_sent);
128 0 : return 1;
129 : }
130 :
131 : dd("key %s not matched", p);
132 :
133 0 : lua_pushnil(L);
134 0 : return 1;
135 : }
136 :
137 :
138 : static int
139 0 : ngx_http_lua_ngx_set(lua_State *L)
140 : {
141 : ngx_http_request_t *r;
142 : u_char *p;
143 : size_t len;
144 :
145 : /* we skip the first argument that is the table */
146 0 : p = (u_char *) luaL_checklstring(L, 2, &len);
147 :
148 0 : if (len == sizeof("status") - 1
149 0 : && ngx_strncmp(p, "status", sizeof("status") - 1) == 0)
150 : {
151 0 : r = ngx_http_lua_get_req(L);
152 0 : if (r == NULL) {
153 0 : return luaL_error(L, "no request object found");
154 : }
155 :
156 0 : if (r->header_sent) {
157 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
158 : "attempt to set ngx.status after sending out "
159 : "response headers");
160 0 : return 0;
161 : }
162 :
163 0 : if (r->err_status) {
164 0 : r->err_status = 0;
165 : }
166 :
167 0 : ngx_http_lua_check_fake_request(L, r);
168 :
169 : /* get the value */
170 0 : r->headers_out.status = (ngx_uint_t) luaL_checknumber(L, 3);
171 :
172 0 : if (r->headers_out.status == 101) {
173 : /*
174 : * XXX work-around a bug in the Nginx core that 101 does
175 : * not have a default status line
176 : */
177 :
178 0 : ngx_str_set(&r->headers_out.status_line, "101 Switching Protocols");
179 :
180 : } else {
181 0 : r->headers_out.status_line.len = 0;
182 : }
183 :
184 0 : return 0;
185 : }
186 :
187 0 : if (len == sizeof("ctx") - 1
188 0 : && ngx_strncmp(p, "ctx", sizeof("ctx") - 1) == 0)
189 : {
190 0 : r = ngx_http_lua_get_req(L);
191 0 : if (r == NULL) {
192 0 : return luaL_error(L, "no request object found");
193 : }
194 :
195 0 : return ngx_http_lua_ngx_set_ctx(L);
196 : }
197 :
198 0 : lua_rawset(L, -3);
199 0 : return 0;
200 : }
201 :
202 :
203 : #ifndef NGX_LUA_NO_FFI_API
204 : int
205 0 : ngx_http_lua_ffi_get_resp_status(ngx_http_request_t *r)
206 : {
207 0 : if (r->connection->fd == (ngx_socket_t) -1) {
208 0 : return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
209 : }
210 :
211 0 : if (r->err_status) {
212 0 : return r->err_status;
213 :
214 0 : } else if (r->headers_out.status) {
215 0 : return r->headers_out.status;
216 :
217 0 : } else if (r->http_version == NGX_HTTP_VERSION_9) {
218 0 : return 9;
219 :
220 : } else {
221 0 : return 0;
222 : }
223 : }
224 :
225 :
226 : int
227 0 : ngx_http_lua_ffi_set_resp_status(ngx_http_request_t *r, int status)
228 : {
229 0 : if (r->connection->fd == (ngx_socket_t) -1) {
230 0 : return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
231 : }
232 :
233 0 : if (r->header_sent) {
234 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
235 : "attempt to set ngx.status after sending out "
236 : "response headers");
237 0 : return NGX_DECLINED;
238 : }
239 :
240 0 : r->headers_out.status = status;
241 :
242 0 : if (r->err_status) {
243 0 : r->err_status = 0;
244 : }
245 :
246 0 : if (status == 101) {
247 : /*
248 : * XXX work-around a bug in the Nginx core older than 1.5.5
249 : * that 101 does not have a default status line
250 : */
251 :
252 0 : ngx_str_set(&r->headers_out.status_line, "101 Switching Protocols");
253 :
254 : } else {
255 0 : r->headers_out.status_line.len = 0;
256 : }
257 :
258 0 : return NGX_OK;
259 : }
260 :
261 :
262 : int
263 0 : ngx_http_lua_ffi_is_subrequest(ngx_http_request_t *r)
264 : {
265 0 : if (r->connection->fd == (ngx_socket_t) -1) {
266 0 : return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
267 : }
268 :
269 0 : return r != r->main;
270 : }
271 :
272 :
273 : int
274 0 : ngx_http_lua_ffi_headers_sent(ngx_http_request_t *r)
275 : {
276 : ngx_http_lua_ctx_t *ctx;
277 :
278 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
279 0 : if (ctx == NULL) {
280 0 : return NGX_HTTP_LUA_FFI_NO_REQ_CTX;
281 : }
282 :
283 0 : if (r->connection->fd == (ngx_socket_t) -1) {
284 0 : return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
285 : }
286 :
287 0 : return r->header_sent ? 1 : 0;
288 : }
289 : #endif /* NGX_LUA_NO_FFI_API */
290 :
291 :
292 : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
|