Skip to content

Commit 0cc9aeb

Browse files
committed
Updating to version 0.3, with HA Proxy support
1 parent 2a3e290 commit 0cc9aeb

File tree

2 files changed

+125
-12
lines changed

2 files changed

+125
-12
lines changed

README.md

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ needs to store stateful information, consider writing a daemon that runs on its
1010
own as opposed to an xinetd application. However, if your needs are light, and
1111
you want HTTP REST-like capabilities, perhaps this meets your needs.
1212

13+
##### Version 0.3 with support for HA Proxy HTTP header
14+
Version 0.3 was updated to parse HA Proxy's `X-Haproxy-Server-State` HTTP
15+
header when HAProxy uses the configuration `option httpchk` with `http-check
16+
send-state`. By default, this xinetd script can send results back to HA Proxy
17+
with both `option tcp-check` and `option httpchk` without differing
18+
configuration. See **HA Proxy Use** below.
19+
1320

1421
## Using for your purposes
1522

@@ -42,29 +49,43 @@ http_response 200 "Success"
4249

4350
### Available functions
4451

45-
#### get_http_req_uri_params_value <param-name>
52+
* #### get_http_req_uri_params_value <param-name>
4653
This function will obtain the value of a paramter provided in the HTTP request.
4754
```bash
4855
# if GET Request URI (GET_REQ_URI) is "/?uptime=seconds&format=json"
4956
format_value=$(get_http_req_uri_params_value "format")
5057
# Result: format_value == json
5158
```
5259

53-
#### http_response <http-code> <message>
60+
* #### get_haproxy_server_state_value <param-name>
61+
This function will obtain the value of a paramter provided in the HTTP request
62+
header **X-Haproxy-Server-State**.
63+
```bash
64+
# if `X-Haproxy-Server-State: UP; name=backend/server; node=haproxy-name; weight=1/2; scur=0/1; qcur=0; throttle=86%
65+
HA_NAME=$(get_haproxy_server_state_value name)
66+
# Result: HA_NAME == backend/server
67+
HA_WEIGHT=$(get_haproxy_server_state_value weight)
68+
# Result: HA_WEIGHT == 1/2
69+
HA_STATE=$(get_haproxy_server_state_value state)
70+
# Result: HA_STATE == UP
71+
```
72+
73+
74+
* #### http_response <http-code> <message>
5475
This function will return a HTTP response and exit.
5576
It will do nothing and return if the --http-response option is not set to 1,
5677
or if the request came from the command line and not as a HTTP request.
5778
```bash
5879
http_response 301 "I did not find what you were looking for."
5980
```
6081

61-
#### decrease_health_value
82+
* #### decrease_health_value
6283
This function will decrease the global health value
6384
```bash
6485
decrease_health_value
6586
```
6687

67-
#### display_health_value
88+
* #### display_health_value
6889
This function displays the global helath value in a HTTP response or standard
6990
output for the command line, and then exits.
7091
```bash
@@ -76,7 +97,7 @@ display_health_value
7697

7798
```bash
7899
linux$ xinetdhttpservice.sh --help
79-
xinetd_http_service 0.2
100+
xinetd_http_service 0.3
80101
https://github.com/rglaue/xinetd_bash_http_service
81102
Copyright (C) 2018 Russell Glaue, CAIT, WIU <http://www.cait.org>
82103

@@ -107,7 +128,7 @@ Examples:
107128
108129
### Test to see how HTTP headers are parsed
109130
110-
#### HTTP GET
131+
* #### HTTP GET
111132
112133
```bash
113134
linux$ echo "GET /test123?var1=val1 HTTP/1.0" | xinetdhttpservice.sh --http-status --show-headers
@@ -124,7 +145,7 @@ HTTP_REQ_METHOD=GET
124145
HTTP_REQ_URI_PARAMS=var1=val1
125146
```
126147
127-
#### HTTP POST
148+
* #### HTTP POST
128149
129150
```bash
130151
linux$ xinetdhttpservice.sh --show-headers <<HTTP_EOF
@@ -170,7 +191,7 @@ HTTP_SERVER=127.0.0.1:8080
170191
--END:HTTP_POST_CONTENT--
171192
```
172193
173-
#### HTTP POST Config: MAX_HTTP_POST_LENGTH
194+
* #### HTTP POST Config: MAX_HTTP_POST_LENGTH
174195
175196
At the top of the xinetdhttpservice.sh bash script, there is a global variable
176197
that define the maximum allowed length of posted data. Posted data that has a
@@ -180,7 +201,7 @@ length greater than this will be cut off.
180201
MAX_HTTP_POST_LENGTH=200
181202
```
182203
183-
#### HTTP POST Config: READ_BUFFER_LENGTH
204+
* #### HTTP POST Config: READ_BUFFER_LENGTH
184205
185206
If a non-compliant HTTP client is posting data that is shorter than the
186207
Content-Length, then the READ_BUFFER_LENGTH should be set to 1. By default
@@ -249,6 +270,62 @@ WEIGHT_VALUE=119
249270
[xinetdhttpservice_config]: https://github.com/rglaue/xinetd_bash_http_service/blob/master/xinetdhttpservice_config
250271
251272
273+
### As a HAProxy server check
274+
275+
First setup the xinetd service, as described previously. Once setup, you should
276+
be able to get the service status via TCP or HTTP check in HAProxy. This can be
277+
tested as follows. Both TCP and HTTP checks will work without differing
278+
configuration in the xinetd_bash_http_service script because the `http_response`
279+
function only delivers output if the client made an HTTP request.
280+
281+
* #### Testing the health checks
282+
```bash
283+
# TCP Checks
284+
shell$ echo | nc 192.168.2.11 8080
285+
Service OK
286+
# HTTP Checks
287+
shell$ curl http://192.168.2.11:8080
288+
Service OK
289+
```
290+
291+
* #### Ensure xinetd script outputs for both HTTP and TCP
292+
```bash
293+
# At the end of your xinetd_bash_http_service script
294+
# send the HTTP response and exit
295+
http_response 200 "Service OK"
296+
# or send a TCP response and exit
297+
echo "Service OK"
298+
exit 0
299+
# end of script
300+
```
301+
302+
* #### Configure HA Proxy
303+
```bash
304+
frontend some-fe-server
305+
bind 192.168.1.1:1234
306+
mode tcp
307+
default_backend some-be-server-pool
308+
309+
# Both of these backends will work, but use http checks with the
310+
# 'http-check send-state' if you want to receive the HA Proxy state.
311+
312+
# tcp checks
313+
#backend some-be-server-pool
314+
# option tcp-check
315+
# tcp-check expect string "Service OK"
316+
# server srv1 192.168.2.11:80 check port 8080
317+
# server srv2 192.168.2.12:80 check port 8080
318+
319+
# http checks
320+
backend some-be-server-pool
321+
option httpchk GET /
322+
http-check send-state
323+
http-check expect string "Service OK"
324+
server srv1 192.168.2.11:80 check port 8080
325+
server srv2 192.168.2.12:80 check port 8080
326+
```
327+
328+
252329
## License
253330
254331
Copyright (C) 2018 [Center for the Application of Information Technologies](http://www.cait.org),

xinetdhttpservice.sh

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
PROG=xinetd_http_service
88
DESCRIPTION="bash script called by xinetd to service a HTTP request; a farmework for reporting on health"
99
SYNOPSIS="${PROG} [options]"
10-
VERSION=0.2
11-
LASTMOD=20180822
10+
VERSION=0.3
11+
LASTMOD=20180904
1212
MAX_HTTP_POST_LENGTH=200
1313

1414
#
@@ -139,6 +139,9 @@ while read -t 0.01 line; do
139139
elif echo "${line}" | grep -qi "^Content-Type:"; then
140140
# Content-Type: application/x-www-form-urlencoded
141141
export HTTP_CONTENT_TYPE="$(echo "${line}"|cut -d" " -f 2-)"
142+
elif echo "${line}" | grep -qi "^X-Haproxy-Server-State:"; then
143+
# X-Haproxy-Server-State: UP; etc..
144+
export HTTP_HAPROXY_SERVER_STATE="$(echo "${line}"|cut -d" " -f 2-)"
142145
elif [ ${#line} -ge 1 ]; then
143146
# <any header>
144147
continue
@@ -212,9 +215,42 @@ get_http_req_uri_params_value () {
212215
exit 1
213216
}
214217

218+
#
219+
# A function for HAProxy
220+
# Parses the value in the HTTP header "X-Haproxy-Server-State"
221+
# Examples:
222+
# HA_WEIGHT=$(get_haproxy_server_state_value weight) # HA_WEIGHT="1/2"
223+
# HA_STATE=$(get_haproxy_server_state_value state) # UP, DOWN, NOLB
224+
#
225+
get_haproxy_server_state_value () {
226+
# Example: "UP; name=backend/server; node=haproxy-name; weight=1/2; scur=0/1; qcur=0; throttle=86%"
227+
PARAM_NAME=$1
228+
IFS='; ' read -r -a params <<< "$HTTP_HAPROXY_SERVER_STATE"
229+
if [ "$PARAM_NAME" == "state" ]; then
230+
echo "${params[0]}"
231+
exit 0
232+
fi
233+
for element in "${params[@]}"; do
234+
element_name="$(echo "$element" | cut -d"=" -f 1)"
235+
if [ "$element_name" == "$PARAM_NAME" ]; then
236+
if echo "$element" | grep -q "="; then
237+
element_value="$(echo "$element" | cut -d"=" -f 2-)"
238+
echo "$element_value"
239+
else
240+
echo ""
241+
fi
242+
exit 0
243+
fi
244+
done
245+
exit 1
246+
}
247+
215248
#
216249
# Parse parameters from the HTTP request
217250
#
251+
if [ ! -z "${HTTP_REQ_URI_PATH}" ]; then
252+
OPT_HTTP_STATUS=1
253+
fi
218254
if echo ${HTTP_REQ_URI_PATH} | grep -qi "health-value"; then
219255
OPT_HTTP_STATUS=1
220256
OPT_HEALTH_VALUE=1
@@ -341,7 +377,7 @@ decrease_health_value
341377
# display health value response, and exit
342378
display_health_value
343379

344-
# send a http_response of 200
380+
# send a http_response of 200, and exit
345381
http_response 200 "Success"
346382

347383
# End of program

0 commit comments

Comments
 (0)