Mercurial > hg > nginx
annotate src/http/modules/ngx_http_flv_module.c @ 4437:3a1507f48686 stable-1.0
Merge of r4372, r4373, r4374:
SCGI fixes:
*) Fixed incorrect use of r->http_version in scgi module.
The r->http_version is a version of client's request, and modules
must not set it unless they are really willing to downgrade protocol
version used for a response (i.e. to HTTP/0.9 if no response headers
are available). In neither case r->http_version may be upgraded.
The former code downgraded response from HTTP/1.1 to HTTP/1.0 for no
reason, causing various problems (see ticket #66). It was also
possible that HTTP/0.9 requests were upgraded to HTTP/1.0.
*) Removed duplicate function declaration.
*) Removed error if there is no Status header.
The SCGI specification doesn't specify format of the response, and
assuming CGI specs should be used there is no reason to complain.
RFC 3875 explicitly states that "A Status header field is optional,
and status 200 'OK' is assumed if it is omitted".
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 05 Feb 2012 13:53:50 +0000 |
parents | b46cd3ce6278 |
children | d620f497c50f |
rev | line source |
---|---|
753 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 #include <ngx_config.h> | |
7 #include <ngx_core.h> | |
8 #include <ngx_http.h> | |
9 | |
10 | |
11 static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
12 | |
13 static ngx_command_t ngx_http_flv_commands[] = { | |
14 | |
15 { ngx_string("flv"), | |
16 NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, | |
17 ngx_http_flv, | |
18 0, | |
19 0, | |
20 NULL }, | |
21 | |
22 ngx_null_command | |
23 }; | |
24 | |
25 | |
4363 | 26 static u_char ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0"; |
753 | 27 |
28 | |
29 static ngx_http_module_t ngx_http_flv_module_ctx = { | |
30 NULL, /* preconfiguration */ | |
31 NULL, /* postconfiguration */ | |
32 | |
33 NULL, /* create main configuration */ | |
34 NULL, /* init main configuration */ | |
35 | |
36 NULL, /* create server configuration */ | |
37 NULL, /* merge server configuration */ | |
38 | |
39 NULL, /* create location configuration */ | |
40 NULL /* merge location configuration */ | |
41 }; | |
42 | |
43 | |
44 ngx_module_t ngx_http_flv_module = { | |
45 NGX_MODULE_V1, | |
46 &ngx_http_flv_module_ctx, /* module context */ | |
47 ngx_http_flv_commands, /* module directives */ | |
48 NGX_HTTP_MODULE, /* module type */ | |
49 NULL, /* init master */ | |
50 NULL, /* init module */ | |
51 NULL, /* init process */ | |
52 NULL, /* init thread */ | |
53 NULL, /* exit thread */ | |
54 NULL, /* exit process */ | |
55 NULL, /* exit master */ | |
56 NGX_MODULE_V1_PADDING | |
57 }; | |
58 | |
59 | |
60 static ngx_int_t | |
61 ngx_http_flv_handler(ngx_http_request_t *r) | |
62 { | |
2415 | 63 u_char *last; |
753 | 64 off_t start, len; |
774
589841f06b87
previous commit broke two modules
Igor Sysoev <igor@sysoev.ru>
parents:
764
diff
changeset
|
65 size_t root; |
753 | 66 ngx_int_t rc; |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
67 ngx_uint_t level, i; |
2415 | 68 ngx_str_t path, value; |
753 | 69 ngx_log_t *log; |
70 ngx_buf_t *b; | |
71 ngx_chain_t out[2]; | |
1454 | 72 ngx_open_file_info_t of; |
753 | 73 ngx_http_core_loc_conf_t *clcf; |
74 | |
75 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { | |
76 return NGX_HTTP_NOT_ALLOWED; | |
77 } | |
78 | |
79 if (r->uri.data[r->uri.len - 1] == '/') { | |
80 return NGX_DECLINED; | |
81 } | |
82 | |
1370
cc114c85be0f
rename ngx_http_discard_body() to ngx_http_discard_request_body()
Igor Sysoev <igor@sysoev.ru>
parents:
1048
diff
changeset
|
83 rc = ngx_http_discard_request_body(r); |
753 | 84 |
1374 | 85 if (rc != NGX_OK) { |
753 | 86 return rc; |
87 } | |
88 | |
1454 | 89 last = ngx_http_map_uri_to_path(r, &path, &root, 0); |
90 if (last == NULL) { | |
753 | 91 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
92 } | |
93 | |
94 log = r->connection->log; | |
95 | |
1454 | 96 path.len = last - path.data; |
753 | 97 |
1454 | 98 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, |
99 "http flv filename: \"%V\"", &path); | |
100 | |
101 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
753 | 102 |
2068
75a8d34459c5
ngx_memzero() ngx_open_file_info_t
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
103 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
|
104 |
3178 | 105 of.read_ahead = clcf->read_ahead; |
2129 | 106 of.directio = clcf->directio; |
1767
c42431762903
open_file_cache_retest > open_file_cache_valid
Igor Sysoev <igor@sysoev.ru>
parents:
1696
diff
changeset
|
107 of.valid = clcf->open_file_cache_valid; |
1772 | 108 of.min_uses = clcf->open_file_cache_min_uses; |
1454 | 109 of.errors = clcf->open_file_cache_errors; |
1457 | 110 of.events = clcf->open_file_cache_events; |
1560
25ee6eee7573
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1553
diff
changeset
|
111 |
1799 | 112 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) |
113 != NGX_OK) | |
114 { | |
1454 | 115 switch (of.err) { |
116 | |
117 case 0: | |
118 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
119 | |
120 case NGX_ENOENT: | |
121 case NGX_ENOTDIR: | |
122 case NGX_ENAMETOOLONG: | |
123 | |
753 | 124 level = NGX_LOG_ERR; |
125 rc = NGX_HTTP_NOT_FOUND; | |
1454 | 126 break; |
753 | 127 |
1454 | 128 case NGX_EACCES: |
129 | |
753 | 130 level = NGX_LOG_ERR; |
131 rc = NGX_HTTP_FORBIDDEN; | |
1454 | 132 break; |
753 | 133 |
1454 | 134 default: |
135 | |
753 | 136 level = NGX_LOG_CRIT; |
137 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1454 | 138 break; |
753 | 139 } |
140 | |
141 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { | |
1454 | 142 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
|
143 "%s \"%s\" failed", of.failed, path.data); |
753 | 144 } |
145 | |
146 return rc; | |
147 } | |
148 | |
1454 | 149 if (!of.is_file) { |
753 | 150 |
1696 | 151 if (ngx_close_file(of.fd) == NGX_FILE_ERROR) { |
753 | 152 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
153 ngx_close_file_n " \"%s\" failed", path.data); | |
154 } | |
155 | |
156 return NGX_DECLINED; | |
157 } | |
158 | |
2444
aee735f41627
set r->root_tested for non-error_page response only
Igor Sysoev <igor@sysoev.ru>
parents:
2415
diff
changeset
|
159 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
|
160 |
753 | 161 start = 0; |
1454 | 162 len = of.size; |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
163 i = 1; |
753 | 164 |
165 if (r->args.len) { | |
166 | |
2415 | 167 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
|
168 |
2415 | 169 start = ngx_atoof(value.data, value.len); |
753 | 170 |
171 if (start == NGX_ERROR || start >= len) { | |
172 start = 0; | |
173 } | |
174 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
175 if (start) { |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
176 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
|
177 i = 0; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
178 } |
753 | 179 } |
180 } | |
181 | |
182 log->action = "sending flv to client"; | |
183 | |
184 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
|
185 r->headers_out.content_length_n = len; |
1454 | 186 r->headers_out.last_modified_time = of.mtime; |
753 | 187 |
188 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
|
189 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
753 | 190 } |
191 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
192 if (i == 0) { |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
193 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
194 if (b == NULL) { |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
195 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
196 } |
753 | 197 |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
198 b->pos = ngx_flv_header; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
199 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
|
200 b->memory = 1; |
753 | 201 |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
202 out[0].buf = b; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
203 out[0].next = &out[1]; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
204 } |
753 | 205 |
781
836f099aa5cb
allow ranges for full flv files
Igor Sysoev <igor@sysoev.ru>
parents:
774
diff
changeset
|
206 |
753 | 207 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); |
208 if (b == NULL) { | |
209 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
210 } | |
211 | |
212 b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); | |
213 if (b->file == NULL) { | |
214 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
215 } | |
216 | |
2122
d090fa684433
allow range for partial flv response
Igor Sysoev <igor@sysoev.ru>
parents:
2087
diff
changeset
|
217 r->allow_ranges = 1; |
d090fa684433
allow range for partial flv response
Igor Sysoev <igor@sysoev.ru>
parents:
2087
diff
changeset
|
218 |
753 | 219 rc = ngx_http_send_header(r); |
220 | |
221 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
222 return rc; | |
223 } | |
224 | |
225 b->file_pos = start; | |
1454 | 226 b->file_last = of.size; |
753 | 227 |
228 b->in_file = b->file_last ? 1: 0; | |
229 b->last_buf = 1; | |
230 b->last_in_chain = 1; | |
231 | |
1696 | 232 b->file->fd = of.fd; |
753 | 233 b->file->name = path; |
234 b->file->log = log; | |
2231
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
235 b->file->directio = of.is_directio; |
753 | 236 |
237 out[1].buf = b; | |
238 out[1].next = NULL; | |
239 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
240 return ngx_http_output_filter(r, &out[i]); |
753 | 241 } |
242 | |
243 | |
244 static char * | |
245 ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
246 { | |
247 ngx_http_core_loc_conf_t *clcf; | |
248 | |
249 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
250 clcf->handler = ngx_http_flv_handler; | |
251 | |
252 return NGX_CONF_OK; | |
253 } |