Skip to content

Commit

Permalink
Updating to version 0.3, with HA Proxy support
Browse files Browse the repository at this point in the history
  • Loading branch information
rglaue committed Sep 4, 2018
1 parent 2a3e290 commit 0cc9aeb
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 12 deletions.
95 changes: 86 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ needs to store stateful information, consider writing a daemon that runs on its
own as opposed to an xinetd application. However, if your needs are light, and
you want HTTP REST-like capabilities, perhaps this meets your needs.

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


## Using for your purposes

Expand Down Expand Up @@ -42,29 +49,43 @@ http_response 200 "Success"

### Available functions

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

#### http_response <http-code> <message>
* #### get_haproxy_server_state_value <param-name>
This function will obtain the value of a paramter provided in the HTTP request
header **X-Haproxy-Server-State**.
```bash
# if `X-Haproxy-Server-State: UP; name=backend/server; node=haproxy-name; weight=1/2; scur=0/1; qcur=0; throttle=86%
HA_NAME=$(get_haproxy_server_state_value name)
# Result: HA_NAME == backend/server
HA_WEIGHT=$(get_haproxy_server_state_value weight)
# Result: HA_WEIGHT == 1/2
HA_STATE=$(get_haproxy_server_state_value state)
# Result: HA_STATE == UP
```


* #### http_response <http-code> <message>
This function will return a HTTP response and exit.
It will do nothing and return if the --http-response option is not set to 1,
or if the request came from the command line and not as a HTTP request.
```bash
http_response 301 "I did not find what you were looking for."
```

#### decrease_health_value
* #### decrease_health_value
This function will decrease the global health value
```bash
decrease_health_value
```

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

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

Expand Down Expand Up @@ -107,7 +128,7 @@ Examples:
### Test to see how HTTP headers are parsed
#### HTTP GET
* #### HTTP GET
```bash
linux$ echo "GET /test123?var1=val1 HTTP/1.0" | xinetdhttpservice.sh --http-status --show-headers
Expand All @@ -124,7 +145,7 @@ HTTP_REQ_METHOD=GET
HTTP_REQ_URI_PARAMS=var1=val1
```
#### HTTP POST
* #### HTTP POST
```bash
linux$ xinetdhttpservice.sh --show-headers <<HTTP_EOF
Expand Down Expand Up @@ -170,7 +191,7 @@ HTTP_SERVER=127.0.0.1:8080
--END:HTTP_POST_CONTENT--
```
#### HTTP POST Config: MAX_HTTP_POST_LENGTH
* #### HTTP POST Config: MAX_HTTP_POST_LENGTH
At the top of the xinetdhttpservice.sh bash script, there is a global variable
that define the maximum allowed length of posted data. Posted data that has a
Expand All @@ -180,7 +201,7 @@ length greater than this will be cut off.
MAX_HTTP_POST_LENGTH=200
```
#### HTTP POST Config: READ_BUFFER_LENGTH
* #### HTTP POST Config: READ_BUFFER_LENGTH
If a non-compliant HTTP client is posting data that is shorter than the
Content-Length, then the READ_BUFFER_LENGTH should be set to 1. By default
Expand Down Expand Up @@ -249,6 +270,62 @@ WEIGHT_VALUE=119
[xinetdhttpservice_config]: https://github.com/rglaue/xinetd_bash_http_service/blob/master/xinetdhttpservice_config
### As a HAProxy server check
First setup the xinetd service, as described previously. Once setup, you should
be able to get the service status via TCP or HTTP check in HAProxy. This can be
tested as follows. Both TCP and HTTP checks will work without differing
configuration in the xinetd_bash_http_service script because the `http_response`
function only delivers output if the client made an HTTP request.
* #### Testing the health checks
```bash
# TCP Checks
shell$ echo | nc 192.168.2.11 8080
Service OK
# HTTP Checks
shell$ curl http://192.168.2.11:8080
Service OK
```
* #### Ensure xinetd script outputs for both HTTP and TCP
```bash
# At the end of your xinetd_bash_http_service script
# send the HTTP response and exit
http_response 200 "Service OK"
# or send a TCP response and exit
echo "Service OK"
exit 0
# end of script
```
* #### Configure HA Proxy
```bash
frontend some-fe-server
bind 192.168.1.1:1234
mode tcp
default_backend some-be-server-pool
# Both of these backends will work, but use http checks with the
# 'http-check send-state' if you want to receive the HA Proxy state.
# tcp checks
#backend some-be-server-pool
# option tcp-check
# tcp-check expect string "Service OK"
# server srv1 192.168.2.11:80 check port 8080
# server srv2 192.168.2.12:80 check port 8080
# http checks
backend some-be-server-pool
option httpchk GET /
http-check send-state
http-check expect string "Service OK"
server srv1 192.168.2.11:80 check port 8080
server srv2 192.168.2.12:80 check port 8080
```
## License
Copyright (C) 2018 [Center for the Application of Information Technologies](http://www.cait.org),
Expand Down
42 changes: 39 additions & 3 deletions xinetdhttpservice.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
PROG=xinetd_http_service
DESCRIPTION="bash script called by xinetd to service a HTTP request; a farmework for reporting on health"
SYNOPSIS="${PROG} [options]"
VERSION=0.2
LASTMOD=20180822
VERSION=0.3
LASTMOD=20180904
MAX_HTTP_POST_LENGTH=200

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

#
# A function for HAProxy
# Parses the value in the HTTP header "X-Haproxy-Server-State"
# Examples:
# HA_WEIGHT=$(get_haproxy_server_state_value weight) # HA_WEIGHT="1/2"
# HA_STATE=$(get_haproxy_server_state_value state) # UP, DOWN, NOLB
#
get_haproxy_server_state_value () {
# Example: "UP; name=backend/server; node=haproxy-name; weight=1/2; scur=0/1; qcur=0; throttle=86%"
PARAM_NAME=$1
IFS='; ' read -r -a params <<< "$HTTP_HAPROXY_SERVER_STATE"
if [ "$PARAM_NAME" == "state" ]; then
echo "${params[0]}"
exit 0
fi
for element in "${params[@]}"; do
element_name="$(echo "$element" | cut -d"=" -f 1)"
if [ "$element_name" == "$PARAM_NAME" ]; then
if echo "$element" | grep -q "="; then
element_value="$(echo "$element" | cut -d"=" -f 2-)"
echo "$element_value"
else
echo ""
fi
exit 0
fi
done
exit 1
}

#
# Parse parameters from the HTTP request
#
if [ ! -z "${HTTP_REQ_URI_PATH}" ]; then
OPT_HTTP_STATUS=1
fi
if echo ${HTTP_REQ_URI_PATH} | grep -qi "health-value"; then
OPT_HTTP_STATUS=1
OPT_HEALTH_VALUE=1
Expand Down Expand Up @@ -341,7 +377,7 @@ decrease_health_value
# display health value response, and exit
display_health_value

# send a http_response of 200
# send a http_response of 200, and exit
http_response 200 "Success"

# End of program

0 comments on commit 0cc9aeb

Please sign in to comment.