[master] 3e86cd8 Make it possible to log arbitrary headers in varnishncsa

Tollef Fog Heen tfheen at varnish-cache.org
Fri Jul 15 10:57:21 CEST 2011


commit 3e86cd8d1e160613c1bcd5def787f4ba8196a9e3
Author: Tollef Fog Heen <tfheen at varnish-software.com>
Date:   Fri Jul 15 10:57:16 2011 +0200

    Make it possible to log arbitrary headers in varnishncsa

diff --git a/bin/varnishncsa/varnishncsa.c b/bin/varnishncsa/varnishncsa.c
index 9178168..94c81ef 100644
--- a/bin/varnishncsa/varnishncsa.c
+++ b/bin/varnishncsa/varnishncsa.c
@@ -54,8 +54,7 @@
  *	%q		Query string
  *	%H		Protocol version
  *
- * TODO:	- Make it possible to grab any request header
- *		- Maybe rotate/compress log
+ * TODO:		- Maybe rotate/compress log
  */
 
 #include "config.h"
@@ -72,6 +71,7 @@
 
 #include "vsb.h"
 #include "vpf.h"
+#include "vqueue.h"
 
 #include "libvarnish.h"
 #include "vsl.h"
@@ -81,14 +81,16 @@
 
 static volatile sig_atomic_t reopen;
 
+struct hdr {
+	char *key;
+	char *value;
+	VTAILQ_ENTRY(hdr) list;
+};
+
 static struct logline {
 	char *df_H;			/* %H, Protocol version */
-	char *df_Host;			/* %{Host}i */
-	char *df_Referer;		/* %{Referer}i */
 	char *df_U;			/* %U, URL path */
 	char *df_q;			/* %q, query string */
-	char *df_User_agent;		/* %{User-agent}i */
-	char *df_X_Forwarded_For;	/* %{X-Forwarded-For}i */
 	char *df_b;			/* %b, Bytes */
 	char *df_h;			/* %h (host name / IP adress)*/
 	char *df_m;			/* %m, Request method*/
@@ -101,6 +103,7 @@ static struct logline {
 	int active;			/* Is log line in an active trans */
 	int complete;			/* Is log line complete */
 	uint64_t bitmap;		/* Bitmap for regex matches */
+	VTAILQ_HEAD(, hdr) headers;
 } **ll;
 
 struct VSM_data *vd;
@@ -186,23 +189,39 @@ trimline(const char *str, const char *end)
 	return (p);
 }
 
+static char *
+get_header(struct logline *l, const char *name)
+{
+	struct hdr *h;
+	VTAILQ_FOREACH(h, &l->headers, list) {
+		if (strcasecmp(h->key, name) == 0) {
+			return h->value;
+			break;
+		}
+	}
+	return NULL;
+}
+
 static void
 clean_logline(struct logline *lp)
 {
+	struct hdr *h, *h2;
 #define freez(x) do { if (x) free(x); x = NULL; } while (0);
 	freez(lp->df_H);
-	freez(lp->df_Host);
-	freez(lp->df_Referer);
 	freez(lp->df_U);
 	freez(lp->df_q);
-	freez(lp->df_User_agent);
-	freez(lp->df_X_Forwarded_For);
 	freez(lp->df_b);
 	freez(lp->df_h);
 	freez(lp->df_m);
 	freez(lp->df_s);
 	freez(lp->df_u);
 	freez(lp->df_ttfb);
+	VTAILQ_FOREACH_SAFE(h, &lp->headers, list, h2) {
+		VTAILQ_REMOVE(&lp->headers, h, list);
+		freez(h->key);
+		freez(h->value);
+		freez(h);
+	}
 #undef freez
 	memset(lp, 0, sizeof *lp);
 }
@@ -293,17 +312,22 @@ collect_backend(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 	case SLT_TxHeader:
 		if (!lp->active)
 			break;
-		if (isprefix(ptr, "user-agent:", end, &next))
-			lp->df_User_agent = trimline(next, end);
-		else if (isprefix(ptr, "referer:", end, &next))
-			lp->df_Referer = trimline(next, end);
-		else if (isprefix(ptr, "authorization:", end, &next) &&
-		    isprefix(next, "basic", end, &next))
+		if (isprefix(ptr, "authorization:", end, &next) &&
+		    isprefix(next, "basic", end, &next)) {
 			lp->df_u = trimline(next, end);
-		else if (isprefix(ptr, "x-forwarded-for:", end, &next))
-			lp->df_X_Forwarded_For = trimline(next, end);
-		else if (isprefix(ptr, "host:", end, &next))
-			lp->df_Host = trimline(next, end);
+		} else {
+			struct hdr *h;
+			const char *split;
+			size_t l;
+			h = malloc(sizeof(struct hdr));
+			AN(h);
+			split = strchr(ptr, ':');
+			AN(split);
+			l = strlen(split);
+			h->key = trimline(ptr, split-1);
+			h->value = trimline(split+1, split+l-1);
+			VTAILQ_INSERT_HEAD(&lp->headers, h, list);
+		}
 		break;
 
 	case SLT_BackendReuse:
@@ -394,22 +418,20 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 	case SLT_RxHeader:
 		if (!lp->active)
 			break;
-		if (isprefix(ptr, "user-agent:", end, &next)) {
-			free(lp->df_User_agent);
-			lp->df_User_agent = trimline(next, end);
-		} else if (isprefix(ptr, "referer:", end, &next)) {
-			free(lp->df_Referer);
-			lp->df_Referer = trimline(next, end);
-		} else if (isprefix(ptr, "authorization:", end, &next) &&
-			   isprefix(next, "basic", end, &next)) {
+		if (isprefix(ptr, "authorization:", end, &next) &&
+		    isprefix(next, "basic", end, &next)) {
 			free(lp->df_u);
 			lp->df_u = trimline(next, end);
-		} else if (isprefix(ptr, "x-forwarded-for:", end, &next)) {
-			free(lp->df_X_Forwarded_For);
-			lp->df_X_Forwarded_For = trimline(next, end);
-		} else if (isprefix(ptr, "host:", end, &next)) {
-			free(lp->df_Host);
-			lp->df_Host = trimline(next, end);
+		} else {
+			struct hdr *h;
+			const char *split;
+			h = malloc(sizeof(struct hdr));
+			AN(h);
+			split = strchr(ptr, ':');
+			AN(split);
+			h->key = trimline(ptr, split);
+			h->value = trimline(split+1, end);
+			VTAILQ_INSERT_HEAD(&lp->headers, h, list);
 		}
 		break;
 
@@ -579,10 +601,10 @@ h_ncsa(void *priv, enum VSL_tag_e tag, unsigned fd,
 			 */
 			VSB_cat(os, lp->df_m);
 			VSB_putc(os, ' ');
-			if (lp->df_Host) {
-				if (strncmp(lp->df_Host, "http://", 7) != 0)
+			if (get_header(lp, "Host")) {
+				if (strncmp(get_header(lp, "Host"), "http://", 7) != 0)
 					VSB_cat(os, "http://");
-				VSB_cat(os, lp->df_Host);
+				VSB_cat(os, get_header(lp, "Host"));
 			}
 			VSB_cat(os, lp->df_U);
 			VSB_cat(os, lp->df_q ? lp->df_q : "");
@@ -626,42 +648,44 @@ h_ncsa(void *priv, enum VSL_tag_e tag, unsigned fd,
 			}
 			break;
 
-		case '{':
-			if (strncmp(p, "{Referer}i", 10) == 0) {
-				VSB_cat(os, lp->df_Referer ? lp->df_Referer : "-");
-				p += 9;
-				break;
-			} else if (strncmp(p, "{Host}i", 7) == 0) {
-				VSB_cat(os, lp->df_Host ? lp->df_Host : "-");
-				p += 6;
-				break;
-			} else if (strncmp(p, "{X-Forwarded-For}i", 18) == 0) {
-				/* %{Referer}i */
-				VSB_cat(os, lp->df_X_Forwarded_For ? lp->df_X_Forwarded_For : "-");
-				p += 17;
-				break;
-			} else if (strncmp(p, "{User-agent}i", 13) == 0) {
-				/* %{User-agent}i */
-				VSB_cat(os, lp->df_User_agent ? lp->df_User_agent : "-");
-				p += 12;
+		case '{': {
+			const char *h, *tmp;
+			char fname[100], type;
+			tmp = p;
+			type = 0;
+			while (*tmp != '\0' && *tmp != '}')
+				tmp++;
+			if (*tmp == '}') {
+				tmp++;
+				type = *tmp;
+				memcpy(fname, p+1, tmp-p-2);
+			}
+
+			switch (type) {
+			case 'i':
+				h = get_header(lp, fname);
+				VSB_cat(os, h ? h : "-");
+				p = tmp;
 				break;
-			} else if (strncmp(p, "{Varnish:", 9) == 0) {
-				/* Scan for what we're looking for */
-				const char *what = p+9;
-				if (strncmp(what, "time_firstbyte}x", 16) == 0) {
+			case 'x':
+				if (strcmp(fname, "Varnish:time_firstbyte") == 0) {
 					VSB_cat(os, lp->df_ttfb);
-					p += 9+15;
-					break;
-				} else if (strncmp(what, "hitmiss}x", 9) == 0) {
+					p = tmp;
+				} else if (strcmp(fname, "Varnish:hitmiss") == 0) {
 					VSB_cat(os, (lp->df_hitmiss ? lp->df_hitmiss : "-"));
-					p += 9+8;
+					p = tmp;
 					break;
-				} else if (strncmp(what, "handling}x", 10) == 0) {
+				} else if (strcmp(fname, "handling") == 0) {
 					VSB_cat(os, (lp->df_handling ? lp->df_handling : "-"));
-					p += 9+9;
+					p = tmp;
 					break;
 				}
+			default:
+				fprintf(stderr, "Unknown format starting at: %s\n", --p);
+				exit(1);
 			}
+			break;
+		}
 			/* Fall through if we haven't handled something */
 			/* FALLTHROUGH*/
 		default:
diff --git a/doc/sphinx/reference/varnishncsa.rst b/doc/sphinx/reference/varnishncsa.rst
index 414e07e..48befed 100644
--- a/doc/sphinx/reference/varnishncsa.rst
+++ b/doc/sphinx/reference/varnishncsa.rst
@@ -68,8 +68,7 @@ The following options are available:
 	         Remote host
 
 	      %{X}i
-	         The contents of header line X.  Supported headers are
-	         *Referer*, *Host*, *X-Forwarded-For* and *User-agent*.
+	         The contents of header line X.
 
 	      %l
 	         Remote logname (always '-')



More information about the varnish-commit mailing list