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 <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
31 1 : ngx_http_lua_capture_filter_init(ngx_conf_t *cf)
32 : {
33 : /* setting up output filters to intercept subrequest responses */
34 1 : ngx_http_lua_next_header_filter = ngx_http_top_header_filter;
35 1 : ngx_http_top_header_filter = ngx_http_lua_capture_header_filter;
36 :
37 1 : ngx_http_lua_next_body_filter = ngx_http_top_body_filter;
38 1 : ngx_http_top_body_filter = ngx_http_lua_capture_body_filter;
39 :
40 1 : return NGX_OK;
41 : }
42 :
43 :
44 : static ngx_int_t
45 1 : 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 1 : ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
54 : "lua capture header filter, uri \"%V\"", &r->uri);
55 :
56 1 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
57 :
58 : dd("old ctx: %p", ctx);
59 :
60 1 : if (ctx == NULL || ! ctx->capture) {
61 :
62 1 : psr = r->post_subrequest;
63 :
64 1 : if (psr != NULL
65 0 : && psr->handler == ngx_http_lua_post_subrequest
66 0 : && 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 0 : psr_data = psr->data;
72 :
73 0 : old_ctx = psr_data->ctx;
74 :
75 0 : if (ctx == NULL) {
76 0 : ctx = old_ctx;
77 0 : ngx_http_set_ctx(r, ctx, ngx_http_lua_module);
78 :
79 : } else {
80 0 : 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 0 : ctx->capture = old_ctx->capture;
85 0 : ctx->index = old_ctx->index;
86 0 : ctx->body = NULL;
87 0 : ctx->last_body = &ctx->body;
88 0 : psr_data->ctx = ctx;
89 : }
90 : }
91 : }
92 :
93 1 : if (ctx && ctx->capture) {
94 0 : 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 0 : r->filter_need_in_memory = 1;
99 0 : r->header_sent = 1;
100 0 : ctx->header_sent = 1;
101 :
102 0 : if (r->method == NGX_HTTP_HEAD) {
103 0 : r->header_only = 1;
104 : }
105 :
106 0 : return NGX_OK;
107 : }
108 :
109 1 : return ngx_http_lua_next_header_filter(r);
110 : }
111 :
112 :
113 : static ngx_int_t
114 2 : 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 2 : ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
122 : "lua capture body filter, uri \"%V\"", &r->uri);
123 :
124 2 : if (in == NULL) {
125 0 : return ngx_http_lua_next_body_filter(r, NULL);
126 : }
127 :
128 2 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
129 :
130 2 : if (!ctx || !ctx->capture) {
131 : dd("no ctx or no capture %.*s", (int) r->uri.len, r->uri.data);
132 :
133 2 : return ngx_http_lua_next_body_filter(r, in);
134 : }
135 :
136 0 : if (ctx->run_post_subrequest) {
137 0 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
138 : "lua body filter skipped because post subrequest "
139 : "already run");
140 0 : return NGX_OK;
141 : }
142 :
143 0 : if (r->parent == NULL) {
144 0 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
145 : "lua body filter skipped because no parent request "
146 : "found");
147 :
148 0 : return NGX_ERROR;
149 : }
150 :
151 0 : pr_ctx = ngx_http_get_module_ctx(r->parent, ngx_http_lua_module);
152 0 : if (pr_ctx == NULL) {
153 0 : return NGX_ERROR;
154 : }
155 :
156 0 : 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 0 : rc = ngx_http_lua_add_copy_chain(r, pr_ctx, &ctx->last_body, in, &eof);
161 0 : if (rc != NGX_OK) {
162 0 : return NGX_ERROR;
163 : }
164 :
165 : dd("add copy chain eof: %d, sr: %d", (int) eof, r != r->main);
166 :
167 0 : if (eof) {
168 0 : ctx->seen_last_for_subreq = 1;
169 : }
170 :
171 0 : ngx_http_lua_discard_bufs(r->pool, in);
172 :
173 0 : return NGX_OK;
174 : }
175 :
176 : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
|