- You want to run some code in response to a webhook, like a github push.
- You have some code on your Raspberry Pi that you want to run from work (great in combination with ngrok).
- That's pretty much it.
Hapttic listens for incoming HTTP connections. When it receives a connection, it dumps all relevant data (headers, path, parameters, the body and other stuff) into a JSON object and calls a bash script with this object as its parameters.
The basic idea is pretty similar. The main advantage of hapttic is ease of setup with a simple Docker image that lets you quickly connect a shell script to a http endpoint.
docker run --rm -p 8080:8080 --name hapttic timonych/hapttic:v2.0.0
cat <<EOF > ~/shellScript.sh
#!/bin/sh
echo \$1
EOF
Then run the following command to spin up the docker container that runs hapttic:
docker run --rm -p 8080:8080 -v ~/shellScript.sh:/usr/src/app/shellScript.sh --name hapttic timonych/hapttic:v2.0.0 -script "./shellScript.sh"
curl http://localhost:8080 -d '{"key" : "value"}'
cat <<EOF > ~/hapttic-config.yml
bind: 0.0.0.0
port: 8080
error: false
scripts:
# rootPath: scriptPath (Relative Path according to hapttic Path)
# rootPath should start with /. If not prefix / will be addedd automaticaly
script1: ./shellScripts/script1.sh
/script2: ./shellScripts/script2.sh
EOF
mkdir -p ~/shellScripts
cat <<EOF > ~/shellScripts/script1.sh
#!/bin/sh
echo "This is $(basename \$0)"
echo \$1 2>&1
EOF
cat <<EOF > ~/shellScripts/script2.sh
#!/bin/sh
echo "This is $(basename \$0)"
echo \$1 2>&1
EOF
Then run the following command to spin up the docker container that runs hapttic:
docker run --rm -p 8080:8080 -v ~/shellScripts:/usr/app/shellScripts -v ~/hapttic-config.yml:/config.yml --name hapttic timonych/hapttic:v2.0.0 -config "/config.yml"
curl http://localhost:8080/script1 -d '{"key1" : "value1"}'
curl http://localhost:8080/script2 -d '{"key2" : "value2"}'
REQUEST=$1
SECRET_TOKEN=$(jq -r '.Header."X-My-Secret"[0]' <(echo $REQUEST))
if [[ "$SECRET_TOKEN" != "SECRET" ]]; then
echo "Incorrect secret token"
exit -1
fi
curl https://www.example.com/api/call/in/response/to/webhook
This request handling script can be run with curl -H "X-My-Secret: SECRET" http://localhost:8080
The jsoendermann/hapttic
Dockerfile includes jq
and curl
, if you need any other command in your request handling script, you should create your own image.
The JSON object your request handling script gets called with is a subset of Go's http.Request
. It's defined in hapttic.go as marshallableRequest
. For documentation on http.Request, see the official net/http page.
You can add encryption by putting an nginx proxy in front of it with a docker-compose file like so:
version: '3'
volumes:
vhost:
html:
services:
nginx-proxy:
restart: always
image: jwilder/nginx-proxy
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /var/certs:/etc/nginx/certs:ro
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
letsencrypt-nginx-proxy-companion:
restart: always
image: jrcs/letsencrypt-nginx-proxy-companion
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /var/certs:/etc/nginx/certs:rw
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
hapttic:
restart: always
image: jsoendermann/hapttic
environment:
- VIRTUAL_HOST=hapttic.your.domain.com # Replace this
- LETSENCRYPT_HOST=hapttic.your.domain.com # Replace this
- LETSENCRYPT_EMAIL=your@email.address # Replace this
volumes:
- /my-request-handler.sh:/hapttic_request_handler.sh # Replace this
command: ["-file", "/hapttic_request_handler.sh"]
depends_on:
- nginx-proxy
- letsencrypt-nginx-proxy-companion