Commit ac3a4381 authored by Dag Erling Smørgrav's avatar Dag Erling Smørgrav

Implement the "error" VCL keyword:

 - add fields to struct sess where VRT_error can store the error code and
   message
 - modify cnt_error() to pass these fields to RES_Error(), then clear them
 - modify RES_Error() (and the entire chain) to accept a third argument
   giving an explanation of the error.
 - have RES_Error() reset the worker before writing the error document, to
   make sure wfd is set.

fixes: #4

git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@823 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 4ed191cc
......@@ -253,6 +253,9 @@ struct sess {
enum step step;
unsigned handling;
unsigned char wantbody;
int err_code;
const char *err_msg;
const char *err_expl;
TAILQ_ENTRY(sess) list;
......@@ -402,7 +405,7 @@ void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...);
#endif
/* cache_response.c */
void RES_Error(struct sess *sp, int error, const char *msg);
void RES_Error(struct sess *sp, int code, const char *msg, const char *expl);
void RES_WriteObj(struct sess *sp);
/* cache_vcl.c */
......
......@@ -130,7 +130,17 @@ DOT }
DOT error -> DONE
*/
static int cnt_error(struct sess *sp) { (void)sp; INCOMPL(); }
static int
cnt_error(struct sess *sp)
{
RES_Error(sp, sp->err_code, sp->err_msg, sp->err_expl);
sp->err_code = 0;
sp->err_msg = NULL;
sp->err_expl = NULL;
sp->step = STP_DONE;
return (0);
}
/*--------------------------------------------------------------------
......@@ -550,7 +560,7 @@ cnt_recv(struct sess *sp)
sp->wrk->acct.req++;
done = http_DissectRequest(sp->http, sp->fd);
if (done != 0) {
RES_Error(sp, done, NULL);
RES_Error(sp, done, NULL, NULL);
sp->step = STP_DONE;
return (0);
}
......
......@@ -14,24 +14,32 @@
/*--------------------------------------------------------------------*/
void
RES_Error(struct sess *sp, int error, const char *msg)
RES_Error(struct sess *sp, int code, const char *msg, const char *expl)
{
char buf[40];
struct vsb *sb;
sb = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
assert(sb != NULL);
assert(code >= 100 && code <= 999);
if (msg == NULL) {
switch (error) {
switch (code) {
case 400: msg = "Bad Request"; break;
case 500: msg = "Internal Error"; break;
default: msg = "HTTP request error"; break;
}
}
if (expl == NULL) {
switch (code) {
case 400: expl = "Your HTTP protocol request did not make sense."; break;
case 404: expl = "The document you requested was not found."; break;
default: expl = "Something unexpected happened."; break;
}
}
vsb_clear(sb);
vsb_printf(sb, "HTTP/1.1 %03d %s\r\n", error, msg);
vsb_printf(sb, "HTTP/1.1 %03d %s\r\n", code, msg);
TIM_format(sp->t_req.tv_sec, buf);
vsb_printf(sb, "Date: %s\r\n", buf);
vsb_cat(sb,
......@@ -42,29 +50,18 @@ RES_Error(struct sess *sp, int error, const char *msg)
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
"<HTML>\r\n"
" <HEAD>\r\n");
vsb_printf(sb, " <TITLE>%03d %s</TITLE>\r\n", error, msg);
vsb_printf(sb, " <TITLE>%03d %s</TITLE>\r\n", code, msg);
vsb_cat(sb,
" </HEAD>\r\n"
" <BODY>\r\n");
vsb_printf(sb, " <H1>Error %03d %s</H1>\r\n", error, msg);
switch(error) {
case 400:
vsb_cat(sb,
" Your HTTP protocol request did not make sense.\r\n");
break;
case 500:
default:
vsb_cat(sb,
" Something unexpected happened.\r\n");
break;
}
vsb_printf(sb, " <H1>Error %03d %s</H1>\r\n", code, msg);
vsb_printf(sb, " <P>%s</P>\r\n", expl);
vsb_cat(sb,
" <P>\r\n"
" <I>\r\n"
" <A href=\"http://varnish.linpro.no/\">Varnish</A>\r\n"
" <I><A href=\"http://varnish.linpro.no/\">Varnish</A></I>\r\n"
" </BODY>\r\n"
"</HTML>\r\n");
vsb_finish(sb);
WRK_Reset(sp->wrk, &sp->fd);
WRK_Write(sp->wrk, vsb_data(sb), vsb_len(sb));
WRK_Flush(sp->wrk);
vca_close_session(sp, msg);
......
......@@ -18,11 +18,14 @@
/*--------------------------------------------------------------------*/
void
VRT_error(struct sess *sp, unsigned err, const char *str)
VRT_error(struct sess *sp, unsigned code, const char *msg, const char *expl)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
VSL(SLT_Debug, 0, "VCL_error(%u, %s)", err, str);
VSL(SLT_Debug, 0, "VCL_error(%u, %s, %s)", code, msg, expl);
sp->err_code = code;
sp->err_msg = msg;
sp->err_expl = expl;
}
/*--------------------------------------------------------------------*/
......
......@@ -42,7 +42,7 @@ int VRT_re_test(struct vsb *, const char *);
void VRT_count(struct sess *, unsigned);
int VRT_rewrite(const char *, const char *);
void VRT_error(struct sess *, unsigned, const char *);
void VRT_error(struct sess *, unsigned, const char *, const char *);
int VRT_switch_config(const char *);
char *VRT_GetHdr(struct sess *, const char *);
......
/*
* $Id: /mirror/varnish/trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl 30495 2006-07-22T08:02:47.026287Z phk $
* $Id: /mirror/varnish/trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl 30980 2006-08-09T11:24:39.011200Z des $
*
* NB: This file is machine generated, DO NOT EDIT!
*
......
......@@ -708,6 +708,7 @@ Action(struct tokenlist *tl)
unsigned a;
struct var *vp;
struct token *at;
int i;
at = tl->t;
vcc_NextToken(tl);
......@@ -730,12 +731,16 @@ Action(struct tokenlist *tl)
a = UintVal(tl);
else
a = 0;
Fc(tl, 1, "VRT_error(sp, %u, ", a);
if (tl->t->tok == CSTR) {
Fc(tl, 0, "%.*s);\n", PF(tl->t));
vcc_NextToken(tl);
} else
Fc(tl, 0, "(const char *)0);\n");
Fc(tl, 1, "VRT_error(sp, %u", a);
for (i = 0; i < 2; ++i) {
if (tl->t->tok == CSTR) {
Fc(tl, 0, ", %.*s", PF(tl->t));
vcc_NextToken(tl);
} else {
Fc(tl, 0, ", (const char *)0");
}
}
Fc(tl, 0, ");\n");
Fc(tl, 1, "VRT_done(sp, VCL_RET_ERROR);\n");
return;
case T_SWITCH_CONFIG:
......
......@@ -510,7 +510,7 @@ vcl_output_lang_h(FILE *f)
fputs("\n", f);
fputs("void VRT_count(struct sess *, unsigned);\n", f);
fputs("int VRT_rewrite(const char *, const char *);\n", f);
fputs("void VRT_error(struct sess *, unsigned, const char *);\n", f);
fputs("void VRT_error(struct sess *, unsigned, const char *, const char *);\n", f);
fputs("int VRT_switch_config(const char *);\n", f);
fputs("\n", f);
fputs("char *VRT_GetHdr(struct sess *, const char *);\n", f);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment