comparison src/http/modules/proxy/ngx_http_proxy_cache.c @ 170:c42be4185301

nginx-0.0.1-2003-11-03-01:56:18 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 02 Nov 2003 22:56:18 +0000
parents
children aff0e5d32af8
comparison
equal deleted inserted replaced
169:edf29bb717da 170:c42be4185301
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
8 int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p)
9 {
10 int rc;
11 char *last;
12 ngx_http_request_t *r;
13 ngx_http_proxy_cache_t *c;
14 ngx_http_proxy_upstream_t *u;
15
16 r = p->request;
17
18 if (!(c = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_cache_t)))) {
19 return NGX_HTTP_INTERNAL_SERVER_ERROR;
20 }
21
22 c->ctx.file.fd = NGX_INVALID_FILE;
23 c->ctx.file.log = r->connection->log;
24 c->ctx.path = p->lcf->cache_path;
25
26 u = p->lcf->upstream;
27
28 c->ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len;
29 if (!(c->ctx.key.data = ngx_palloc(r->pool, c->ctx.key.len + 1))) {
30 return NGX_HTTP_INTERNAL_SERVER_ERROR;
31 }
32
33 last = ngx_cpymem(c->ctx.key.data, u->url.data, u->url.len);
34
35 last = ngx_cpymem(last, r->uri.data + u->location->len,
36 r->uri.len - u->location->len);
37
38 if (r->args.len > 0) {
39 *(last++) = '?';
40 last = ngx_cpymem(last, r->args.data, r->args.len);
41 }
42 *last = '\0';
43
44 p->header_in = ngx_create_temp_hunk(r->pool, p->lcf->header_buffer_size);
45 if (p->header_in == NULL) {
46 return NGX_HTTP_INTERNAL_SERVER_ERROR;
47 }
48 p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module;
49
50 c->ctx.buf = p->header_in;
51 p->cache = c;
52
53 rc = ngx_http_cache_get_file(r, &c->ctx);
54
55 if (rc == NGX_OK || rc == NGX_STALE) {
56 p->header_in->pos += c->ctx.header.size;
57
58 } else if (rc == NGX_DECLINED) {
59 p->header_in->pos += c->ctx.header.size;
60 p->header_in->last = p->header_in->pos;
61 }
62
63 return rc;
64 }
65
66
67 int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p)
68 {
69 int rc, i;
70 ngx_table_elt_t *h;
71 ngx_http_request_t *r;
72 ngx_http_proxy_cache_t *c;
73
74 rc = ngx_http_proxy_parse_status_line(p);
75
76 c = p->cache;
77 r = p->request;
78
79 if (rc == NGX_AGAIN) {
80 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
81 "\"proxy_header_buffer_size\" "
82 "is too small to read header from \"%s\"",
83 c->ctx.file.name.data);
84 return NGX_HTTP_INTERNAL_SERVER_ERROR;
85 }
86
87 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
88 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
89 "no valid HTTP/1.0 header in \"%s\"",
90 c->ctx.file.name.data);
91 return NGX_HTTP_INTERNAL_SERVER_ERROR;
92 }
93
94 /* rc == NGX_OK */
95
96 c->status = p->status;
97 c->status_line.len = p->status_end - p->status_start;
98 c->status_line.data = ngx_palloc(r->pool, c->status_line.len + 1);
99 if (c->status_line.data == NULL) {
100 return NGX_HTTP_INTERNAL_SERVER_ERROR;
101 }
102
103 ngx_cpystrn(c->status_line.data, p->status_start, c->status_line.len + 1);
104
105 ngx_log_debug(r->connection->log, "http cache status %d '%s'" _
106 c->status _ c->status_line.data);
107
108 c->headers_in.headers = ngx_create_table(r->pool, 20);
109
110 for ( ;; ) {
111 rc = ngx_http_parse_header_line(r, p->header_in);
112
113 if (rc == NGX_OK) {
114
115 /* a header line has been parsed successfully */
116
117 h = ngx_http_add_header(&c->headers_in, ngx_http_proxy_headers_in);
118 if (h == NULL) {
119 return NGX_HTTP_INTERNAL_SERVER_ERROR;
120 }
121
122 h->key.len = r->header_name_end - r->header_name_start;
123 h->value.len = r->header_end - r->header_start;
124
125 h->key.data = ngx_palloc(r->pool,
126 h->key.len + 1 + h->value.len + 1);
127 if (h->key.data == NULL) {
128 return NGX_HTTP_INTERNAL_SERVER_ERROR;
129 }
130
131 h->value.data = h->key.data + h->key.len + 1;
132 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
133 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
134
135 for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) {
136 if (ngx_http_proxy_headers_in[i].name.len != h->key.len) {
137 continue;
138 }
139
140 if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data,
141 h->key.data) == 0)
142 {
143 *((ngx_table_elt_t **) ((char *) &c->headers_in
144 + ngx_http_proxy_headers_in[i].offset)) = h;
145 break;
146 }
147 }
148
149 ngx_log_debug(r->connection->log, "HTTP cache header: '%s: %s'" _
150 h->key.data _ h->value.data);
151
152 continue;
153
154 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
155
156 /* a whole header has been parsed successfully */
157
158 ngx_log_debug(r->connection->log, "HTTP header done");
159
160 return ngx_http_proxy_send_cached_response(p);
161
162 } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) {
163
164 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
165 "invalid header in \"%s\"",
166 c->ctx.file.name.data);
167 return NGX_HTTP_INTERNAL_SERVER_ERROR;
168 }
169
170 /* rc == NGX_AGAIN || rc == NGX_HTTP_PARSE_TOO_LONG_HEADER */
171
172 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
173 "\"proxy_header_buffer_size\" "
174 "is too small to read header from \"%s\"",
175 c->ctx.file.name.data);
176 return NGX_HTTP_INTERNAL_SERVER_ERROR;
177 }
178 }
179
180
181 int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p)
182 {
183 int rc;
184 ngx_hunk_t *h;
185 ngx_chain_t out;
186 ngx_http_request_t *r;
187
188 r = p->request;
189
190 r->headers_out.status = p->status;
191
192 #if 0
193 r->headers_out.content_length_n = -1;
194 r->headers_out.content_length = NULL;
195 #endif
196
197 /* copy an cached header to r->headers_out */
198
199 if (ngx_http_proxy_copy_header(p, &p->cache->headers_in) == NGX_ERROR) {
200 return NGX_HTTP_INTERNAL_SERVER_ERROR;
201 }
202
203 /* we need to allocate all before the header would be sent */
204
205 if (!((h = ngx_calloc_hunk(r->pool)))) {
206 return NGX_HTTP_INTERNAL_SERVER_ERROR;
207 }
208
209 if (!((h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
210 return NGX_HTTP_INTERNAL_SERVER_ERROR;
211 }
212
213 rc = ngx_http_send_header(r);
214
215 /* NEEDED ??? */ p->header_sent = 1;
216
217 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
218 return rc;
219 }
220
221 /* TODO: part in p->header_in */
222
223 h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
224
225 h->file_pos = p->header_in->pos - p->header_in->start;
226 h->file_last = h->file_pos + p->cache->ctx.header.length;
227
228 h->file->fd = p->cache->ctx.file.fd;
229 h->file->log = r->connection->log;
230
231 out.hunk = h;
232 out.next = NULL;
233
234 return ngx_http_output_filter(r, &out);
235 }