[PATCH] Handle If-None-Match HTTP header in plain view

John Keeping john at keeping.me.uk
Mon Aug 11 23:32:05 CEST 2014


On Mon, Aug 11, 2014 at 05:53:23PM -0300, Damián Nohales wrote:
> We are sending Etag to clients but this header is basically unusefulness
> if the server doesn't tell the client if the content has been changed or
> not for a given Path/Etag pair.
> 
> Signed-off-by: Damián Nohales <damiannohales at gmail.com>
> ---

How does this interact with CGit's cache?  What happens if the original
page expires from the cache and then a request comes in with a matching
Etag?

>  cgit.c      |  1 +
>  cgit.h      |  1 +
>  ui-plain.c  | 41 +++++++++++++++++++++--------------------
>  ui-shared.c | 20 ++++++++++++++++++++
>  ui-shared.h |  1 +
>  5 files changed, 44 insertions(+), 20 deletions(-)
> 
> diff --git a/cgit.c b/cgit.c
> index 8c4517d..7af7712 100644
> --- a/cgit.c
> +++ b/cgit.c
> @@ -385,6 +385,7 @@ static void prepare_context(void)
>  	ctx.env.server_port = getenv("SERVER_PORT");
>  	ctx.env.http_cookie = getenv("HTTP_COOKIE");
>  	ctx.env.http_referer = getenv("HTTP_REFERER");
> +	ctx.env.if_none_match = getenv("HTTP_IF_NONE_MATCH");
>  	ctx.env.content_length = getenv("CONTENT_LENGTH") ? strtoul(getenv("CONTENT_LENGTH"), NULL, 10) : 0;
>  	ctx.env.authenticated = 0;
>  	ctx.page.mimetype = "text/html";
> diff --git a/cgit.h b/cgit.h
> index 0badc64..eddd4c7 100644
> --- a/cgit.h
> +++ b/cgit.h
> @@ -282,6 +282,7 @@ struct cgit_environment {
>  	const char *server_port;
>  	const char *http_cookie;
>  	const char *http_referer;
> +	const char *if_none_match;
>  	unsigned int content_length;
>  	int authenticated;
>  };
> diff --git a/ui-plain.c b/ui-plain.c
> index 30fff89..a08dc5b 100644
> --- a/ui-plain.c
> +++ b/ui-plain.c
> @@ -103,8 +103,8 @@ static int print_object(const unsigned char *sha1, const char *path)
>  	ctx.page.filename = path;
>  	ctx.page.size = size;
>  	ctx.page.etag = sha1_to_hex(sha1);
> -	cgit_print_http_headers();
> -	html_raw(buf, size);
> +	if (!cgit_print_http_headers_matching_etag())
> +		html_raw(buf, size);
>  	/* If we allocated this, then casting away const is safe. */
>  	if (freemime)
>  		free((char*) ctx.page.mimetype);
> @@ -128,24 +128,25 @@ static void print_dir(const unsigned char *sha1, const char *base,
>  	fullpath = buildpath(base, baselen, path);
>  	slash = (fullpath[0] == '/' ? "" : "/");
>  	ctx.page.etag = sha1_to_hex(sha1);
> -	cgit_print_http_headers();
> -	htmlf("<html><head><title>%s", slash);
> -	html_txt(fullpath);
> -	htmlf("</title></head>\n<body>\n<h2>%s", slash);
> -	html_txt(fullpath);
> -	html("</h2>\n<ul>\n");
> -	len = strlen(fullpath);
> -	if (len > 1) {
> -		fullpath[len - 1] = 0;
> -		slash = strrchr(fullpath, '/');
> -		if (slash)
> -			*(slash + 1) = 0;
> -		else
> -			fullpath = NULL;
> -		html("<li>");
> -		cgit_plain_link("../", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
> -				fullpath);
> -		html("</li>\n");
> +	if (!cgit_print_http_headers_matching_etag()) {
> +		htmlf("<html><head><title>%s", slash);
> +		html_txt(fullpath);
> +		htmlf("</title></head>\n<body>\n<h2>%s", slash);
> +		html_txt(fullpath);
> +		html("</h2>\n<ul>\n");
> +		len = strlen(fullpath);
> +		if (len > 1) {
> +			fullpath[len - 1] = 0;
> +			slash = strrchr(fullpath, '/');
> +			if (slash)
> +				*(slash + 1) = 0;
> +			else
> +				fullpath = NULL;
> +			html("<li>");
> +			cgit_plain_link("../", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
> +					fullpath);
> +			html("</li>\n");
> +		}
>  	}
>  	free(fullpath);
>  }
> diff --git a/ui-shared.c b/ui-shared.c
> index 9dde0a3..84c7efd 100644
> --- a/ui-shared.c
> +++ b/ui-shared.c
> @@ -661,6 +661,26 @@ void cgit_print_http_headers(void)
>  		exit(0);
>  }
>  
> +int cgit_print_http_headers_matching_etag(void)
> +{
> +	int match = 0;
> +	char *etag;
> +	if (ctx.page.etag && ctx.env.if_none_match) {
> +		etag = fmtalloc("\"%s\"", ctx.page.etag);
> +		if (!strcmp(etag, ctx.env.if_none_match)) {
> +			ctx.page.status = 304;
> +			ctx.page.statusmsg = "Not Modified";
> +			ctx.page.mimetype = NULL;
> +			ctx.page.size = 0;
> +			ctx.page.filename = NULL;
> +			match = 1;
> +		}
> +		free(etag);
> +	}
> +	cgit_print_http_headers();
> +	return match;
> +}
> +
>  void cgit_print_docstart(void)
>  {
>  	if (ctx.cfg.embedded) {
> diff --git a/ui-shared.h b/ui-shared.h
> index 3e7a91b..e279f42 100644
> --- a/ui-shared.h
> +++ b/ui-shared.h
> @@ -60,6 +60,7 @@ extern void cgit_vprint_error(const char *fmt, va_list ap);
>  extern void cgit_print_date(time_t secs, const char *format, int local_time);
>  extern void cgit_print_age(time_t t, time_t max_relative, const char *format);
>  extern void cgit_print_http_headers(void);
> +extern int cgit_print_http_headers_matching_etag(void);
>  extern void cgit_print_docstart(void);
>  extern void cgit_print_docend();
>  extern void cgit_print_pageheader(void);
> -- 
> 2.0.4
> 
> _______________________________________________
> CGit mailing list
> CGit at lists.zx2c4.com
> http://lists.zx2c4.com/mailman/listinfo/cgit


More information about the CGit mailing list