Mercurial > hg > nginx
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 } |