Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 1 | |
| 2 | #include <ngx_config.h> |
| 3 | #include <ngx_core.h> |
| 4 | #include <ngx_http.h> |
| 5 | #include <ngx_http_proxy_handler.h> |
| 6 | |
| 7 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 8 | static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p); |
| 9 | |
| 10 | |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 11 | int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p) |
| 12 | { |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 13 | int rc; |
| 14 | char *last; |
| 15 | ngx_http_request_t *r; |
| 16 | ngx_http_proxy_cache_t *c; |
| 17 | ngx_http_proxy_upstream_conf_t *u; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 18 | |
| 19 | r = p->request; |
| 20 | |
| 21 | if (!(c = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_cache_t)))) { |
| 22 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 23 | } |
| 24 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 25 | p->cache = c; |
| 26 | |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 27 | c->ctx.file.fd = NGX_INVALID_FILE; |
| 28 | c->ctx.file.log = r->connection->log; |
| 29 | c->ctx.path = p->lcf->cache_path; |
| 30 | |
| 31 | u = p->lcf->upstream; |
| 32 | |
| 33 | c->ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len; |
| 34 | if (!(c->ctx.key.data = ngx_palloc(r->pool, c->ctx.key.len + 1))) { |
| 35 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 36 | } |
| 37 | |
| 38 | last = ngx_cpymem(c->ctx.key.data, u->url.data, u->url.len); |
| 39 | |
| 40 | last = ngx_cpymem(last, r->uri.data + u->location->len, |
| 41 | r->uri.len - u->location->len); |
| 42 | |
| 43 | if (r->args.len > 0) { |
| 44 | *(last++) = '?'; |
| 45 | last = ngx_cpymem(last, r->args.data, r->args.len); |
| 46 | } |
| 47 | *last = '\0'; |
| 48 | |
| 49 | p->header_in = ngx_create_temp_hunk(r->pool, p->lcf->header_buffer_size); |
| 50 | if (p->header_in == NULL) { |
| 51 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 52 | } |
| 53 | p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; |
| 54 | |
| 55 | c->ctx.buf = p->header_in; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 56 | |
| 57 | rc = ngx_http_cache_get_file(r, &c->ctx); |
| 58 | |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 59 | switch (rc) { |
| 60 | case NGX_HTTP_CACHE_STALE: |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 61 | p->stale = 1; |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 62 | p->state->cache = NGX_HTTP_PROXY_CACHE_EXPR; |
| 63 | break; |
| 64 | |
| 65 | case NGX_HTTP_CACHE_AGED: |
| 66 | p->stale = 1; |
| 67 | p->state->cache = NGX_HTTP_PROXY_CACHE_AGED; |
| 68 | break; |
| 69 | |
| 70 | case NGX_OK: |
| 71 | p->state->cache = NGX_HTTP_PROXY_CACHE_HIT; |
| 72 | break; |
| 73 | |
| 74 | default: |
| 75 | p->state->cache = NGX_HTTP_PROXY_CACHE_MISS; |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 76 | } |
| 77 | |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 78 | if (rc == NGX_OK |
| 79 | || rc == NGX_HTTP_CACHE_STALE |
| 80 | || rc == NGX_HTTP_CACHE_AGED) |
| 81 | { |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 82 | p->header_in->pos = p->header_in->start + c->ctx.header_size; |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 83 | if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) { |
| 84 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 85 | } |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 86 | p->header_in->pos = p->header_in->start + c->ctx.header_size; |
| 87 | p->header_in->last = p->header_in->pos; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 88 | |
| 89 | } else if (rc == NGX_DECLINED) { |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 90 | p->header_in->pos = p->header_in->start + c->ctx.header_size; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 91 | p->header_in->last = p->header_in->pos; |
| 92 | } |
| 93 | |
| 94 | return rc; |
| 95 | } |
| 96 | |
| 97 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 98 | static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p) |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 99 | { |
| 100 | int rc, i; |
| 101 | ngx_table_elt_t *h; |
| 102 | ngx_http_request_t *r; |
| 103 | ngx_http_proxy_cache_t *c; |
| 104 | |
| 105 | rc = ngx_http_proxy_parse_status_line(p); |
| 106 | |
| 107 | c = p->cache; |
| 108 | r = p->request; |
| 109 | |
| 110 | if (rc == NGX_AGAIN) { |
| 111 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
| 112 | "\"proxy_header_buffer_size\" " |
| 113 | "is too small to read header from \"%s\"", |
| 114 | c->ctx.file.name.data); |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 115 | return NGX_ERROR; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { |
| 119 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
| 120 | "no valid HTTP/1.0 header in \"%s\"", |
| 121 | c->ctx.file.name.data); |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 122 | return NGX_ERROR; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | /* rc == NGX_OK */ |
| 126 | |
| 127 | c->status = p->status; |
| 128 | c->status_line.len = p->status_end - p->status_start; |
| 129 | c->status_line.data = ngx_palloc(r->pool, c->status_line.len + 1); |
| 130 | if (c->status_line.data == NULL) { |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 131 | return NGX_ERROR; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 132 | } |
| 133 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 134 | /* reset for the possible parsing the upstream header */ |
| 135 | |
| 136 | p->status = 0; |
| 137 | p->status_count = 0; |
| 138 | |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 139 | ngx_cpystrn(c->status_line.data, p->status_start, c->status_line.len + 1); |
| 140 | |
| 141 | ngx_log_debug(r->connection->log, "http cache status %d '%s'" _ |
| 142 | c->status _ c->status_line.data); |
| 143 | |
| 144 | c->headers_in.headers = ngx_create_table(r->pool, 20); |
| 145 | |
| 146 | for ( ;; ) { |
| 147 | rc = ngx_http_parse_header_line(r, p->header_in); |
| 148 | |
| 149 | if (rc == NGX_OK) { |
| 150 | |
| 151 | /* a header line has been parsed successfully */ |
| 152 | |
| 153 | h = ngx_http_add_header(&c->headers_in, ngx_http_proxy_headers_in); |
| 154 | if (h == NULL) { |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 155 | return NGX_ERROR; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | h->key.len = r->header_name_end - r->header_name_start; |
| 159 | h->value.len = r->header_end - r->header_start; |
| 160 | |
| 161 | h->key.data = ngx_palloc(r->pool, |
| 162 | h->key.len + 1 + h->value.len + 1); |
| 163 | if (h->key.data == NULL) { |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 164 | return NGX_ERROR; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | h->value.data = h->key.data + h->key.len + 1; |
| 168 | ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); |
| 169 | ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); |
| 170 | |
| 171 | for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) { |
| 172 | if (ngx_http_proxy_headers_in[i].name.len != h->key.len) { |
| 173 | continue; |
| 174 | } |
| 175 | |
| 176 | if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data, |
| 177 | h->key.data) == 0) |
| 178 | { |
| 179 | *((ngx_table_elt_t **) ((char *) &c->headers_in |
| 180 | + ngx_http_proxy_headers_in[i].offset)) = h; |
| 181 | break; |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | ngx_log_debug(r->connection->log, "HTTP cache header: '%s: %s'" _ |
| 186 | h->key.data _ h->value.data); |
| 187 | |
| 188 | continue; |
| 189 | |
| 190 | } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { |
| 191 | |
| 192 | /* a whole header has been parsed successfully */ |
| 193 | |
| 194 | ngx_log_debug(r->connection->log, "HTTP header done"); |
| 195 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 196 | c->ctx.file_start = p->header_in->pos - p->header_in->start; |
| 197 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 198 | return NGX_OK; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 199 | |
| 200 | } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) { |
| 201 | |
| 202 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
| 203 | "invalid header in \"%s\"", |
| 204 | c->ctx.file.name.data); |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 205 | return NGX_ERROR; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | /* rc == NGX_AGAIN || rc == NGX_HTTP_PARSE_TOO_LONG_HEADER */ |
| 209 | |
| 210 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
| 211 | "\"proxy_header_buffer_size\" " |
| 212 | "is too small to read header from \"%s\"", |
| 213 | c->ctx.file.name.data); |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 214 | return NGX_ERROR; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 215 | } |
| 216 | } |
| 217 | |
| 218 | |
Igor Sysoev | e8732b0 | 2003-11-05 17:03:41 +0000 | [diff] [blame^] | 219 | #if 0 |
| 220 | |
| 221 | static void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p) |
| 222 | { |
| 223 | rc = ngx_http_busy_lock(p->lcf->busy_lock, p->cache->ctx.md5); |
| 224 | |
| 225 | if (rc == NGX_OK) { |
| 226 | ngx_http_proxy_request_upstream(p); |
| 227 | } |
| 228 | |
| 229 | if (rc == NGX_AGAIN) { |
| 230 | if (p->busy_lock_time) { |
| 231 | ngx_add_timer(p->request->connection->read, 1000); |
| 232 | return; |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | rc == NGX_ERROR |
| 237 | check waitn |
| 238 | } |
| 239 | |
| 240 | #endif |
| 241 | |
| 242 | |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 243 | int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p) |
| 244 | { |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 245 | int rc, len, i; |
| 246 | off_t rest; |
| 247 | ngx_hunk_t *h0, *h1; |
| 248 | ngx_chain_t out[2]; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 249 | ngx_http_request_t *r; |
| 250 | |
| 251 | r = p->request; |
| 252 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 253 | r->headers_out.status = p->cache->status; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 254 | |
| 255 | #if 0 |
| 256 | r->headers_out.content_length_n = -1; |
| 257 | r->headers_out.content_length = NULL; |
| 258 | #endif |
| 259 | |
| 260 | /* copy an cached header to r->headers_out */ |
| 261 | |
| 262 | if (ngx_http_proxy_copy_header(p, &p->cache->headers_in) == NGX_ERROR) { |
| 263 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 264 | } |
| 265 | |
| 266 | /* we need to allocate all before the header would be sent */ |
| 267 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 268 | len = p->header_in->end - (p->header_in->start + p->cache->ctx.file_start); |
| 269 | |
| 270 | h0 = NULL; |
| 271 | h1 = NULL; |
| 272 | |
| 273 | if (len) { |
| 274 | if (!((h0 = ngx_calloc_hunk(r->pool)))) { |
| 275 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 276 | } |
| 277 | |
| 278 | if (!((h0->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) { |
| 279 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 280 | } |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 281 | } |
| 282 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 283 | if (len < p->cache->ctx.length) { |
| 284 | if (!((h1 = ngx_calloc_hunk(r->pool)))) { |
| 285 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 286 | } |
| 287 | |
| 288 | if (!((h1->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) { |
| 289 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 290 | } |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 291 | } |
| 292 | |
| 293 | rc = ngx_http_send_header(r); |
| 294 | |
| 295 | /* NEEDED ??? */ p->header_sent = 1; |
| 296 | |
| 297 | if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { |
| 298 | return rc; |
| 299 | } |
| 300 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 301 | rest = p->cache->ctx.length; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 302 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 303 | if (len) { |
| 304 | if (p->valid_header_in) { |
| 305 | h0->pos = p->header_in->start + p->cache->ctx.file_start; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 306 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 307 | if (len > p->cache->ctx.length) { |
| 308 | h0->last = h0->pos + p->cache->ctx.length; |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 309 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 310 | } else { |
| 311 | h0->last = p->header_in->end; |
| 312 | } |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 313 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 314 | h0->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; |
| 315 | } |
| 316 | |
| 317 | h0->type |= NGX_HUNK_FILE; |
| 318 | h0->file_pos = p->cache->ctx.file_start; |
| 319 | |
| 320 | h0->file->fd = p->cache->ctx.file.fd; |
| 321 | h0->file->log = r->connection->log; |
| 322 | |
| 323 | if (len > p->cache->ctx.length) { |
| 324 | h0->file_last = h0->file_pos + p->cache->ctx.length; |
| 325 | rest = 0; |
| 326 | |
| 327 | } else { |
| 328 | h0->file_last = h0->file_pos + len; |
| 329 | rest -= len; |
| 330 | } |
| 331 | |
| 332 | out[0].hunk = h0; |
| 333 | out[0].next = &out[1]; |
| 334 | i = 0; |
| 335 | |
| 336 | } else { |
| 337 | i = -1; |
| 338 | } |
| 339 | |
| 340 | if (rest) { |
| 341 | h1->file_pos = p->cache->ctx.file_start + len; |
| 342 | h1->file_last = h1->file_pos + rest; |
| 343 | h1->type = NGX_HUNK_FILE; |
| 344 | |
| 345 | h1->file->fd = p->cache->ctx.file.fd; |
| 346 | h1->file->log = r->connection->log; |
| 347 | |
| 348 | out[++i].hunk = h1; |
| 349 | } |
| 350 | |
| 351 | out[i].next = NULL; |
| 352 | if (!r->main) { |
| 353 | out[i].hunk->type |= NGX_HUNK_LAST; |
| 354 | } |
| 355 | |
| 356 | return ngx_http_output_filter(r, out); |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 357 | } |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 358 | |
| 359 | |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 360 | int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p) |
| 361 | { |
| 362 | time_t date, last_modified, expires; |
| 363 | ngx_http_proxy_headers_in_t *h; |
| 364 | |
| 365 | switch (p->upstream->status) { |
| 366 | case NGX_HTTP_OK: |
| 367 | case NGX_HTTP_MOVED_PERMANENTLY: |
| 368 | case NGX_HTTP_MOVED_TEMPORARILY: |
| 369 | break; |
| 370 | |
| 371 | #if 0 |
| 372 | case NGX_HTTP_NOT_MODIFIED: |
| 373 | return 1; |
| 374 | #endif |
| 375 | |
| 376 | default: |
| 377 | return 0; |
| 378 | } |
| 379 | |
| 380 | h = &p->upstream->headers_in; |
| 381 | |
| 382 | date = NGX_ERROR; |
| 383 | if (h->date) { |
| 384 | date = ngx_http_parse_time(h->date->value.data, h->date->value.len); |
| 385 | } |
| 386 | if (date == NGX_ERROR) { |
| 387 | date = ngx_time(); |
| 388 | } |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 389 | p->cache->ctx.date = date; |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 390 | |
| 391 | last_modified = NGX_ERROR; |
| 392 | if (h->last_modified) { |
| 393 | last_modified = ngx_http_parse_time(h->last_modified->value.data, |
| 394 | h->last_modified->value.len); |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 395 | p->cache->ctx.last_modified = last_modified; |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 396 | } |
| 397 | |
| 398 | if (h->x_accel_expires) { |
| 399 | expires = ngx_atoi(h->x_accel_expires->value.data, |
| 400 | h->x_accel_expires->value.len); |
| 401 | if (expires != NGX_ERROR) { |
| 402 | p->state->reason = NGX_HTTP_PROXY_CACHE_XAE; |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 403 | p->cache->ctx.expires = date + expires; |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 404 | return (expires > 0); |
| 405 | } |
| 406 | } |
| 407 | |
| 408 | if (!p->lcf->ignore_expires) { |
| 409 | |
| 410 | /* TODO: Cache-Control: no-cache, max-age= */ |
| 411 | |
| 412 | if (h->expires) { |
| 413 | expires = ngx_http_parse_time(h->expires->value.data, |
| 414 | h->expires->value.len); |
| 415 | if (expires != NGX_ERROR) { |
| 416 | p->state->reason = NGX_HTTP_PROXY_CACHE_EXP; |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 417 | p->cache->ctx.expires = expires; |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 418 | return (date < expires); |
| 419 | } |
| 420 | } |
| 421 | } |
| 422 | |
| 423 | if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) { |
| 424 | p->state->reason = NGX_HTTP_PROXY_CACHE_MVD; |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 425 | p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60; |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 426 | return 1; |
| 427 | } |
| 428 | |
| 429 | if (p->upstream->status == NGX_HTTP_MOVED_TEMPORARILY) { |
| 430 | return 1; |
| 431 | } |
| 432 | |
| 433 | if (last_modified != NGX_ERROR && p->lcf->lm_factor > 0) { |
| 434 | |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 435 | /* FIXME: time_t == int_64_t, we can use fpu */ |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 436 | |
| 437 | p->state->reason = NGX_HTTP_PROXY_CACHE_LMF; |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 438 | p->cache->ctx.expires = ngx_time() |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 439 | + (((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100; |
| 440 | return 1; |
| 441 | } |
| 442 | |
| 443 | if (p->lcf->default_expires > 0) { |
| 444 | p->state->reason = NGX_HTTP_PROXY_CACHE_PDE; |
Igor Sysoev | 9cc1ace | 2003-11-04 22:12:39 +0000 | [diff] [blame] | 445 | p->cache->ctx.expires = p->lcf->default_expires; |
Igor Sysoev | cf80a70 | 2003-11-03 22:20:44 +0000 | [diff] [blame] | 446 | return 1; |
| 447 | } |
| 448 | |
| 449 | return 0; |
| 450 | } |
| 451 | |
| 452 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 453 | int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p) |
| 454 | { |
Igor Sysoev | e8732b0 | 2003-11-05 17:03:41 +0000 | [diff] [blame^] | 455 | ngx_event_pipe_t *ep; |
| 456 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 457 | if (p->cache == NULL) { |
| 458 | return NGX_OK; |
| 459 | } |
| 460 | |
Igor Sysoev | e8732b0 | 2003-11-05 17:03:41 +0000 | [diff] [blame^] | 461 | ep = p->upstream->event_pipe; |
| 462 | |
| 463 | if (p->cache->ctx.length == -1) { |
| 464 | /* TODO: test rc */ |
| 465 | ngx_write_file(&ep->temp_file->file, |
| 466 | (char *) &ep->read_length, sizeof(off_t), |
| 467 | offsetof(ngx_http_cache_header_t, length)); |
| 468 | } |
| 469 | |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 470 | return ngx_http_cache_update_file(p->request, &p->cache->ctx, |
Igor Sysoev | e8732b0 | 2003-11-05 17:03:41 +0000 | [diff] [blame^] | 471 | &ep->temp_file->file.name); |
Igor Sysoev | a1512b1 | 2003-11-03 17:33:31 +0000 | [diff] [blame] | 472 | } |