58
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
660
|
4 * Copyright (C) Nginx, Inc.
|
58
|
5 */
|
|
6
|
|
7
|
|
8 #include <ngx_config.h>
|
|
9 #include <ngx_core.h>
|
|
10 #include <ngx_http.h>
|
|
11
|
|
12
|
426
|
13 static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r,
|
|
14 ngx_chain_t *in);
|
230
|
15 static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf);
|
58
|
16
|
|
17
|
|
18 static ngx_http_module_t ngx_http_postpone_filter_module_ctx = {
|
|
19 NULL, /* preconfiguration */
|
230
|
20 ngx_http_postpone_filter_init, /* postconfiguration */
|
58
|
21
|
|
22 NULL, /* create main configuration */
|
|
23 NULL, /* init main configuration */
|
|
24
|
|
25 NULL, /* create server configuration */
|
|
26 NULL, /* merge server configuration */
|
|
27
|
|
28 NULL, /* create location configuration */
|
|
29 NULL /* merge location configuration */
|
|
30 };
|
|
31
|
|
32
|
|
33 ngx_module_t ngx_http_postpone_filter_module = {
|
|
34 NGX_MODULE_V1,
|
|
35 &ngx_http_postpone_filter_module_ctx, /* module context */
|
|
36 NULL, /* module directives */
|
|
37 NGX_HTTP_MODULE, /* module type */
|
90
|
38 NULL, /* init master */
|
230
|
39 NULL, /* init module */
|
90
|
40 NULL, /* init process */
|
|
41 NULL, /* init thread */
|
|
42 NULL, /* exit thread */
|
|
43 NULL, /* exit process */
|
|
44 NULL, /* exit master */
|
|
45 NGX_MODULE_V1_PADDING
|
58
|
46 };
|
|
47
|
|
48
|
668
|
49 static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
|
58
|
50
|
|
51
|
|
52 static ngx_int_t
|
|
53 ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|
54 {
|
426
|
55 ngx_connection_t *c;
|
|
56 ngx_http_postponed_request_t *pr;
|
58
|
57
|
426
|
58 c = r->connection;
|
|
59
|
|
60 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
132
|
61 "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
|
76
|
62
|
426
|
63 if (r != c->data) {
|
58
|
64
|
426
|
65 if (in) {
|
|
66 ngx_http_postpone_filter_add(r, in);
|
|
67 return NGX_OK;
|
58
|
68 }
|
|
69
|
426
|
70 #if 0
|
|
71 /* TODO: SSI may pass NULL */
|
|
72 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
|
73 "http postpone filter NULL inactive request",
|
|
74 &r->uri, &r->args);
|
190
|
75 #endif
|
|
76
|
426
|
77 return NGX_OK;
|
132
|
78 }
|
|
79
|
|
80 if (r->postponed == NULL) {
|
426
|
81
|
|
82 if (in || c->buffered) {
|
668
|
83 return ngx_http_next_body_filter(r->main, in);
|
426
|
84 }
|
|
85
|
|
86 return NGX_OK;
|
|
87 }
|
|
88
|
|
89 if (in) {
|
|
90 ngx_http_postpone_filter_add(r, in);
|
132
|
91 }
|
|
92
|
426
|
93 do {
|
|
94 pr = r->postponed;
|
|
95
|
|
96 if (pr->request) {
|
|
97
|
|
98 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
|
99 "http postpone filter wake \"%V?%V\"",
|
|
100 &pr->request->uri, &pr->request->args);
|
|
101
|
|
102 r->postponed = pr->next;
|
|
103
|
|
104 c->data = pr->request;
|
|
105
|
520
|
106 return ngx_http_post_request(pr->request, NULL);
|
426
|
107 }
|
132
|
108
|
426
|
109 if (pr->out == NULL) {
|
|
110 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
|
111 "http postpone filter NULL output",
|
|
112 &r->uri, &r->args);
|
|
113
|
|
114 } else {
|
|
115 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
|
116 "http postpone filter output \"%V?%V\"",
|
|
117 &r->uri, &r->args);
|
58
|
118
|
668
|
119 if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) {
|
426
|
120 return NGX_ERROR;
|
|
121 }
|
|
122 }
|
|
123
|
|
124 r->postponed = pr->next;
|
|
125
|
|
126 } while (r->postponed);
|
|
127
|
|
128 return NGX_OK;
|
58
|
129 }
|
|
130
|
|
131
|
|
132 static ngx_int_t
|
426
|
133 ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in)
|
132
|
134 {
|
426
|
135 ngx_http_postponed_request_t *pr, **ppr;
|
132
|
136
|
426
|
137 if (r->postponed) {
|
|
138 for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
|
132
|
139
|
426
|
140 if (pr->request == NULL) {
|
|
141 goto found;
|
132
|
142 }
|
|
143
|
426
|
144 ppr = &pr->next;
|
132
|
145
|
426
|
146 } else {
|
|
147 ppr = &r->postponed;
|
|
148 }
|
144
|
149
|
426
|
150 pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
|
|
151 if (pr == NULL) {
|
|
152 return NGX_ERROR;
|
132
|
153 }
|
384
|
154
|
426
|
155 *ppr = pr;
|
384
|
156
|
426
|
157 pr->request = NULL;
|
|
158 pr->out = NULL;
|
|
159 pr->next = NULL;
|
|
160
|
|
161 found:
|
|
162
|
|
163 if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_OK) {
|
|
164 return NGX_OK;
|
384
|
165 }
|
|
166
|
426
|
167 return NGX_ERROR;
|
132
|
168 }
|
|
169
|
|
170
|
|
171 static ngx_int_t
|
230
|
172 ngx_http_postpone_filter_init(ngx_conf_t *cf)
|
58
|
173 {
|
668
|
174 ngx_http_next_body_filter = ngx_http_top_body_filter;
|
58
|
175 ngx_http_top_body_filter = ngx_http_postpone_filter;
|
|
176
|
|
177 return NGX_OK;
|
|
178 }
|