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 { ...@@ -253,6 +253,9 @@ struct sess {
enum step step; enum step step;
unsigned handling; unsigned handling;
unsigned char wantbody; unsigned char wantbody;
int err_code;
const char *err_msg;
const char *err_expl;
TAILQ_ENTRY(sess) list; TAILQ_ENTRY(sess) list;
...@@ -402,7 +405,7 @@ void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...); ...@@ -402,7 +405,7 @@ void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...);
#endif #endif
/* cache_response.c */ /* 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); void RES_WriteObj(struct sess *sp);
/* cache_vcl.c */ /* cache_vcl.c */
......
...@@ -130,7 +130,17 @@ DOT } ...@@ -130,7 +130,17 @@ DOT }
DOT error -> DONE 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) ...@@ -550,7 +560,7 @@ cnt_recv(struct sess *sp)
sp->wrk->acct.req++; sp->wrk->acct.req++;
done = http_DissectRequest(sp->http, sp->fd); done = http_DissectRequest(sp->http, sp->fd);
if (done != 0) { if (done != 0) {
RES_Error(sp, done, NULL); RES_Error(sp, done, NULL, NULL);
sp->step = STP_DONE; sp->step = STP_DONE;
return (0); return (0);
} }
......
...@@ -14,24 +14,32 @@ ...@@ -14,24 +14,32 @@
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void 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]; char buf[40];
struct vsb *sb; struct vsb *sb;
sb = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND); sb = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
assert(sb != NULL); assert(sb != NULL);
assert(code >= 100 && code <= 999);
if (msg == NULL) { if (msg == NULL) {
switch (error) { switch (code) {
case 400: msg = "Bad Request"; break; case 400: msg = "Bad Request"; break;
case 500: msg = "Internal Error"; break; case 500: msg = "Internal Error"; break;
default: msg = "HTTP request 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_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); TIM_format(sp->t_req.tv_sec, buf);
vsb_printf(sb, "Date: %s\r\n", buf); vsb_printf(sb, "Date: %s\r\n", buf);
vsb_cat(sb, vsb_cat(sb,
...@@ -42,29 +50,18 @@ RES_Error(struct sess *sp, int error, const char *msg) ...@@ -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" "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
"<HTML>\r\n" "<HTML>\r\n"
" <HEAD>\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, vsb_cat(sb,
" </HEAD>\r\n" " </HEAD>\r\n"
" <BODY>\r\n"); " <BODY>\r\n");
vsb_printf(sb, " <H1>Error %03d %s</H1>\r\n", error, msg); vsb_printf(sb, " <H1>Error %03d %s</H1>\r\n", code, msg);
switch(error) { vsb_printf(sb, " <P>%s</P>\r\n", expl);
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_cat(sb, vsb_cat(sb,
" <P>\r\n" " <I><A href=\"http://varnish.linpro.no/\">Varnish</A></I>\r\n"
" <I>\r\n"
" <A href=\"http://varnish.linpro.no/\">Varnish</A>\r\n"
" </BODY>\r\n" " </BODY>\r\n"
"</HTML>\r\n"); "</HTML>\r\n");
vsb_finish(sb); vsb_finish(sb);
WRK_Reset(sp->wrk, &sp->fd);
WRK_Write(sp->wrk, vsb_data(sb), vsb_len(sb)); WRK_Write(sp->wrk, vsb_data(sb), vsb_len(sb));
WRK_Flush(sp->wrk); WRK_Flush(sp->wrk);
vca_close_session(sp, msg); vca_close_session(sp, msg);
......
...@@ -18,11 +18,14 @@ ...@@ -18,11 +18,14 @@
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void 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); 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 *); ...@@ -42,7 +42,7 @@ int VRT_re_test(struct vsb *, const char *);
void VRT_count(struct sess *, unsigned); void VRT_count(struct sess *, unsigned);
int VRT_rewrite(const char *, const char *); 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 *); int VRT_switch_config(const char *);
char *VRT_GetHdr(struct sess *, 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! * NB: This file is machine generated, DO NOT EDIT!
* *
......
...@@ -708,6 +708,7 @@ Action(struct tokenlist *tl) ...@@ -708,6 +708,7 @@ Action(struct tokenlist *tl)
unsigned a; unsigned a;
struct var *vp; struct var *vp;
struct token *at; struct token *at;
int i;
at = tl->t; at = tl->t;
vcc_NextToken(tl); vcc_NextToken(tl);
...@@ -730,12 +731,16 @@ Action(struct tokenlist *tl) ...@@ -730,12 +731,16 @@ Action(struct tokenlist *tl)
a = UintVal(tl); a = UintVal(tl);
else else
a = 0; a = 0;
Fc(tl, 1, "VRT_error(sp, %u, ", a); Fc(tl, 1, "VRT_error(sp, %u", a);
if (tl->t->tok == CSTR) { for (i = 0; i < 2; ++i) {
Fc(tl, 0, "%.*s);\n", PF(tl->t)); if (tl->t->tok == CSTR) {
vcc_NextToken(tl); Fc(tl, 0, ", %.*s", PF(tl->t));
} else vcc_NextToken(tl);
Fc(tl, 0, "(const char *)0);\n"); } else {
Fc(tl, 0, ", (const char *)0");
}
}
Fc(tl, 0, ");\n");
Fc(tl, 1, "VRT_done(sp, VCL_RET_ERROR);\n"); Fc(tl, 1, "VRT_done(sp, VCL_RET_ERROR);\n");
return; return;
case T_SWITCH_CONFIG: case T_SWITCH_CONFIG:
......
...@@ -510,7 +510,7 @@ vcl_output_lang_h(FILE *f) ...@@ -510,7 +510,7 @@ vcl_output_lang_h(FILE *f)
fputs("\n", f); fputs("\n", f);
fputs("void VRT_count(struct sess *, unsigned);\n", f); fputs("void VRT_count(struct sess *, unsigned);\n", f);
fputs("int VRT_rewrite(const char *, const char *);\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("int VRT_switch_config(const char *);\n", f);
fputs("\n", f); fputs("\n", f);
fputs("char *VRT_GetHdr(struct sess *, const char *);\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