diff --git a/include/haproxy/http.h b/include/haproxy/http.h index 299264051..e28f3cc90 100644 --- a/include/haproxy/http.h +++ b/include/haproxy/http.h @@ -27,15 +27,20 @@ #include #include #include +#include extern const int http_err_codes[HTTP_ERR_SIZE]; extern const char *http_err_msgs[HTTP_ERR_SIZE]; extern const struct ist http_known_methods[HTTP_METH_OTHER]; extern const uint8_t http_char_classes[256]; +extern long http_err_status_codes[512 / sizeof(long)]; +extern long http_fail_status_codes[512 / sizeof(long)]; enum http_meth_t find_http_meth(const char *str, const int len); int http_get_status_idx(unsigned int status); const char *http_get_reason(unsigned int status); +void http_status_add_range(long *array, uint low, uint high); +void http_status_del_range(long *array, uint low, uint high); struct ist http_get_host_port(const struct ist host); int http_is_default_port(const struct ist schm, const struct ist port); int http_validate_scheme(const struct ist schm); @@ -212,6 +217,18 @@ static inline int http_path_has_forbidden_char(const struct ist ist, const char return 0; } +/* Checks status code array for the presence of status code . + * Returns non-zero if the code is present, zero otherwise. Any status code is + * permitted. + */ +static inline int http_status_matches(const long *array, uint status) +{ + if (status < 100 || status > 599) + return 0; + + return ha_bit_test(status - 100, array); +} + #endif /* _HAPROXY_HTTP_H */ /* diff --git a/src/http.c b/src/http.c index 072762d85..82da7bb13 100644 --- a/src/http.c +++ b/src/http.c @@ -344,6 +344,14 @@ const struct ist http_known_methods[HTTP_METH_OTHER] = { [HTTP_METH_CONNECT] = IST("CONNECT"), }; +/* 500 bits to indicate for each status code from 100 to 599 if it participates + * to the error or failure class. The last 12 bits are not assigned for now. + * Not initialized, has to be done at boot. This is manipulated using + * http_status_{add,del}_range(). + */ +long http_err_status_codes[512 / sizeof(long)] = { }; +long http_fail_status_codes[512 / sizeof(long)] = { }; + /* * returns a known method among HTTP_METH_* or HTTP_METH_OTHER for all unknown * ones. @@ -477,6 +485,40 @@ const char *http_get_reason(unsigned int status) } } +/* add status codes from low to high included to status codes array + * which must be compatible with http_err_codes and http_fail_codes (i.e. 512 + * bits each). This is not thread save and is meant for being called during + * boot only. Only status codes 100-599 are permitted. + */ +void http_status_add_range(long *array, uint low, uint high) +{ + low -= 100; + high -= 100; + + BUG_ON(low > 499); + BUG_ON(high > 499); + + while (low <= high) + ha_bit_set(low++, array); +} + +/* remove status codes from low to high included to status codes array + * which must be compatible with http_err_codes and http_fail_codes (i.e. 512 + * bits each). This is not thread save and is meant for being called during + * boot only. Only status codes 100-599 are permitted. + */ +void http_status_del_range(long *array, uint low, uint high) +{ + low -= 100; + high -= 100; + + BUG_ON(low > 499); + BUG_ON(high > 499); + + while (low <= high) + ha_bit_clr(low++, array); +} + /* Returns the ist string corresponding to port part (without ':') in the host * , IST_NULL if no ':' is found or an empty IST if there is no digit. In * the last case, the result is the original ist trimmed to 0. So be sure to test @@ -1430,3 +1472,14 @@ struct ist http_trim_trailing_spht(struct ist value) return ret; } + +/* initialize the required structures and arrays */ +static void _http_init() +{ + /* preset the default status codes that count as errors and failures */ + http_status_add_range(http_err_status_codes, 400, 499); + http_status_add_range(http_fail_status_codes, 500, 599); + http_status_del_range(http_fail_status_codes, 501, 501); + http_status_del_range(http_fail_status_codes, 505, 505); +} +INITCALL0(STG_INIT, _http_init);