Mercurial > hg > nginx-vendor-0-5
comparison src/http/modules/proxy/ngx_http_proxy_cache.c @ 0:f0b350454894 NGINX_0_1_0
nginx 0.1.0
*) The first public version.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 04 Oct 2004 00:00:00 +0400 |
parents | |
children | 46833bd150cb |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0b350454894 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 #include <ngx_http_proxy_handler.h> | |
11 | |
12 | |
13 static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p, | |
14 int rc); | |
15 static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p); | |
16 static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p); | |
17 | |
18 | |
19 int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p) | |
20 { | |
21 char *last; | |
22 ngx_http_request_t *r; | |
23 ngx_http_proxy_cache_t *c; | |
24 ngx_http_proxy_upstream_conf_t *u; | |
25 | |
26 r = p->request; | |
27 | |
28 if (!(c = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_cache_t)))) { | |
29 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
30 } | |
31 | |
32 p->cache = c; | |
33 | |
34 c->ctx.file.fd = NGX_INVALID_FILE; | |
35 c->ctx.file.log = r->connection->log; | |
36 c->ctx.path = p->lcf->cache_path; | |
37 | |
38 u = p->lcf->upstream; | |
39 | |
40 c->ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len; | |
41 if (!(c->ctx.key.data = ngx_palloc(r->pool, c->ctx.key.len + 1))) { | |
42 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
43 } | |
44 | |
45 last = ngx_cpymem(c->ctx.key.data, u->url.data, u->url.len); | |
46 | |
47 last = ngx_cpymem(last, r->uri.data + u->location->len, | |
48 r->uri.len - u->location->len); | |
49 | |
50 if (r->args.len > 0) { | |
51 *(last++) = '?'; | |
52 last = ngx_cpymem(last, r->args.data, r->args.len); | |
53 } | |
54 *last = '\0'; | |
55 | |
56 p->header_in = ngx_create_temp_hunk(r->pool, p->lcf->header_buffer_size); | |
57 if (p->header_in == NULL) { | |
58 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
59 } | |
60 p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; | |
61 | |
62 c->ctx.buf = p->header_in; | |
63 c->ctx.log = r->connection->log; | |
64 | |
65 return ngx_http_proxy_process_cached_response(p, | |
66 ngx_http_cache_get_file(r, &c->ctx)); | |
67 } | |
68 | |
69 | |
70 static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p, | |
71 int rc) | |
72 { | |
73 if (rc == NGX_OK) { | |
74 p->state->cache_state = NGX_HTTP_PROXY_CACHE_HIT; | |
75 p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; | |
76 | |
77 if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) { | |
78 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
79 } | |
80 | |
81 p->valid_header_in = 1; | |
82 | |
83 return ngx_http_proxy_send_cached_response(p); | |
84 } | |
85 | |
86 if (rc == NGX_HTTP_CACHE_STALE) { | |
87 p->state->cache_state = NGX_HTTP_PROXY_CACHE_EXPR; | |
88 | |
89 } else if (rc == NGX_HTTP_CACHE_AGED) { | |
90 p->state->cache_state = NGX_HTTP_PROXY_CACHE_AGED; | |
91 } | |
92 | |
93 if (rc == NGX_HTTP_CACHE_STALE || rc == NGX_HTTP_CACHE_AGED) { | |
94 p->state->expired = ngx_time() - p->cache->ctx.expires; | |
95 p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; | |
96 | |
97 if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) { | |
98 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
99 } | |
100 | |
101 p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; | |
102 p->header_in->last = p->header_in->pos; | |
103 | |
104 p->stale = 1; | |
105 p->valid_header_in = 1; | |
106 | |
107 } else if (rc == NGX_DECLINED) { | |
108 p->state->cache_state = NGX_HTTP_PROXY_CACHE_MISS; | |
109 p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; | |
110 p->header_in->last = p->header_in->pos; | |
111 } | |
112 | |
113 if (p->lcf->busy_lock) { | |
114 p->try_busy_lock = 1; | |
115 | |
116 p->header_in->pos = p->header_in->start; | |
117 p->header_in->last = p->header_in->start; | |
118 | |
119 p->busy_lock.time = 0; | |
120 p->busy_lock.event = p->request->connection->read; | |
121 p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler; | |
122 p->busy_lock.md5 = p->cache->ctx.md5; | |
123 | |
124 ngx_http_proxy_cache_busy_lock(p); | |
125 return NGX_DONE; | |
126 } | |
127 | |
128 return ngx_http_proxy_request_upstream(p); | |
129 } | |
130 | |
131 | |
132 static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) | |
133 { | |
134 int rc, i; | |
135 ngx_table_elt_t *h; | |
136 ngx_http_request_t *r; | |
137 ngx_http_proxy_cache_t *c; | |
138 | |
139 rc = ngx_http_proxy_parse_status_line(p); | |
140 | |
141 c = p->cache; | |
142 r = p->request; | |
143 | |
144 if (rc == NGX_AGAIN) { | |
145 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
146 "\"proxy_header_buffer_size\" " | |
147 "is too small to read header from \"%s\"", | |
148 c->ctx.file.name.data); | |
149 return NGX_ERROR; | |
150 } | |
151 | |
152 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { | |
153 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
154 "no valid HTTP/1.0 header in \"%s\"", | |
155 c->ctx.file.name.data); | |
156 return NGX_ERROR; | |
157 } | |
158 | |
159 /* rc == NGX_OK */ | |
160 | |
161 c->status = p->status; | |
162 c->status_line.len = p->status_end - p->status_start; | |
163 c->status_line.data = ngx_palloc(r->pool, c->status_line.len + 1); | |
164 if (c->status_line.data == NULL) { | |
165 return NGX_ERROR; | |
166 } | |
167 | |
168 /* reset for the possible parsing the upstream header */ | |
169 | |
170 p->status = 0; | |
171 p->status_count = 0; | |
172 | |
173 ngx_cpystrn(c->status_line.data, p->status_start, c->status_line.len + 1); | |
174 | |
175 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
176 "http cache status %d \"%s\"", | |
177 c->status, c->status_line.data); | |
178 | |
179 /* TODO: ngx_init_table */ | |
180 c->headers_in.headers = ngx_create_table(r->pool, 20); | |
181 | |
182 for ( ;; ) { | |
183 rc = ngx_http_parse_header_line(r, p->header_in); | |
184 | |
185 if (rc == NGX_OK) { | |
186 | |
187 /* a header line has been parsed successfully */ | |
188 | |
189 h = ngx_http_add_header(&c->headers_in, ngx_http_proxy_headers_in); | |
190 if (h == NULL) { | |
191 return NGX_ERROR; | |
192 } | |
193 | |
194 h->key.len = r->header_name_end - r->header_name_start; | |
195 h->value.len = r->header_end - r->header_start; | |
196 | |
197 h->key.data = ngx_palloc(r->pool, | |
198 h->key.len + 1 + h->value.len + 1); | |
199 if (h->key.data == NULL) { | |
200 return NGX_ERROR; | |
201 } | |
202 | |
203 h->value.data = h->key.data + h->key.len + 1; | |
204 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
205 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | |
206 | |
207 for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) { | |
208 if (ngx_http_proxy_headers_in[i].name.len != h->key.len) { | |
209 continue; | |
210 } | |
211 | |
212 if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data, | |
213 h->key.data) == 0) | |
214 { | |
215 *((ngx_table_elt_t **) ((char *) &c->headers_in | |
216 + ngx_http_proxy_headers_in[i].offset)) = h; | |
217 break; | |
218 } | |
219 } | |
220 | |
221 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
222 "http cache header: \"%s: %s\"", | |
223 h->key.data, h->value.data); | |
224 | |
225 continue; | |
226 | |
227 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | |
228 | |
229 /* a whole header has been parsed successfully */ | |
230 | |
231 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
232 "http cache header done"); | |
233 | |
234 c->ctx.file_start = p->header_in->pos - p->header_in->start; | |
235 | |
236 return NGX_OK; | |
237 | |
238 } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) { | |
239 | |
240 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
241 "invalid header in \"%s\"", | |
242 c->ctx.file.name.data); | |
243 return NGX_ERROR; | |
244 } | |
245 | |
246 /* rc == NGX_AGAIN || rc == NGX_HTTP_PARSE_TOO_LONG_HEADER */ | |
247 | |
248 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
249 "\"proxy_header_buffer_size\" " | |
250 "is too small to read header from \"%s\"", | |
251 c->ctx.file.name.data); | |
252 return NGX_ERROR; | |
253 } | |
254 } | |
255 | |
256 | |
257 void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p) | |
258 { | |
259 int rc, ft_type; | |
260 | |
261 rc = ngx_http_busy_lock_cachable(p->lcf->busy_lock, &p->busy_lock, | |
262 p->try_busy_lock); | |
263 | |
264 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0, | |
265 "http cache busy lock cachable: %d", rc); | |
266 | |
267 if (rc == NGX_OK) { | |
268 if (p->try_busy_lock) { | |
269 p->busy_locked = 1; | |
270 p->header_in->pos = p->header_in->start + p->cache->ctx.header_size; | |
271 p->header_in->last = p->header_in->pos; | |
272 | |
273 ngx_http_proxy_request_upstream(p); | |
274 return; | |
275 } | |
276 | |
277 ngx_http_proxy_cache_look_complete_request(p); | |
278 return; | |
279 } | |
280 | |
281 p->try_busy_lock = 0; | |
282 | |
283 if (p->cache->ctx.file.fd != NGX_INVALID_FILE | |
284 && !p->cache->ctx.file.info_valid) | |
285 { | |
286 if (ngx_fd_info(p->cache->ctx.file.fd, &p->cache->ctx.file.info) | |
287 == NGX_FILE_ERROR) | |
288 { | |
289 ngx_log_error(NGX_LOG_CRIT, p->request->connection->log, ngx_errno, | |
290 ngx_fd_info_n " \"%s\" failed", | |
291 p->cache->ctx.file.name.data); | |
292 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
293 return; | |
294 } | |
295 | |
296 p->cache->ctx.file.info_valid = 1; | |
297 } | |
298 | |
299 if (rc == NGX_AGAIN) { | |
300 | |
301 if ((ngx_event_flags & (NGX_USE_CLEAR_EVENT|NGX_HAVE_KQUEUE_EVENT)) | |
302 && !p->request->connection->write->active) | |
303 { | |
304 /* | |
305 * kqueue allows to detect when client closes prematurely | |
306 * connection | |
307 */ | |
308 | |
309 p->request->connection->write->event_handler = | |
310 ngx_http_proxy_check_broken_connection; | |
311 | |
312 if (ngx_add_event(p->request->connection->write, NGX_WRITE_EVENT, | |
313 NGX_CLEAR_EVENT) == NGX_ERROR) | |
314 { | |
315 ngx_http_proxy_finalize_request(p, | |
316 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
317 return; | |
318 } | |
319 } | |
320 | |
321 return; | |
322 } | |
323 | |
324 ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock); | |
325 | |
326 if (rc == NGX_DONE) { | |
327 ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK; | |
328 | |
329 } else { | |
330 /* rc == NGX_ERROR */ | |
331 ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING; | |
332 } | |
333 | |
334 if (p->stale && (p->lcf->use_stale & ft_type)) { | |
335 ngx_http_proxy_finalize_request(p, | |
336 ngx_http_proxy_send_cached_response(p)); | |
337 return; | |
338 } | |
339 | |
340 p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE; | |
341 ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE); | |
342 } | |
343 | |
344 | |
345 static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p) | |
346 { | |
347 int rc; | |
348 ngx_http_cache_ctx_t *ctx; | |
349 | |
350 if (!(ctx = ngx_pcalloc(p->request->pool, sizeof(ngx_http_cache_ctx_t)))) { | |
351 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
352 return; | |
353 } | |
354 | |
355 *ctx = p->cache->ctx; | |
356 | |
357 rc = ngx_http_cache_open_file(ctx, ngx_file_uniq(&p->cache->ctx.file.info)); | |
358 | |
359 if (rc == NGX_DECLINED || rc == NGX_HTTP_CACHE_THE_SAME) { | |
360 p->try_busy_lock = 1; | |
361 p->busy_lock.time = 0; | |
362 ngx_http_proxy_cache_busy_lock(p); | |
363 return; | |
364 } | |
365 | |
366 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0, | |
367 "http cache old fd:%d, new fd:%d", | |
368 p->cache->ctx.file.fd, ctx->file.fd); | |
369 | |
370 if (p->cache->ctx.file.fd != NGX_INVALID_FILE) { | |
371 if (ngx_close_file(p->cache->ctx.file.fd) == NGX_FILE_ERROR) { | |
372 ngx_log_error(NGX_LOG_ALERT, p->request->connection->log, ngx_errno, | |
373 ngx_close_file_n " \"%s\" failed", | |
374 p->cache->ctx.file.name.data); | |
375 } | |
376 } | |
377 | |
378 p->cache->ctx = *ctx; | |
379 | |
380 p->status = 0; | |
381 p->status_count = 0; | |
382 | |
383 ngx_http_proxy_finalize_request(p, | |
384 ngx_http_proxy_process_cached_response(p, rc)); | |
385 } | |
386 | |
387 | |
388 int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) | |
389 { | |
390 int rc, len, i; | |
391 off_t rest; | |
392 ngx_hunk_t *h0, *h1; | |
393 ngx_chain_t out[2]; | |
394 ngx_http_request_t *r; | |
395 | |
396 r = p->request; | |
397 | |
398 r->headers_out.status = p->cache->status; | |
399 | |
400 #if 0 | |
401 r->headers_out.content_length_n = -1; | |
402 r->headers_out.content_length = NULL; | |
403 #endif | |
404 | |
405 /* copy an cached header to r->headers_out */ | |
406 | |
407 if (ngx_http_proxy_copy_header(p, &p->cache->headers_in) == NGX_ERROR) { | |
408 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
409 } | |
410 | |
411 /* we need to allocate all before the header would be sent */ | |
412 | |
413 len = p->header_in->end - (p->header_in->start + p->cache->ctx.file_start); | |
414 | |
415 h0 = NULL; | |
416 h1 = NULL; | |
417 | |
418 if (len) { | |
419 if (!((h0 = ngx_calloc_hunk(r->pool)))) { | |
420 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
421 } | |
422 | |
423 if (!((h0->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) { | |
424 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
425 } | |
426 } | |
427 | |
428 if (len < p->cache->ctx.length) { | |
429 if (!((h1 = ngx_calloc_hunk(r->pool)))) { | |
430 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
431 } | |
432 | |
433 if (!((h1->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) { | |
434 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
435 } | |
436 } | |
437 | |
438 rc = ngx_http_send_header(r); | |
439 | |
440 /* NEEDED ??? */ p->header_sent = 1; | |
441 | |
442 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
443 return rc; | |
444 } | |
445 | |
446 rest = p->cache->ctx.length; | |
447 | |
448 if (len) { | |
449 if (p->valid_header_in) { | |
450 h0->pos = p->header_in->start + p->cache->ctx.file_start; | |
451 | |
452 if (len > p->cache->ctx.length) { | |
453 h0->last = h0->pos + p->cache->ctx.length; | |
454 | |
455 } else { | |
456 h0->last = p->header_in->end; | |
457 } | |
458 | |
459 h0->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; | |
460 } | |
461 | |
462 h0->type |= NGX_HUNK_FILE; | |
463 h0->file_pos = p->cache->ctx.file_start; | |
464 | |
465 h0->file->fd = p->cache->ctx.file.fd; | |
466 h0->file->log = r->connection->log; | |
467 | |
468 if (len > p->cache->ctx.length) { | |
469 h0->file_last = h0->file_pos + p->cache->ctx.length; | |
470 rest = 0; | |
471 | |
472 } else { | |
473 h0->file_last = h0->file_pos + len; | |
474 rest -= len; | |
475 } | |
476 | |
477 out[0].hunk = h0; | |
478 out[0].next = &out[1]; | |
479 i = 0; | |
480 | |
481 } else { | |
482 i = -1; | |
483 } | |
484 | |
485 if (rest) { | |
486 h1->file_pos = p->cache->ctx.file_start + len; | |
487 h1->file_last = h1->file_pos + rest; | |
488 h1->type = NGX_HUNK_FILE; | |
489 | |
490 h1->file->fd = p->cache->ctx.file.fd; | |
491 h1->file->log = r->connection->log; | |
492 | |
493 out[++i].hunk = h1; | |
494 } | |
495 | |
496 out[i].next = NULL; | |
497 if (!r->main) { | |
498 out[i].hunk->type |= NGX_HUNK_LAST; | |
499 } | |
500 | |
501 r->file.fd = p->cache->ctx.file.fd; | |
502 | |
503 return ngx_http_output_filter(r, out); | |
504 } | |
505 | |
506 | |
507 int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) | |
508 { | |
509 time_t date, last_modified, expires, t; | |
510 ngx_http_proxy_headers_in_t *h; | |
511 | |
512 switch (p->upstream->status) { | |
513 case NGX_HTTP_OK: | |
514 case NGX_HTTP_MOVED_PERMANENTLY: | |
515 case NGX_HTTP_MOVED_TEMPORARILY: | |
516 break; | |
517 | |
518 #if 0 | |
519 case NGX_HTTP_NOT_MODIFIED: | |
520 return 1; | |
521 #endif | |
522 | |
523 default: | |
524 return 0; | |
525 } | |
526 | |
527 h = &p->upstream->headers_in; | |
528 | |
529 date = NGX_ERROR; | |
530 if (h->date) { | |
531 date = ngx_http_parse_time(h->date->value.data, h->date->value.len); | |
532 } | |
533 if (date == NGX_ERROR) { | |
534 date = ngx_time(); | |
535 } | |
536 p->cache->ctx.date = date; | |
537 | |
538 last_modified = NGX_ERROR; | |
539 if (h->last_modified) { | |
540 last_modified = ngx_http_parse_time(h->last_modified->value.data, | |
541 h->last_modified->value.len); | |
542 p->cache->ctx.last_modified = last_modified; | |
543 } | |
544 | |
545 if (h->x_accel_expires) { | |
546 expires = ngx_atoi(h->x_accel_expires->value.data, | |
547 h->x_accel_expires->value.len); | |
548 if (expires != NGX_ERROR) { | |
549 p->state->reason = NGX_HTTP_PROXY_CACHE_XAE; | |
550 p->state->expires = expires; | |
551 p->cache->ctx.expires = date + expires; | |
552 return (expires > 0); | |
553 } | |
554 } | |
555 | |
556 if (!p->lcf->ignore_expires) { | |
557 | |
558 /* TODO: Cache-Control: no-cache, max-age= */ | |
559 | |
560 if (h->expires) { | |
561 expires = ngx_http_parse_time(h->expires->value.data, | |
562 h->expires->value.len); | |
563 if (expires != NGX_ERROR) { | |
564 p->state->reason = NGX_HTTP_PROXY_CACHE_EXP; | |
565 p->state->expires = expires - date; | |
566 p->cache->ctx.expires = expires; | |
567 return (date < expires); | |
568 } | |
569 } | |
570 } | |
571 | |
572 if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) { | |
573 p->state->reason = NGX_HTTP_PROXY_CACHE_MVD; | |
574 p->state->expires = /* STUB: 1 hour */ 60 * 60; | |
575 p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60; | |
576 return 1; | |
577 } | |
578 | |
579 if (p->upstream->status == NGX_HTTP_MOVED_TEMPORARILY) { | |
580 return 1; | |
581 } | |
582 | |
583 if (last_modified != NGX_ERROR && p->lcf->lm_factor > 0) { | |
584 | |
585 /* FIXME: time_t == int_64_t, we can use fpu */ | |
586 | |
587 p->state->reason = NGX_HTTP_PROXY_CACHE_LMF; | |
588 t = (time_t) | |
589 ((((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100); | |
590 p->state->expires = t; | |
591 p->cache->ctx.expires = ngx_time() + t; | |
592 return 1; | |
593 } | |
594 | |
595 if (p->lcf->default_expires > 0) { | |
596 p->state->reason = NGX_HTTP_PROXY_CACHE_PDE; | |
597 p->state->expires = p->lcf->default_expires; | |
598 p->cache->ctx.expires = ngx_time() + p->lcf->default_expires; | |
599 return 1; | |
600 } | |
601 | |
602 return 0; | |
603 } | |
604 | |
605 | |
606 int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p) | |
607 { | |
608 ngx_event_pipe_t *ep; | |
609 | |
610 if (p->cache == NULL) { | |
611 return NGX_OK; | |
612 } | |
613 | |
614 ep = p->upstream->event_pipe; | |
615 | |
616 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0, | |
617 "http cache update len: " OFF_T_FMT ":" OFF_T_FMT, | |
618 p->cache->ctx.length, ep->read_length); | |
619 | |
620 if (p->cache->ctx.length == -1) { | |
621 /* TODO: test rc */ | |
622 ngx_write_file(&ep->temp_file->file, | |
623 (char *) &ep->read_length, sizeof(off_t), | |
624 offsetof(ngx_http_cache_header_t, length)); | |
625 } | |
626 | |
627 return ngx_http_cache_update_file(p->request, &p->cache->ctx, | |
628 &ep->temp_file->file.name); | |
629 } |