r2353 - in trunk/varnish-cache: bin/varnishd include

phk at projects.linpro.no phk at projects.linpro.no
Wed Jan 16 16:15:39 CET 2008


Author: phk
Date: 2008-01-16 16:15:39 +0100 (Wed, 16 Jan 2008)
New Revision: 2353

Modified:
   trunk/varnish-cache/bin/varnishd/cache.h
   trunk/varnish-cache/bin/varnishd/cache_center.c
   trunk/varnish-cache/bin/varnishd/cache_fetch.c
   trunk/varnish-cache/bin/varnishd/mgt_vcc.c
   trunk/varnish-cache/include/http_headers.h
Log:
Rework the handling of message-bodies in requests to be closer to
RFC2616 and catch things we don't deal with better.

Move code to receive body from request into separate function,
FetchReqBody() so it can be invoked when center::STP_HIT.

Check read errors and make FetchReqBody() return an error code for
client/server side so we don't penalize backends for client trouble.

Make it a client error, for now, to send chunked encoding.

This also isolates the big stack buffer from the subsequent function
calls in Fetch() and will be saner if we ever add chunked-encoding
handling.

Only send the body to the backend on pass, otherwise discard it.

This is controlled via the sp->sendbody flag which is reset in at
STP_RECV and set it at STP_PASS.

In STP_HIT, on deliver, call FetchReqBody() to dispose of any body
the request might contain.

Filter Content-Length: headers out (c->b) on fetches, but not for pass.

Rewrite default vcl_recv{} to be take advantage of our new capabilities.

This should make PUT, DELETE, OPTIONS, and TRACE work as well as POST.



Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2008-01-16 14:53:48 UTC (rev 2352)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2008-01-16 15:15:39 UTC (rev 2353)
@@ -329,6 +329,7 @@
 	enum step		step;
 	unsigned		cur_method;
 	unsigned 		handling;
+	unsigned char		sendbody;
 	unsigned char		wantbody;
 	int			err_code;
 	const char		*err_reason;
@@ -469,6 +470,7 @@
 
 /* cache_fetch.c */
 int Fetch(struct sess *sp);
+int FetchReqBody(struct sess *sp);
 
 /* cache_hash.c */
 void HSH_Prealloc(struct sess *sp);

Modified: trunk/varnish-cache/bin/varnishd/cache_center.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_center.c	2008-01-16 14:53:48 UTC (rev 2352)
+++ trunk/varnish-cache/bin/varnishd/cache_center.c	2008-01-16 15:15:39 UTC (rev 2353)
@@ -451,6 +451,8 @@
 	VCL_hit_method(sp);
 
 	if (sp->handling == VCL_RET_DELIVER) {
+		/* Dispose of any body part of the request */
+		FetchReqBody(sp);
 		sp->step = STP_DELIVER;
 		return (0);
 	}
@@ -682,6 +684,7 @@
 	sp->obj = sp->wrk->nobj;
 	sp->wrk->nobj = NULL;
 	sp->obj->busy = 1;
+	sp->sendbody = 1;
 	sp->step = STP_FETCH;
 	return (0);
 }
@@ -760,6 +763,7 @@
 	VCL_recv_method(sp);
 
 	sp->wantbody = (strcmp(sp->http->hd[HTTP_HDR_REQ].b, "HEAD") != 0);
+	sp->sendbody = 0;
 	switch(sp->handling) {
 	case VCL_RET_LOOKUP:
 		/* XXX: discard req body, if any */

Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_fetch.c	2008-01-16 14:53:48 UTC (rev 2352)
+++ trunk/varnish-cache/bin/varnishd/cache_fetch.c	2008-01-16 15:15:39 UTC (rev 2353)
@@ -246,6 +246,49 @@
 	return (1);
 }
 
+/*--------------------------------------------------------------------
+ * Fetch any body attached to the incoming request, and either write it
+ * to the backend (if we pass) or discard it (anything else).
+ * This is mainly a separate function to isolate the stack buffer and
+ * to contain the complexity when we start handling chunked encoding.
+ */
+
+int
+FetchReqBody(struct sess *sp)
+{
+	unsigned long content_length;
+	char buf[8192];
+	char *ptr, *endp;
+	int read;
+
+	if (http_GetHdr(sp->http, H_Content_Length, &ptr)) {
+
+		content_length = strtoul(ptr, &endp, 10);
+		/* XXX should check result of conversion */
+		while (content_length) {
+			if (content_length > sizeof buf)
+				read = sizeof buf;
+			else
+				read = content_length;
+			read = HTC_Read(sp->htc, buf, read);
+			if (read < 0)
+				return (1);
+			content_length -= read;
+			if (!sp->sendbody)
+				continue;
+			WRK_Write(sp->wrk, buf, read);
+			if (WRK_Flush(sp->wrk))
+				return (2);
+		}
+	}
+	if (http_GetHdr(sp->http, H_Transfer_Encoding, NULL)) {
+		/* XXX: Handle chunked encoding. */
+		WSL(sp->wrk, SLT_Debug, sp->fd, "Transfer-Encoding in request");
+		return (1);
+	}
+	return (0);
+}
+
 /*--------------------------------------------------------------------*/
 
 int
@@ -261,7 +304,6 @@
 	int mklen, is_head;
 	struct http_conn htc[1];
 	int i;
-	char *ptr, *endp;
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
@@ -289,31 +331,13 @@
 	WRK_Reset(w, &vc->fd);
 	http_Write(w, hp, 0);
 
-	/*
-	 * If a POST request was passed to fetch, we must send any
-	 * pipelined bytes to the backend as well
-	 */
-	if (http_GetHdr(sp->http, H_Content_Length, &ptr)) {
-		unsigned long content_length;
-		char buf[8192];
-		int read;
-
-		content_length = strtoul(ptr, &endp, 10);
-		/* XXX should check result of conversion */
-		while (content_length) {
-			if (content_length > sizeof buf)
-				read = sizeof buf;
-			else
-				read = content_length;
-			read = HTC_Read(sp->htc, buf, read);
-			WRK_Write(w, buf, read);
-			if (WRK_Flush(w)) {
-				VBE_UpdateHealth(sp, vc, -1);
-				VBE_ClosedFd(sp->wrk, vc);
-				return (__LINE__);
-			}
-			content_length -= read;
-		}
+	/* Deal with any message-body the request might have */
+	i = FetchReqBody(sp);
+	if (i > 0) {
+		if (i > 1)
+			VBE_UpdateHealth(sp, vc, -1);
+		VBE_ClosedFd(sp->wrk, vc);
+		return (__LINE__);
 	}
 
 	if (WRK_Flush(w)) {

Modified: trunk/varnish-cache/bin/varnishd/mgt_vcc.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_vcc.c	2008-01-16 14:53:48 UTC (rev 2352)
+++ trunk/varnish-cache/bin/varnishd/mgt_vcc.c	2008-01-16 15:15:39 UTC (rev 2353)
@@ -77,13 +77,26 @@
  */
 static const char *default_vcl =
     "sub vcl_recv {\n"
-    "    if (req.request != \"GET\" && req.request != \"HEAD\") {\n"
+    "    if (req.request != \"GET\" &&\n"
+    "      req.request != \"HEAD\" &&\n"
+    "      req.request != \"PUT\" &&\n"
+    "      req.request != \"POST\" &&\n"
+    "      req.request != \"TRACE\" &&\n"
+    "      req.request != \"OPTIONS\" &&\n"
+    "      req.request != \"DELETE\") {\n"
+    "        /* Non-RFC2616 or CONNECT which is weird. */\n"
     "        pipe;\n"
     "    }\n"
     "    if (req.http.Expect) {\n"
+    "        /* Expect is just too hard at present. */\n"
     "        pipe;\n"
     "    }\n"
+    "    if (req.request != \"GET\" && req.request != \"HEAD\") {\n"
+    "        /* We only deal with GET and HEAD by default */\n"
+    "        pass;\n"
+    "    }\n"
     "    if (req.http.Authenticate || req.http.Cookie) {\n"
+    "        /* Not cacheable by default */\n"
     "        pass;\n"
     "    }\n"
     "    lookup;\n"

Modified: trunk/varnish-cache/include/http_headers.h
===================================================================
--- trunk/varnish-cache/include/http_headers.h	2008-01-16 14:53:48 UTC (rev 2352)
+++ trunk/varnish-cache/include/http_headers.h	2008-01-16 15:15:39 UTC (rev 2353)
@@ -65,7 +65,7 @@
 HTTPH("Connection",		H_Connection,		3, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0)	/* RFC2616 14.10 */
 HTTPH("Content-Encoding",	H_Content_Encoding,	2, 0, 0, 0, 0)	/* RFC2616 14.11 */
 HTTPH("Content-Langugae",	H_Content_Language,	2, 0, 0, 0, 0)	/* RFC2616 14.12 */
-HTTPH("Content-Length",		H_Content_Length,	2, 2, HTTPH_A_INS, 0, 0)	/* RFC2616 14.13 */
+HTTPH("Content-Length",		H_Content_Length,	2, 2, HTTPH_R_FETCH|HTTPH_A_INS, 0, 0)	/* RFC2616 14.13 */
 HTTPH("Content-Location",	H_Content_Location,	2, 0, 0, 0, 0)  /* RFC2616 14.14 */
 HTTPH("Content-MD5",		H_Content_MD5,		2, 0, 0, 0, 0)  /* RFC2616 14.15 */
 HTTPH("Content-Range",		H_Content_Range,	2, 3, HTTPH_R_PASS|HTTPH_A_PASS|HTTPH_R_FETCH|HTTPH_A_INS, 0, 0)  /* RFC2616 14.16 */




More information about the varnish-commit mailing list