| Line 440... |
Line 440... |
| 440 |
static void fin_request(httpd_conn_t *c) {
|
440 |
static void fin_request(httpd_conn_t *c) {
|
| 441 |
if (!IS_HTTP_1_1(c))
|
441 |
if (!IS_HTTP_1_1(c))
|
| 442 |
c->attr |= CONNECTION_CLOSE;
|
442 |
c->attr |= CONNECTION_CLOSE;
|
| 443 |
}
|
443 |
}
|
| 444 |
|
444 |
|
| - |
|
445 |
static SEXP custom_handlers_env;
|
| - |
|
446 |
|
| - |
|
447 |
/* returns a httpd handler (closure) for a given path. As a special case
|
| - |
|
448 |
* it can return a symbol that will be resolved in the "tools" namespace.
|
| - |
|
449 |
* currently it allows custom handlers for paths of the form
|
| - |
|
450 |
* /custom/<name>[/.*] where <name> must less than 64 characters long
|
| - |
|
451 |
* and is matched against closures in tools:::.httpd.handlers.env */
|
| - |
|
452 |
static SEXP handler_for_path(const char *path) {
|
| - |
|
453 |
if (path && !strncmp(path, "/custom/", 8)) { /* starts with /custom/ ? */
|
| - |
|
454 |
const char *c = path + 8, *e = c;
|
| - |
|
455 |
while (*c && *c != '/') c++; /* find out the name */
|
| - |
|
456 |
if (c - e > 0 && c - e < 64) { /* if it's 1..63 chars long, proceed */
|
| - |
|
457 |
char fn[64];
|
| - |
|
458 |
memcpy(fn, e, c - e); /* create a local C string with the name for the install() call */
|
| - |
|
459 |
fn[c - e] = 0;
|
| - |
|
460 |
DBG(Rprintf("handler_for_path('%s'): looking up custom handler '%s'\n", path, fn));
|
| - |
|
461 |
/* we cache custom_handlers_env so in case it has not been loaded yet, fetch it */
|
| - |
|
462 |
if (!custom_handlers_env)
|
| - |
|
463 |
custom_handlers_env = eval(install(".httpd.handlers.env"), R_FindNamespace(mkString("tools")));
|
| - |
|
464 |
/* we only proceed if .httpd.handlers.env really exists */
|
| - |
|
465 |
if (TYPEOF(custom_handlers_env) == ENVSXP) {
|
| - |
|
466 |
SEXP cl = findVarInFrame3(custom_handlers_env, install(fn), TRUE);
|
| - |
|
467 |
if (cl != R_UnboundValue && TYPEOF(cl) == CLOSXP) /* we need a closure */
|
| - |
|
468 |
return cl;
|
| - |
|
469 |
}
|
| - |
|
470 |
}
|
| - |
|
471 |
}
|
| - |
|
472 |
DBG(Rprintf(" - falling back to default httpd\n"));
|
| - |
|
473 |
return install("httpd");
|
| - |
|
474 |
}
|
| - |
|
475 |
|
| 445 |
/* process a request by calling the httpd() function in R */
|
476 |
/* process a request by calling the httpd() function in R */
|
| 446 |
static void process_request(httpd_conn_t *c)
|
477 |
static void process_request(httpd_conn_t *c)
|
| 447 |
{
|
478 |
{
|
| 448 |
const char *ct = "text/html";
|
479 |
const char *ct = "text/html";
|
| 449 |
char *query = 0, *s;
|
480 |
char *query = 0, *s;
|
| Line 460... |
Line 491... |
| 460 |
uri_decode(c->url); /* decode the path part */
|
491 |
uri_decode(c->url); /* decode the path part */
|
| 461 |
{ /* construct "try(httpd(url, query, body), silent=TRUE)" */
|
492 |
{ /* construct "try(httpd(url, query, body), silent=TRUE)" */
|
| 462 |
SEXP sTrue = PROTECT(ScalarLogical(TRUE));
|
493 |
SEXP sTrue = PROTECT(ScalarLogical(TRUE));
|
| 463 |
SEXP y, x = PROTECT(lang3(
|
494 |
SEXP y, x = PROTECT(lang3(
|
| 464 |
install("try"),
|
495 |
install("try"),
|
| 465 |
LCONS(install("httpd"),
|
496 |
LCONS(handler_for_path(c->url),
|
| 466 |
list3(mkString(c->url), query ? parse_query(query) : R_NilValue, parse_request_body(c))),
|
497 |
list3(mkString(c->url), query ? parse_query(query) : R_NilValue, parse_request_body(c))),
|
| 467 |
sTrue));
|
498 |
sTrue));
|
| 468 |
SET_TAG(CDR(CDR(x)), install("silent"));
|
499 |
SET_TAG(CDR(CDR(x)), install("silent"));
|
| 469 |
DBG(Rprintf("eval(try(httpd('%s'),silent=TRUE))\n", c->url));
|
500 |
DBG(Rprintf("eval(try(httpd('%s'),silent=TRUE))\n", c->url));
|
| 470 |
|
501 |
|