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 <nginx.h>
15 #include "ngx_http_lua_capturefilter.h"
16 #include "ngx_http_lua_util.h"
17 #include "ngx_http_lua_exception.h"
18 #include "ngx_http_lua_subrequest.h"
19
20
21 ngx_http_output_header_filter_pt ngx_http_lua_next_header_filter;
22 ngx_http_output_body_filter_pt ngx_http_lua_next_body_filter;
23
24
25 static ngx_int_t ngx_http_lua_capture_header_filter(ngx_http_request_t *r);
26 static ngx_int_t ngx_http_lua_capture_body_filter(ngx_http_request_t *r,
27 ngx_chain_t *in);
28
29
30 ngx_int_t
ngx_http_lua_capture_filter_init(ngx_conf_t * cf)31 ngx_http_lua_capture_filter_init(ngx_conf_t *cf)
32 {
33 /* setting up output filters to intercept subrequest responses */
34 ngx_http_lua_next_header_filter = ngx_http_top_header_filter;
35 ngx_http_top_header_filter = ngx_http_lua_capture_header_filter;
36
37 ngx_http_lua_next_body_filter = ngx_http_top_body_filter;
38 ngx_http_top_body_filter = ngx_http_lua_capture_body_filter;
39
40 return NGX_OK;
41 }
42
43
44 static ngx_int_t
ngx_http_lua_capture_header_filter(ngx_http_request_t * r)45 ngx_http_lua_capture_header_filter(ngx_http_request_t *r)
46 {
47 ngx_http_post_subrequest_t *psr;
48 ngx_http_lua_ctx_t *old_ctx;
49 ngx_http_lua_ctx_t *ctx;
50
51 ngx_http_lua_post_subrequest_data_t *psr_data;
52
53 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
54 "lua capture header filter, uri \"%V\"", &r->uri);
55
56 ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
57
58 dd("old ctx: %p", ctx);
59
60 if (ctx == NULL || ! ctx->capture) {
61
62 psr = r->post_subrequest;
63
64 if (psr != NULL
65 && psr->handler == ngx_http_lua_post_subrequest
66 && psr->data != NULL)
67 {
68 /* the lua ctx has been cleared by ngx_http_internal_redirect,
69 * resume it from the post_subrequest data
70 */
71 psr_data = psr->data;
72
73 old_ctx = psr_data->ctx;
74
75 if (ctx == NULL) {
76 ctx = old_ctx;
77 ngx_http_set_ctx(r, ctx, ngx_http_lua_module);
78
79 } else {
80 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
81 "lua restoring ctx with capture %d, index %d",
82 old_ctx->capture, old_ctx->index);
83
84 ctx->capture = old_ctx->capture;
85 ctx->index = old_ctx->index;
86 ctx->body = NULL;
87 ctx->last_body = &ctx->body;
88 psr_data->ctx = ctx;
89 }
90 }
91 }
92
93 if (ctx && ctx->capture) {
94 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
95 "lua capturing response body");
96
97 /* force subrequest response body buffer in memory */
98 r->filter_need_in_memory = 1;
99 r->header_sent = 1;
100 ctx->header_sent = 1;
101
102 if (r->method == NGX_HTTP_HEAD) {
103 r->header_only = 1;
104 }
105
106 return NGX_OK;
107 }
108
109 return ngx_http_lua_next_header_filter(r);
110 }
111
112
113 static ngx_int_t
ngx_http_lua_capture_body_filter(ngx_http_request_t * r,ngx_chain_t * in)114 ngx_http_lua_capture_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
115 {
116 int rc;
117 ngx_int_t eof;
118 ngx_http_lua_ctx_t *ctx;
119 ngx_http_lua_ctx_t *pr_ctx;
120
121 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
122 "lua capture body filter, uri \"%V\"", &r->uri);
123
124 if (in == NULL) {
125 return ngx_http_lua_next_body_filter(r, NULL);
126 }
127
128 ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
129
130 if (!ctx || !ctx->capture) {
131 dd("no ctx or no capture %.*s", (int) r->uri.len, r->uri.data);
132
133 return ngx_http_lua_next_body_filter(r, in);
134 }
135
136 if (ctx->run_post_subrequest) {
137 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
138 "lua body filter skipped because post subrequest "
139 "already run");
140 return NGX_OK;
141 }
142
143 if (r->parent == NULL) {
144 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
145 "lua body filter skipped because no parent request "
146 "found");
147
148 return NGX_ERROR;
149 }
150
151 pr_ctx = ngx_http_get_module_ctx(r->parent, ngx_http_lua_module);
152 if (pr_ctx == NULL) {
153 return NGX_ERROR;
154 }
155
156 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
157 "lua capture body filter capturing response body, uri "
158 "\"%V\"", &r->uri);
159
160 rc = ngx_http_lua_add_copy_chain(r, pr_ctx, &ctx->last_body, in, &eof);
161 if (rc != NGX_OK) {
162 return NGX_ERROR;
163 }
164
165 dd("add copy chain eof: %d, sr: %d", (int) eof, r != r->main);
166
167 if (eof) {
168 ctx->seen_last_for_subreq = 1;
169 }
170
171 ngx_http_lua_discard_bufs(r->pool, in);
172
173 return NGX_OK;
174 }
175
176 /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
177