Mercurial > urweb
comparison src/c/fastcgi.c @ 861:bd153951c794
Fix env-reading bug in fastcgi; a bunch of non-AJAXy demos working
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 27 Jun 2009 15:36:56 -0400 |
parents | a738002d5b4d |
children | 66dbf3953758 |
comparison
equal
deleted
inserted
replaced
860:a738002d5b4d | 861:bd153951c794 |
---|---|
68 unsigned short contentLength) { | 68 unsigned short contentLength) { |
69 o->r.type = type; | 69 o->r.type = type; |
70 o->r.requestIdB1 = o->r.requestIdB0 = 0; | 70 o->r.requestIdB1 = o->r.requestIdB0 = 0; |
71 o->r.contentLengthB1 = contentLength >> 8; | 71 o->r.contentLengthB1 = contentLength >> 8; |
72 o->r.contentLengthB0 = contentLength & 255; | 72 o->r.contentLengthB0 = contentLength & 255; |
73 return uw_really_send(o->sock, &o->r, sizeof(o->r) - (65535 - contentLength)); | 73 return uw_really_send(o->sock, &o->r, sizeof(o->r) - 65535 + contentLength); |
74 } | 74 } |
75 | 75 |
76 #define LATEST(i) ((FCGI_Record *)(i->buf + i->used)) | 76 #define LATEST(i) ((FCGI_Record *)(i->buf + i->used)) |
77 | 77 |
78 static FCGI_Record *fastcgi_recv(FCGI_Input *i) { | 78 static FCGI_Record *fastcgi_recv(FCGI_Input *i) { |
164 } | 164 } |
165 | 165 |
166 static void log_debug(void *data, const char *fmt, ...) { | 166 static void log_debug(void *data, const char *fmt, ...) { |
167 } | 167 } |
168 | 168 |
169 typedef struct { | |
170 char *name, *value; | |
171 unsigned name_len, value_len; | |
172 } nvp; | |
173 | |
174 static char *search_nvps(nvp *nvps, const char *h) { | |
175 for (; nvps->name; ++nvps) | |
176 if (!strcmp(h, nvps->name)) | |
177 return nvps->value; | |
178 | |
179 return NULL; | |
180 } | |
181 | |
182 typedef struct { | |
183 nvp *nvps; | |
184 char *uppercased; | |
185 int n_nvps, uppercased_len; | |
186 } headers; | |
187 | |
188 static char *get_header(void *data, const char *h) { | |
189 headers *hs = (headers *)data; | |
190 size_t len = strlen(h); | |
191 char *s, *r; | |
192 const char *saved_h = h; | |
193 | |
194 if (len > hs->uppercased_len) { | |
195 hs->uppercased_len = len; | |
196 hs->uppercased = realloc(hs->uppercased, len + 6); | |
197 } | |
198 | |
199 strcpy(hs->uppercased, "HTTP_"); | |
200 for (s = hs->uppercased+5; *h; ++h) | |
201 *s++ = *h == '-' ? '_' : toupper(*h); | |
202 *s = 0; | |
203 | |
204 if (!strcasecmp(saved_h, "Content-length") | |
205 || !strcasecmp(saved_h, "Content-type")) | |
206 return search_nvps(hs->nvps, hs->uppercased + 5); | |
207 else | |
208 return search_nvps(hs->nvps, hs->uppercased); | |
209 } | |
210 | |
169 static int read_funny_len(char **buf, int *len) { | 211 static int read_funny_len(char **buf, int *len) { |
170 if (*len <= 0) | 212 if (*len <= 0) |
171 return -1; | 213 return -1; |
172 | 214 |
173 if ((*buf)[0] >> 7 == 0) { | 215 if ((*buf)[0] >> 7 == 0) { |
184 *len -= 4; | 226 *len -= 4; |
185 return r; | 227 return r; |
186 } | 228 } |
187 } | 229 } |
188 | 230 |
189 typedef struct { | |
190 char *name, *value; | |
191 unsigned name_len, value_len; | |
192 } nvp; | |
193 | |
194 static char *search_nvps(nvp *nvps, const char *h) { | |
195 for (; nvps->name; ++nvps) | |
196 if (!strcmp(h, nvps->name)) | |
197 return nvps->value; | |
198 | |
199 return NULL; | |
200 } | |
201 | |
202 typedef struct { | |
203 nvp *nvps; | |
204 char *uppercased; | |
205 int n_nvps, uppercased_len; | |
206 } headers; | |
207 | |
208 static char *get_header(void *data, const char *h) { | |
209 headers *hs = (headers *)data; | |
210 size_t len = strlen(h); | |
211 char *s, *r; | |
212 const char *saved_h = h; | |
213 | |
214 if (len > hs->uppercased_len) { | |
215 hs->uppercased_len = len; | |
216 hs->uppercased = realloc(hs->uppercased, len + 6); | |
217 } | |
218 | |
219 strcpy(hs->uppercased, "HTTP_"); | |
220 for (s = hs->uppercased+5; *h; ++h) | |
221 *s++ = *h == '-' ? '_' : toupper(*h); | |
222 *s = 0; | |
223 | |
224 if (!strcasecmp(saved_h, "Content-length") | |
225 || !strcasecmp(saved_h, "Content-type")) | |
226 return search_nvps(hs->nvps, hs->uppercased + 5); | |
227 else | |
228 return search_nvps(hs->nvps, hs->uppercased); | |
229 } | |
230 | |
231 static int read_nvp(char *buf, int len, nvp *nv) { | 231 static int read_nvp(char *buf, int len, nvp *nv) { |
232 int nameLength, valueLength; | 232 int nameLength, valueLength; |
233 | 233 |
234 if ((nameLength = read_funny_len(&buf, &len)) < 0) | 234 if ((nameLength = read_funny_len(&buf, &len)) < 0) |
235 return -1; | 235 return -1; |
236 if ((valueLength = read_funny_len(&buf, &len)) < 0) | 236 if ((valueLength = read_funny_len(&buf, &len)) < 0) |
237 return -1; | 237 return -1; |
238 if (len < nameLength + valueLength) | 238 if (len < nameLength + valueLength) |
239 return -1; | 239 return -1; |
240 | 240 |
241 if (nameLength+1 > nv->name_len) { | 241 if (!nv->name || nameLength+1 > nv->name_len) { |
242 nv->name_len = nameLength+1; | 242 nv->name_len = nameLength+1; |
243 nv->name = realloc(nv->name, nv->name_len); | 243 nv->name = nv->name ? realloc(nv->name, nv->name_len) : malloc(nv->name_len); |
244 } | 244 } |
245 if (valueLength+1 > nv->value_len) { | 245 if (!nv->value || valueLength+1 > nv->value_len) { |
246 nv->value_len = valueLength+1; | 246 nv->value_len = valueLength+1; |
247 nv->value = realloc(nv->value, nv->value_len); | 247 nv->value = nv->value ? realloc(nv->value, nv->value_len) : malloc(nv->value_len); |
248 } | 248 } |
249 | 249 |
250 memcpy(nv->name, buf, nameLength); | 250 memcpy(nv->name, buf, nameLength); |
251 nv->name[nameLength] = 0; | 251 nv->name[nameLength] = 0; |
252 | 252 |
265 headers hs; | 265 headers hs; |
266 size_t body_size = 0; | 266 size_t body_size = 0; |
267 char *body = malloc(0); | 267 char *body = malloc(0); |
268 size_t path_size = 0; | 268 size_t path_size = 0; |
269 char *path_buf = malloc(0); | 269 char *path_buf = malloc(0); |
270 int tries = 0; | |
270 | 271 |
271 hs.uppercased = malloc(0); | 272 hs.uppercased = malloc(0); |
272 hs.uppercased_len = 0; | 273 hs.uppercased_len = 0; |
273 hs.nvps = malloc(sizeof(nvp)); | 274 hs.nvps = malloc(sizeof(nvp)); |
274 hs.n_nvps = 1; | 275 hs.n_nvps = 1; |
284 | 285 |
285 if (!(r = fastcgi_recv(in))) { | 286 if (!(r = fastcgi_recv(in))) { |
286 fprintf(stderr, "Error receiving initial message\n"); | 287 fprintf(stderr, "Error receiving initial message\n"); |
287 goto done; | 288 goto done; |
288 } | 289 } |
289 | 290 |
290 if (r->type != FCGI_BEGIN_REQUEST) { | 291 if (r->type != FCGI_BEGIN_REQUEST) { |
291 write_stderr(out, "First message is not BEGIN_REQUEST\n"); | 292 write_stderr(out, "First message is not BEGIN_REQUEST\n"); |
292 goto done; | 293 goto done; |
293 } else if (((FCGI_BeginRequestBody *)&r->contentData)->roleB0 != FCGI_RESPONDER) { | 294 } else if (((FCGI_BeginRequestBody *)&r->contentData)->roleB0 != FCGI_RESPONDER) { |
294 write_stderr(out, "First message is not BEGIN_REQUEST\n"); | 295 write_stderr(out, "First message is not BEGIN_REQUEST\n"); |
337 goto done; | 338 goto done; |
338 } | 339 } |
339 } else | 340 } else |
340 body_len = 0; | 341 body_len = 0; |
341 | 342 |
342 if (body_len > body_size) { | 343 if (body_len+1 > body_size) { |
343 body_size = body_len; | 344 body_size = body_len+1; |
344 body = realloc(body, body_size); | 345 body = realloc(body, body_size); |
345 } | 346 } |
346 | 347 |
347 for (body_read = 0; body_read < body_len; ) { | 348 for (body_read = 0; body_read < body_len; ) { |
348 char *buf; | 349 char *buf; |
372 | 373 |
373 memcpy(&body[body_read], r->contentData, this_len); | 374 memcpy(&body[body_read], r->contentData, this_len); |
374 body_read += this_len; | 375 body_read += this_len; |
375 } | 376 } |
376 | 377 |
378 body[body_read] = 0; | |
379 | |
377 if (!(method = search_nvps(hs.nvps, "REQUEST_METHOD"))) { | 380 if (!(method = search_nvps(hs.nvps, "REQUEST_METHOD"))) { |
378 write_stderr(out, "REQUEST_METHOD not set\n"); | 381 write_stderr(out, "REQUEST_METHOD not set\n"); |
379 goto done; | 382 goto done; |
380 } | 383 } |
381 | 384 |
382 if (!(path = search_nvps(hs.nvps, "SCRIPT_NAME"))) { | 385 if (!(path = search_nvps(hs.nvps, "SCRIPT_NAME"))) { |
383 write_stderr(out, "SCRIPT_NAME not set\n"); | 386 write_stderr(out, "SCRIPT_NAME not set\n"); |
384 goto done; | 387 goto done; |
385 } | 388 } |
386 | 389 |
387 if (path_info = search_nvps(hs.nvps, "PATH_INFO")) { | 390 if (path_info = search_nvps(hs.nvps, "PATH_INFO")) { |
388 int len1 = strlen(path), len2 = strlen(path_info); | 391 int len1 = strlen(path), len2 = strlen(path_info); |
389 int len = len1 + len2 + 1; | 392 int len = len1 + len2 + 1; |
390 | 393 |
391 if (len > path_size) { | 394 if (len > path_size) { |
399 | 402 |
400 if (!(query_string = search_nvps(hs.nvps, "QUERY_STRING"))) | 403 if (!(query_string = search_nvps(hs.nvps, "QUERY_STRING"))) |
401 query_string = ""; | 404 query_string = ""; |
402 | 405 |
403 uw_set_headers(ctx, get_header, &hs); | 406 uw_set_headers(ctx, get_header, &hs); |
407 | |
404 { | 408 { |
405 request_result rr; | 409 request_result rr; |
406 FCGI_EndRequestBody *erb = (FCGI_EndRequestBody *)out->r.contentData; | 410 FCGI_EndRequestBody *erb = (FCGI_EndRequestBody *)out->r.contentData; |
407 | 411 |
408 rr = uw_request(rc, ctx, method, path, query_string, body, body_read, | 412 rr = uw_request(rc, ctx, method, path, query_string, body, body_read, |