The R Project SVN R

Rev

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

Rev 49788 Rev 49887
Line 177... Line 177...
177
    char *url, *body;              /* URL and request body */
177
    char *url, *body;              /* URL and request body */
178
    unsigned int line_pos, body_pos, content_length; /* positions in the buffers and desired content length */
178
    unsigned int line_pos, body_pos, content_length; /* positions in the buffers and desired content length */
179
    char part, method, attr;       /* request part, method and connection attributes */
179
    char part, method, attr;       /* request part, method and connection attributes */
180
} httpd_conn_t;
180
} httpd_conn_t;
181
 
181
 
-
 
182
/* returns the HTTP/x.x string for a given connection - we support 1.0 and 1.1 only */
-
 
183
#define HTTP_SIG(C) ((((C)->attr & HTTP_1_0) == 0) ? "HTTP/1.1" : "HTTP/1.0")
-
 
184
 
-
 
185
#define IS_HTTP_1_1(C) (((C)->attr & HTTP_1_0) == 0)
-
 
186
 
182
/* --- static list of currently activbe workers --- */
187
/* --- static list of currently activbe workers --- */
183
static httpd_conn_t *workers[MAX_WORKERS];
188
static httpd_conn_t *workers[MAX_WORKERS];
184
 
189
 
185
/* --- flag determining whether one-time initialization is yet to be performed --- */
190
/* --- flag determining whether one-time initialization is yet to be performed --- */
186
static int needs_init = 1;
191
static int needs_init = 1;
Line 291... Line 296...
291
	i += n;
296
	i += n;
292
    }
297
    }
293
    return 0;
298
    return 0;
294
}
299
}
295
 
300
 
-
 
301
/* sends HTTP/x.x plus the text (which should be of the form " XXX ...") */
-
 
302
static int send_http_response(httpd_conn_t *c, const char *text) {
-
 
303
    const char *s = HTTP_SIG(c);
-
 
304
    if (send(c->sock, s, 8, 0) < 8) return -1;
-
 
305
    return send_response(c->sock, text, strlen(text));
-
 
306
}
-
 
307
 
296
/* decode URI in place (decoding never expands) */
308
/* decode URI in place (decoding never expands) */
297
static void uri_decode(char *s)
309
static void uri_decode(char *s)
298
{
310
{
299
    char *t = s;
311
    char *t = s;
300
    while (*s) {
312
    while (*s) {
Line 385... Line 397...
385
    DBG(Rprintf("process_request_main_thread returned\n"));
397
    DBG(Rprintf("process_request_main_thread returned\n"));
386
}
398
}
387
#define process_request process_request_main_thread
399
#define process_request process_request_main_thread
388
#endif
400
#endif
389
 
401
 
-
 
402
/* finalize a request - essentially for HTTP/1.0 it means that
-
 
403
 * we have to close the connection */
-
 
404
static void fin_request(httpd_conn_t *c) {
-
 
405
    if (!IS_HTTP_1_1(c))
-
 
406
	c->attr |= CONNECTION_CLOSE;
-
 
407
}
-
 
408
 
390
/* process a request by calling the httpd() function in R */
409
/* process a request by calling the httpd() function in R */
391
static void process_request(httpd_conn_t *c)
410
static void process_request(httpd_conn_t *c)
392
{
411
{
393
    const char *ct = "text/html";
412
    const char *ct = "text/html";
394
    char *query = 0, *s;
413
    char *query = 0, *s;
Line 431... Line 450...
431
	     status code: must be an integer if present (default is 200)
450
	     status code: must be an integer if present (default is 200)
432
	 */
451
	 */
433
 
452
 
434
	if (TYPEOF(x) == STRSXP && LENGTH(x) > 0) { /* string means there was an error */
453
	if (TYPEOF(x) == STRSXP && LENGTH(x) > 0) { /* string means there was an error */
435
	    const char *s = CHAR(STRING_ELT(x, 0));
454
	    const char *s = CHAR(STRING_ELT(x, 0));
436
	    send_response(c->sock, "HTTP/1.1 500 Evaluation error\r\nConnection: close\r\nContent-type: text/plain\r\n\r\n", 78);
455
	    send_http_response(c, " 500 Evaluation error\r\nConnection: close\r\nContent-type: text/plain\r\n\r\n");
437
	    DBG(Rprintf("respond with 500 and content: %s\n", s));
456
	    DBG(Rprintf("respond with 500 and content: %s\n", s));
438
	    if (c->method != METHOD_HEAD)
457
	    if (c->method != METHOD_HEAD)
439
		send_response(c->sock, s, strlen(s));
458
		send_response(c->sock, s, strlen(s));
440
	    c->attr |= CONNECTION_CLOSE; /* force close */
459
	    c->attr |= CONNECTION_CLOSE; /* force close */
441
	    UNPROTECT(3);
460
	    UNPROTECT(3);
Line 459... Line 478...
459
	    y = VECTOR_ELT(x, 0);
478
	    y = VECTOR_ELT(x, 0);
460
	    if (TYPEOF(y) == STRSXP && LENGTH(y) > 0) {
479
	    if (TYPEOF(y) == STRSXP && LENGTH(y) > 0) {
461
		char buf[64];
480
		char buf[64];
462
		const char *cs = CHAR(STRING_ELT(y, 0)), *fn = 0;
481
		const char *cs = CHAR(STRING_ELT(y, 0)), *fn = 0;
463
		if (code == 200)
482
		if (code == 200)
464
		    send_response(c->sock, "HTTP/1.1 200 OK\r\nContent-type: ", 31);
483
		    send_http_response(c, " 200 OK\r\nContent-type: ");
465
		else {
484
		else {
466
		    sprintf(buf, "HTTP/1.1 %d Code %d\r\nContent-type: ", code, code);
485
		    sprintf(buf, "%s %d Code %d\r\nContent-type: ", HTTP_SIG(c), code, code);
467
		    send_response(c->sock, buf, strlen(buf));
486
		    send_response(c->sock, buf, strlen(buf));
468
		}
487
		}
469
		send_response(c->sock, ct, strlen(ct));
488
		send_response(c->sock, ct, strlen(ct));
470
		if (sHeaders != R_NilValue) {
489
		if (sHeaders != R_NilValue) {
471
		    unsigned int i = 0, n = LENGTH(sHeaders);
490
		    unsigned int i = 0, n = LENGTH(sHeaders);
Line 486... Line 505...
486
		    FILE *f = fopen(fn, "rb");
505
		    FILE *f = fopen(fn, "rb");
487
		    long fsz = 0;
506
		    long fsz = 0;
488
		    if (!f) {
507
		    if (!f) {
489
			send_response(c->sock, "\r\nContent-length: 0\r\n\r\n", 23);
508
			send_response(c->sock, "\r\nContent-length: 0\r\n\r\n", 23);
490
			UNPROTECT(3);
509
			UNPROTECT(3);
-
 
510
			fin_request(c);
491
			return;
511
			return;
492
		    }
512
		    }
493
		    fseek(f, 0, SEEK_END);
513
		    fseek(f, 0, SEEK_END);
494
		    fsz = ftell(f);
514
		    fsz = ftell(f);
495
		    fseek(f, 0, SEEK_SET);
515
		    fseek(f, 0, SEEK_SET);
Line 510... Line 530...
510
			}
530
			}
511
			free(fbuf);
531
			free(fbuf);
512
		    }
532
		    }
513
		    fclose(f);
533
		    fclose(f);
514
		    UNPROTECT(3);
534
		    UNPROTECT(3);
-
 
535
		    fin_request(c);
515
		    return;
536
		    return;
516
		}
537
		}
517
		sprintf(buf, "\r\nContent-length: %u\r\n\r\n", (unsigned int) strlen(cs));
538
		sprintf(buf, "\r\nContent-length: %u\r\n\r\n", (unsigned int) strlen(cs));
518
		send_response(c->sock, buf, strlen(buf));
539
		send_response(c->sock, buf, strlen(buf));
519
		if (c->method != METHOD_HEAD)
540
		if (c->method != METHOD_HEAD)
520
		    send_response(c->sock, cs, strlen(cs));
541
		    send_response(c->sock, cs, strlen(cs));
521
		UNPROTECT(3);
542
		UNPROTECT(3);
-
 
543
		fin_request(c);
522
		return;
544
		return;
523
	    }
545
	    }
524
	    if (TYPEOF(y) == RAWSXP) {
546
	    if (TYPEOF(y) == RAWSXP) {
525
		char buf[64];
547
		char buf[64];
526
		Rbyte *cs = RAW(y);
548
		Rbyte *cs = RAW(y);
527
		if (code == 200)
549
		if (code == 200)
528
		    send_response(c->sock, "HTTP/1.1 200 OK\r\nContent-type: ", 31);
550
		    send_http_response(c, " 200 OK\r\nContent-type: ");
529
		else {
551
		else {
530
		    sprintf(buf, "HTTP/1.1 %d Code %d\r\nContent-type: ", code, code);
552
		    sprintf(buf, "%s %d Code %d\r\nContent-type: ", HTTP_SIG(c), code, code);
531
		    send_response(c->sock, buf, strlen(buf));
553
		    send_response(c->sock, buf, strlen(buf));
532
		}
554
		}
533
		send_response(c->sock, ct, strlen(ct));
555
		send_response(c->sock, ct, strlen(ct));
534
		if (sHeaders != R_NilValue) {
556
		if (sHeaders != R_NilValue) {
535
		    unsigned int i = 0, n = LENGTH(sHeaders);
557
		    unsigned int i = 0, n = LENGTH(sHeaders);
Line 542... Line 564...
542
		sprintf(buf, "\r\nContent-length: %u\r\n\r\n", LENGTH(y));
564
		sprintf(buf, "\r\nContent-length: %u\r\n\r\n", LENGTH(y));
543
		send_response(c->sock, buf, strlen(buf));
565
		send_response(c->sock, buf, strlen(buf));
544
		if (c->method != METHOD_HEAD)
566
		if (c->method != METHOD_HEAD)
545
		    send_response(c->sock, (char*) cs, LENGTH(y));
567
		    send_response(c->sock, (char*) cs, LENGTH(y));
546
		UNPROTECT(3);
568
		UNPROTECT(3);
-
 
569
		fin_request(c);
547
		return;
570
		return;
548
	    }
571
	    }
549
	}
572
	}
550
	UNPROTECT(3);
573
	UNPROTECT(3);
551
    }
574
    }
552
    send_response(c->sock, "HTTP/1.1 500 Invalid response from R\r\nConnection: close\r\nContent-type: text/plain\r\n\r\nServer error: invalid response from R\r\n", 124);
575
    send_http_response(c, " 500 Invalid response from R\r\nConnection: close\r\nContent-type: text/plain\r\n\r\nServer error: invalid response from R\r\n");
553
    c->attr |= CONNECTION_CLOSE; /* force close */
576
    c->attr |= CONNECTION_CLOSE; /* force close */
554
}
577
}
555
 
578
 
556
#ifdef WIN32
579
#ifdef WIN32
557
#undef process_request
580
#undef process_request
Line 598... Line 621...
598
	    /* ok, we have genuine data in the line buffer */
621
	    /* ok, we have genuine data in the line buffer */
599
	    if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n')) { /* single, empty line - end of headers */
622
	    if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n')) { /* single, empty line - end of headers */
600
		/* --- check request validity --- */
623
		/* --- check request validity --- */
601
		DBG(printf(" end of request, moving to body\n"));
624
		DBG(printf(" end of request, moving to body\n"));
602
		if (!(c->attr & HTTP_1_0) && !(c->attr & HOST_HEADER)) { /* HTTP/1.1 mandates Host: header */
625
		if (!(c->attr & HTTP_1_0) && !(c->attr & HOST_HEADER)) { /* HTTP/1.1 mandates Host: header */
603
		    send(c->sock, "HTTP/1.1 400 Bad Request (Host: missing)\r\nConnection: close\r\n\r\n", 63, 0);
626
		    send_http_response(c, " 400 Bad Request (Host: missing)\r\nConnection: close\r\n\r\n");
604
		    remove_worker(c);
627
		    remove_worker(c);
605
		    return;
628
		    return;
606
 
629
 
607
		}
630
		}
608
		if (c->attr & CONTENT_LENGTH) {
631
		if (c->attr & CONTENT_LENGTH) {
Line 749... Line 772...
749
    /* we enter here only if recv was used to leave the headers with no body */
772
    /* we enter here only if recv was used to leave the headers with no body */
750
    if (c->part == PART_BODY && !c->body) {
773
    if (c->part == PART_BODY && !c->body) {
751
	char *s = c->line_buf;
774
	char *s = c->line_buf;
752
	if (c->line_pos > 0) {
775
	if (c->line_pos > 0) {
753
	    if ((s[0] != '\r' || s[1] != '\n') && (s[0] != '\n')) {
776
	    if ((s[0] != '\r' || s[1] != '\n') && (s[0] != '\n')) {
754
		send(c->sock, "HTTP/1.0 411 length is required for non-empty body\r\nConnection: close\r\n\r\n", 73, 0);
777
		send_http_response(c, " 411 length is required for non-empty body\r\nConnection: close\r\n\r\n");
755
		remove_worker(c);
778
		remove_worker(c);
756
		return;
779
		return;
757
	    }
780
	    }
758
	    /* empty body, good */
781
	    /* empty body, good */
759
	    process_request(c);
782
	    process_request(c);
Line 789... Line 812...
789
	    process_request(c);
812
	    process_request(c);
790
	    remove_worker(c);
813
	    remove_worker(c);
791
	    return;
814
	    return;
792
	}
815
	}
793
	if ((s[0] != '\r' || s[1] != '\n') && (s[0] != '\n')) {
816
	if ((s[0] != '\r' || s[1] != '\n') && (s[0] != '\n')) {
794
	    send(c->sock, "HTTP/1.0 411 length is required for non-empty body\r\nConnection: close\r\n\r\n", 73, 0);
817
	    send_http_response(c, " 411 length is required for non-empty body\r\nConnection: close\r\n\r\n");
795
	    remove_worker(c);
818
	    remove_worker(c);
796
	    return;
819
	    return;
797
	}
820
	}
798
    }
821
    }
799
}
822
}