Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_flv_module.c @ 9021:f5515e727656
Fixed "zero size buf" alerts with subrequests.
Since 4611:2b6cb7528409 responses from the gzip static, flv, and mp4 modules
can be used with subrequests, though empty files were not properly handled.
Empty gzipped, flv, and mp4 files thus resulted in "zero size buf in output"
alerts. While valid corresponding files are not expected to be empty, such
files shouldn't result in alerts.
Fix is to set b->sync on such empty subrequest responses, similarly to what
ngx_http_send_special() does.
Additionally, the static module, the ngx_http_send_response() function, and
file cache are modified to do the same instead of not sending the response
body at all in such cases, since not sending the response body at all is
believed to be at least questionable, and might break various filters
which do not expect such behaviour.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sat, 28 Jan 2023 05:23:33 +0300 |
parents | 1c3b78d7cdc9 |
children |
rev | line source |
---|---|
753 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
753 | 5 */ |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
12 static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
13 | |
14 static ngx_command_t ngx_http_flv_commands[] = { | |
15 | |
16 { ngx_string("flv"), | |
17 NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, | |
18 ngx_http_flv, | |
19 0, | |
20 0, | |
21 NULL }, | |
22 | |
23 ngx_null_command | |
24 }; | |
25 | |
26 | |
4297
2f8e9469b436
Fixed flv header to match specification.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3527
diff
changeset
|
27 static u_char ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0"; |
753 | 28 |
29 | |
30 static ngx_http_module_t ngx_http_flv_module_ctx = { | |
31 NULL, /* preconfiguration */ | |
32 NULL, /* postconfiguration */ | |
33 | |
34 NULL, /* create main configuration */ | |
35 NULL, /* init main configuration */ | |
36 | |
37 NULL, /* create server configuration */ | |
38 NULL, /* merge server configuration */ | |
39 | |
40 NULL, /* create location configuration */ | |
41 NULL /* merge location configuration */ | |
42 }; | |
43 | |
44 | |
45 ngx_module_t ngx_http_flv_module = { | |
46 NGX_MODULE_V1, | |
47 &ngx_http_flv_module_ctx, /* module context */ | |
48 ngx_http_flv_commands, /* module directives */ | |
49 NGX_HTTP_MODULE, /* module type */ | |
50 NULL, /* init master */ | |
51 NULL, /* init module */ | |
52 NULL, /* init process */ | |
53 NULL, /* init thread */ | |
54 NULL, /* exit thread */ | |
55 NULL, /* exit process */ | |
56 NULL, /* exit master */ | |
57 NGX_MODULE_V1_PADDING | |
58 }; | |
59 | |
60 | |
61 static ngx_int_t | |
62 ngx_http_flv_handler(ngx_http_request_t *r) | |
63 { | |
2415 | 64 u_char *last; |
753 | 65 off_t start, len; |
774
589841f06b87
previous commit broke two modules
Igor Sysoev <igor@sysoev.ru>
parents:
764
diff
changeset
|
66 size_t root; |
753 | 67 ngx_int_t rc; |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
68 ngx_uint_t level, i; |
2415 | 69 ngx_str_t path, value; |
753 | 70 ngx_log_t *log; |
71 ngx_buf_t *b; | |
72 ngx_chain_t out[2]; | |
1454 | 73 ngx_open_file_info_t of; |
753 | 74 ngx_http_core_loc_conf_t *clcf; |
75 | |
76 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { | |
77 return NGX_HTTP_NOT_ALLOWED; | |
78 } | |
79 | |
80 if (r->uri.data[r->uri.len - 1] == '/') { | |
81 return NGX_DECLINED; | |
82 } | |
83 | |
1370
cc114c85be0f
rename ngx_http_discard_body() to ngx_http_discard_request_body()
Igor Sysoev <igor@sysoev.ru>
parents:
1048
diff
changeset
|
84 rc = ngx_http_discard_request_body(r); |
753 | 85 |
1374 | 86 if (rc != NGX_OK) { |
753 | 87 return rc; |
88 } | |
89 | |
1454 | 90 last = ngx_http_map_uri_to_path(r, &path, &root, 0); |
91 if (last == NULL) { | |
753 | 92 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
93 } | |
94 | |
95 log = r->connection->log; | |
96 | |
1454 | 97 path.len = last - path.data; |
753 | 98 |
1454 | 99 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, |
100 "http flv filename: \"%V\"", &path); | |
101 | |
102 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
753 | 103 |
2068
75a8d34459c5
ngx_memzero() ngx_open_file_info_t
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
104 ngx_memzero(&of, sizeof(ngx_open_file_info_t)); |
75a8d34459c5
ngx_memzero() ngx_open_file_info_t
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
105 |
3178 | 106 of.read_ahead = clcf->read_ahead; |
2129 | 107 of.directio = clcf->directio; |
1767
c42431762903
open_file_cache_retest > open_file_cache_valid
Igor Sysoev <igor@sysoev.ru>
parents:
1696
diff
changeset
|
108 of.valid = clcf->open_file_cache_valid; |
1772 | 109 of.min_uses = clcf->open_file_cache_min_uses; |
1454 | 110 of.errors = clcf->open_file_cache_errors; |
1457 | 111 of.events = clcf->open_file_cache_events; |
4494
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
112 |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
113 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
114 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
115 } |
1560
25ee6eee7573
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1553
diff
changeset
|
116 |
1799 | 117 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) |
118 != NGX_OK) | |
119 { | |
1454 | 120 switch (of.err) { |
121 | |
122 case 0: | |
123 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
124 | |
125 case NGX_ENOENT: | |
126 case NGX_ENOTDIR: | |
127 case NGX_ENAMETOOLONG: | |
128 | |
753 | 129 level = NGX_LOG_ERR; |
130 rc = NGX_HTTP_NOT_FOUND; | |
1454 | 131 break; |
753 | 132 |
1454 | 133 case NGX_EACCES: |
4478
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
134 #if (NGX_HAVE_OPENAT) |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
135 case NGX_EMLINK: |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
136 case NGX_ELOOP: |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
137 #endif |
1454 | 138 |
753 | 139 level = NGX_LOG_ERR; |
140 rc = NGX_HTTP_FORBIDDEN; | |
1454 | 141 break; |
753 | 142 |
1454 | 143 default: |
144 | |
753 | 145 level = NGX_LOG_CRIT; |
146 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1454 | 147 break; |
753 | 148 } |
149 | |
150 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { | |
1454 | 151 ngx_log_error(level, log, of.err, |
2756
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2721
diff
changeset
|
152 "%s \"%s\" failed", of.failed, path.data); |
753 | 153 } |
154 | |
155 return rc; | |
156 } | |
157 | |
1454 | 158 if (!of.is_file) { |
753 | 159 return NGX_DECLINED; |
160 } | |
161 | |
2444
aee735f41627
set r->root_tested for non-error_page response only
Igor Sysoev <igor@sysoev.ru>
parents:
2415
diff
changeset
|
162 r->root_tested = !r->error_page; |
2087
c8039b26a949
always test root existence for access_log with variables
Igor Sysoev <igor@sysoev.ru>
parents:
2086
diff
changeset
|
163 |
753 | 164 start = 0; |
1454 | 165 len = of.size; |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
166 i = 1; |
753 | 167 |
168 if (r->args.len) { | |
169 | |
2415 | 170 if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) { |
2086
22d36702c654
allow several values in query string
Igor Sysoev <igor@sysoev.ru>
parents:
2068
diff
changeset
|
171 |
2415 | 172 start = ngx_atoof(value.data, value.len); |
753 | 173 |
174 if (start == NGX_ERROR || start >= len) { | |
175 start = 0; | |
176 } | |
177 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
178 if (start) { |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
179 len = sizeof(ngx_flv_header) - 1 + len - start; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
180 i = 0; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
181 } |
753 | 182 } |
183 } | |
184 | |
185 log->action = "sending flv to client"; | |
186 | |
187 r->headers_out.status = NGX_HTTP_OK; | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
188 r->headers_out.content_length_n = len; |
1454 | 189 r->headers_out.last_modified_time = of.mtime; |
753 | 190 |
4748
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
191 if (ngx_http_set_etag(r) != NGX_OK) { |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
192 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
193 } |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
194 |
753 | 195 if (ngx_http_set_content_type(r) != NGX_OK) { |
754
4ac89c5aa10d
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
753
diff
changeset
|
196 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
753 | 197 } |
198 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
199 if (i == 0) { |
6973
99934aade555
Use ngx_calloc_buf() where appropriate.
Ruslan Ermilov <ru@nginx.com>
parents:
4748
diff
changeset
|
200 b = ngx_calloc_buf(r->pool); |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
201 if (b == NULL) { |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
202 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
203 } |
753 | 204 |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
205 b->pos = ngx_flv_header; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
206 b->last = ngx_flv_header + sizeof(ngx_flv_header) - 1; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
207 b->memory = 1; |
753 | 208 |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
209 out[0].buf = b; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
210 out[0].next = &out[1]; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
211 } |
753 | 212 |
781
836f099aa5cb
allow ranges for full flv files
Igor Sysoev <igor@sysoev.ru>
parents:
774
diff
changeset
|
213 |
6973
99934aade555
Use ngx_calloc_buf() where appropriate.
Ruslan Ermilov <ru@nginx.com>
parents:
4748
diff
changeset
|
214 b = ngx_calloc_buf(r->pool); |
753 | 215 if (b == NULL) { |
216 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
217 } | |
218 | |
219 b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); | |
220 if (b->file == NULL) { | |
221 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
222 } | |
223 | |
2122
d090fa684433
allow range for partial flv response
Igor Sysoev <igor@sysoev.ru>
parents:
2087
diff
changeset
|
224 r->allow_ranges = 1; |
d090fa684433
allow range for partial flv response
Igor Sysoev <igor@sysoev.ru>
parents:
2087
diff
changeset
|
225 |
753 | 226 rc = ngx_http_send_header(r); |
227 | |
228 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
229 return rc; | |
230 } | |
231 | |
232 b->file_pos = start; | |
1454 | 233 b->file_last = of.size; |
753 | 234 |
9020 | 235 b->in_file = b->file_last ? 1 : 0; |
4611
2b6cb7528409
Allows particular modules to handle subrequests properly.
Andrey Belov <defan@nginx.com>
parents:
4494
diff
changeset
|
236 b->last_buf = (r == r->main) ? 1 : 0; |
753 | 237 b->last_in_chain = 1; |
9021
f5515e727656
Fixed "zero size buf" alerts with subrequests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
9020
diff
changeset
|
238 b->sync = (b->last_buf || b->in_file) ? 0 : 1; |
753 | 239 |
1696 | 240 b->file->fd = of.fd; |
753 | 241 b->file->name = path; |
242 b->file->log = log; | |
2231
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
243 b->file->directio = of.is_directio; |
753 | 244 |
245 out[1].buf = b; | |
246 out[1].next = NULL; | |
247 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
248 return ngx_http_output_filter(r, &out[i]); |
753 | 249 } |
250 | |
251 | |
252 static char * | |
253 ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
254 { | |
255 ngx_http_core_loc_conf_t *clcf; | |
256 | |
257 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
258 clcf->handler = ngx_http_flv_handler; | |
259 | |
260 return NGX_CONF_OK; | |
261 } |