The R Project SVN R

Rev

Rev 51562 | Rev 51653 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 51562 Rev 51563
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