diff -Naur haproxy-ss-20090207/include/types/proxy.h haproxy-ss-20090222/include/types/proxy.h --- haproxy-ss-20090207/include/types/proxy.h 2009-02-06 18:28:13.000000000 +0800 +++ haproxy-ss-20090222/include/types/proxy.h 2009-02-23 20:04:54.000000000 +0800 @@ -110,6 +110,8 @@ #define PR_O2_SPLIC_REQ 0x00000001 /* transfer requests using linux kernel's splice() */ #define PR_O2_SPLIC_RTR 0x00000002 /* transfer responses using linux kernel's splice() */ #define PR_O2_SPLIC_AUT 0x00000004 /* automatically use linux kernel's splice() */ +#define PR_O2_EXPECT 0x00000008 /* http-check expect sth */ +#define PR_O2_NOEXPECT 0x00000010 /* http-check expect ! sth */ #define PR_O2_SPLIC_ANY (PR_O2_SPLIC_REQ|PR_O2_SPLIC_RTR|PR_O2_SPLIC_AUT) /* This structure is used to apply fast weighted round robin on a server group */ @@ -253,6 +255,9 @@ char *req_add[MAX_NEWHDR], *rsp_add[MAX_NEWHDR]; /* headers to be added */ int grace; /* grace time after stop request */ char *check_req; /* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */ + char *expect_str; /* http-check expected content */ + regex_t *expect_regex; /* http-check expected content */ + char *expect_type; /* type of http-check, such as status, string */ int check_len; /* Length of the HTTP or SSL3 request */ struct chunk errmsg[HTTP_ERR_SIZE]; /* default or customized error messages for known errors */ int uuid; /* universally unique proxy ID, used for SNMP */ diff -Naur haproxy-ss-20090207/src/cfgparse.c haproxy-ss-20090222/src/cfgparse.c --- haproxy-ss-20090207/src/cfgparse.c 2009-02-06 18:28:13.000000000 +0800 +++ haproxy-ss-20090222/src/cfgparse.c 2009-02-24 10:54:20.000000000 +0800 @@ -1662,9 +1662,69 @@ if (strcmp(args[1], "disable-on-404") == 0) { /* enable a graceful server shutdown on an HTTP 404 response */ curproxy->options |= PR_O_DISABLE404; + } + else if(strcmp(args[1], "expect") == 0) { + if(strcmp(args[2], "status") == 0 || strcmp(args[2], "string") == 0) { + curproxy->options2 |= PR_O2_EXPECT; + if(*(args[3]) == 0) { + Alert("parsing [%s:%d] : '%s %s %s' expects as an argument.\n", + file, linenum, args[0], args[1], args[2]); + return -1; + } + curproxy->expect_type = strdup(args[2]); + curproxy->expect_str = strdup(args[3]); + + } + else if(strcmp(args[2], "rstatus") == 0 || strcmp(args[2], "rstring") == 0) { + curproxy->options2 |= PR_O2_EXPECT; + if(*(args[3]) == 0) { + Alert("parsing [%s:%d] : '%s %s %s' expects as an argument.\n", + file, linenum, args[0], args[1], args[2]); + return -1; + } + curproxy->expect_regex = calloc(1, sizeof(regex_t)); + if (regcomp(curproxy->expect_regex, args[3], REG_EXTENDED) != 0) { + Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[0]); + return -1; + } + curproxy->expect_type = strdup(args[2]); + } + + else if(strcmp(args[2], "!") == 0 ) { + curproxy->options2 |= PR_O2_NOEXPECT; + if(strcmp(args[3], "status") == 0 || strcmp(args[3], "string") == 0) { + if(*(args[4]) == 0) { + Alert("parsing [%s:%d] : '%s %s %s %s' expects as an argument.\n", + file, linenum, args[0], args[1], args[2], args[3]); + return -1; + } + curproxy->expect_type = strdup(args[3]); + curproxy->expect_str = strdup(args[4]); + } + else if(strcmp(args[3], "rstatus") == 0 || strcmp(args[3], "rstring") == 0) { + if(*(args[4]) == 0) { + Alert("parsing [%s:%d] : '%s %s %s %s' expects as an argument.\n", + file, linenum, args[0], args[1], args[2], args[3]); + return -1; + } + + free(curproxy->expect_regex); + curproxy->expect_regex = calloc(1, sizeof(regex_t)); + if (regcomp(curproxy->expect_regex, args[4], REG_EXTENDED) != 0) { + Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[0]); + return -1; + } + curproxy->expect_type = strdup(args[3]); + } + + } + else { + Alert("parsing [%s:%d] : '%s %s' only supports (!) (r)status|(r)string'.\n", file, linenum, args[0], args[1]); + return -1; + } } else { - Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]); + Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]); return -1; } } diff -Naur haproxy-ss-20090207/src/checks.c haproxy-ss-20090222/src/checks.c --- haproxy-ss-20090207/src/checks.c 2009-02-06 18:28:13.000000000 +0800 +++ haproxy-ss-20090222/src/checks.c 2009-02-24 10:47:05.000000000 +0800 @@ -42,6 +42,8 @@ #include #include +static void httpchk_expect(struct server *s); + /* sends a log message when a backend goes down, and also sets last * change date. */ @@ -477,8 +479,11 @@ goto out_wakeup; } + if((s->proxy->options2 & PR_O2_EXPECT) || (s->proxy->options2 & PR_O2_NOEXPECT)) { + httpchk_expect(s); + } /* check the reply : HTTP/1.X 2xx and 3xx are OK */ - if (trash[9] == '2' || trash[9] == '3') + else if (trash[9] == '2' || trash[9] == '3') s->result |= SRV_CHK_RUNNING; else if ((s->proxy->options & PR_O_DISABLE404) && (s->state & SRV_RUNNING) && @@ -872,6 +877,68 @@ return 0; } +static void httpchk_expect(struct server *s) +{ + int inv = 0; + int ret; + if(s->proxy->options2 & PR_O2_EXPECT) + inv = 1; + + if(strcmp(s->proxy->expect_type, "status") == 0 || strcmp(s->proxy->expect_type, "rstatus") == 0 ) { + char status_code[] = "000"; + memcpy(status_code, &trash[9], 3); + if(strcmp(s->proxy->expect_type, "status") == 0 ) + ret = strncmp(s->proxy->expect_str, status_code, 3); + else + ret = regexec(s->proxy->expect_regex, status_code, MAX_MATCH, pmatch, 0); + + if(ret == 0) { + if(inv) + s->result |= SRV_CHK_RUNNING; + else + s->result |= SRV_CHK_ERROR; + } + else { + if(inv) + s->result |= SRV_CHK_ERROR; + else + s->result |= SRV_CHK_RUNNING; + } + } + else if(strcmp(s->proxy->expect_type, "string") == 0 || strcmp(s->proxy->expect_type, "rstring") == 0) { + + char content[BUFSIZE]; + memcpy(content, trash, sizeof(trash)); + char *contentlen=strstr(content, "Content-Length"); + char *conlen; + contentlen+=16; + if ( (conlen=strstr(contentlen,"\n")) != NULL ) + *conlen = '\0'; + + /* get the response content */ + char *contentptr=NULL; + if((contentptr = strstr(trash, "\r\n\r\n")) != NULL) { + contentptr += 4; + contentptr[atoi(contentlen)] = '\0'; + if(strcmp(s->proxy->expect_type, "string") == 0) + ret = strncmp(s->proxy->expect_str, contentptr, atoi(contentlen)-1); + else + ret = regexec(s->proxy->expect_regex, contentptr, MAX_MATCH, pmatch, 0); + if(ret == 0 ) { + if(inv) + s->result |= SRV_CHK_RUNNING; + else + s->result |= SRV_CHK_ERROR; + } + else { + if(inv) + s->result |= SRV_CHK_ERROR; + else + s->result |= SRV_CHK_RUNNING; + } + } + } +} /* * Local variables: * c-indent-level: 8