Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_postpone_filter_module.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
13 static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r,
14  ngx_chain_t *in);
15 static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf);
16 
17 
18 static ngx_http_module_t ngx_http_postpone_filter_module_ctx = {
19  NULL, /* preconfiguration */
20  ngx_http_postpone_filter_init, /* postconfiguration */
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 
35  &ngx_http_postpone_filter_module_ctx, /* module context */
36  NULL, /* module directives */
37  NGX_HTTP_MODULE, /* module type */
38  NULL, /* init master */
39  NULL, /* init module */
40  NULL, /* init process */
41  NULL, /* init thread */
42  NULL, /* exit thread */
43  NULL, /* exit process */
44  NULL, /* exit master */
46 };
47 
48 
49 static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
50 
51 
52 static ngx_int_t
53 ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
54 {
57 
58  c = r->connection;
59 
61  "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
62 
63  if (r != c->data) {
64 
65  if (in) {
66  ngx_http_postpone_filter_add(r, in);
67  return NGX_OK;
68  }
69 
70 #if 0
71  /* TODO: SSI may pass NULL */
73  "http postpone filter NULL inactive request",
74  &r->uri, &r->args);
75 #endif
76 
77  return NGX_OK;
78  }
79 
80  if (r->postponed == NULL) {
81 
82  if (in || c->buffered) {
83  return ngx_http_next_body_filter(r->main, in);
84  }
85 
86  return NGX_OK;
87  }
88 
89  if (in) {
90  ngx_http_postpone_filter_add(r, in);
91  }
92 
93  do {
94  pr = r->postponed;
95 
96  if (pr->request) {
97 
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 
106  return ngx_http_post_request(pr->request, NULL);
107  }
108 
109  if (pr->out == NULL) {
111  "http postpone filter NULL output",
112  &r->uri, &r->args);
113 
114  } else {
116  "http postpone filter output \"%V?%V\"",
117  &r->uri, &r->args);
118 
119  if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) {
120  return NGX_ERROR;
121  }
122  }
123 
124  r->postponed = pr->next;
125 
126  } while (r->postponed);
127 
128  return NGX_OK;
129 }
130 
131 
132 static ngx_int_t
133 ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in)
134 {
135  ngx_http_postponed_request_t *pr, **ppr;
136 
137  if (r->postponed) {
138  for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
139 
140  if (pr->request == NULL) {
141  goto found;
142  }
143 
144  ppr = &pr->next;
145 
146  } else {
147  ppr = &r->postponed;
148  }
149 
150  pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
151  if (pr == NULL) {
152  return NGX_ERROR;
153  }
154 
155  *ppr = pr;
156 
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;
165  }
166 
167  return NGX_ERROR;
168 }
169 
170 
171 static ngx_int_t
172 ngx_http_postpone_filter_init(ngx_conf_t *cf)
173 {
174  ngx_http_next_body_filter = ngx_http_top_body_filter;
175  ngx_http_top_body_filter = ngx_http_postpone_filter;
176 
177  return NGX_OK;
178 }