-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Craig
committed
Apr 19, 2021
1 parent
7fc4e5c
commit b1ae366
Showing
24 changed files
with
648 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
.git/ | ||
.gitignore | ||
.idea/ | ||
.DS_Store/ | ||
*venv*/ | ||
.env | ||
*.iml | ||
*.md | ||
.coverage | ||
__pycache__/ | ||
*.py[cod] | ||
.Python | ||
*.egg-info/ | ||
*.egg | ||
build/ | ||
dist/ | ||
static/ | ||
docker-compose.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,129 +1,33 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
# IDE stuff | ||
.idea/ | ||
*.iml | ||
|
||
# because macs | ||
*.DS_Store | ||
|
||
# C extensions | ||
*.so | ||
# environments | ||
*venv*/ | ||
.tox/ | ||
*.pid | ||
.env | ||
|
||
# Distribution / packaging | ||
# python stuff | ||
__pycache__/ | ||
*.py[cod] | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
pip-wheel-metadata/ | ||
share/python-wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.py,cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
build/ | ||
dist/ | ||
|
||
# Django stuff: | ||
# Django stuff | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
local_*.yaml | ||
/configs/local*.yaml | ||
static/ | ||
media/ | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
|
||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||
__pypackages__/ | ||
|
||
# Celery stuff | ||
celerybeat-schedule | ||
celerybeat.pid | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ | ||
# pytest | ||
.pytest_cache/ | ||
.coverage | ||
pytest.ini |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Changelog | ||
|
||
|
||
## [1.0.0-beta] - 19/04/2021 | ||
- Initial working release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
FROM tecktron/python-bjoern:latest | ||
ARG DEBIAN_FRONTEND=noninteractive | ||
RUN apt-get clean && apt-get update && \ | ||
apt-get -y install --no-install-recommends \ | ||
apt-utils \ | ||
build-essential \ | ||
libpq-dev \ | ||
postgresql-client \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
ENV MODULE_NAME=webhook_catchall.wsgi | ||
|
||
COPY . /app | ||
RUN chmod +x /app/prestart.sh | ||
WORKDIR /app/ | ||
|
||
RUN python -m pip install pip --no-cache-dir --upgrade | ||
RUN pip install -r /app/requirements.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,101 @@ | ||
# webhook-catchall | ||
Generic HTTP service based in Django designed to catch webhooks for testing | ||
# Webhook Catchall | ||
A simple HTTP service based on Django that was built to catch and show webhook data in a testing environment. | ||
Includes a Django admin page what shows the url that was hit, and the data that was received. | ||
|
||
**THIS IS FOR DEVELOPMENT PURPOSES ONLY IT IS NOT RECOMMENDED FOR PRODUCTION USE** | ||
|
||
## Requirements | ||
- A Postgres Database. | ||
- Python 3.8+ or Docker | ||
|
||
## Installation | ||
|
||
There are 2 ways to use this: | ||
1. Use the Docker image (easiest) | ||
2. Run this as a local Python service using the built in Django server | ||
|
||
### Docker Service | ||
The latest docker image is available at my docker hub. [You can find it here]() | ||
|
||
#### Options | ||
The image provides options to change the database settings via environment variables | ||
so that you can adjust to fit your system. The variables are: | ||
- `DB_NAME`: The name of the database (e.g., `webhook_catchall`) | ||
- `DB_USER`: The username of the database (e.g., `postgres`) | ||
- `DB_PASS`: The password of the database (e.g., `postgres`) | ||
- `DB_HOST`: The host of the database (e.g., `127.0.0.1`) | ||
- `DB_PORT`: The port of the database (e.g., `5432`) | ||
|
||
You can also change the default admin username and password as well. To do so simply pass in the | ||
environment params of `ADMIN_USER` and `ADMIN_PASS` (defaults to `admin`:`admin`) | ||
|
||
##### Demo docker-compose.yml | ||
Included in the project is an example `docker-compose.yml` that will bring up the project | ||
with a postgres database and have it running on port 8181. You can then simply point your | ||
webhooks to `http://localhost:8181/`, and your browser to `http://localhost:8181/admin/` to login | ||
with the default admin to see what was captured. | ||
|
||
|
||
### Local Django server | ||
You can of course run this locally using Django's build in test server. Please don't | ||
forget to update parameters here with those of your system and choosing. | ||
|
||
1. Clone this repo. | ||
2. Create a local Python virtual environment and activate it (e.g., `python -m venv ./.venv && source ./.venv/bin/activate`) | ||
3. Install the requirements using pip (e.g., `pip install -r requirements.txt`) | ||
4. Create a file called `.env` in the project root (this file is git ignored FYI) | ||
5. Copy this code block and replace it with the settings from your database setup: | ||
```bash | ||
DB_NAME=webhook_catchall | ||
DB_USER=postgres | ||
DB_PASS=postgres | ||
DB_HOST=127.0.0.1 | ||
DB_PORT=5432 | ||
``` | ||
6. Run the Django migrations: `python manage.py migrate` | ||
7. Run Django's static collection: `python manage.py collectstatic` | ||
8. Run the `create_default_superuser` management command to create the admin user: | ||
`python manage.py create_default_superuser --username="admin" --password="admin"` | ||
9. Run the Django testserver: `python manage.py testserver 127.0.0.2:8181` to start the server. | ||
10. Open your browser to `http://localhost:8181/admin/` and login to the admin. | ||
## Usage | ||
Once you have the service up and running, it will support receiving data from any HTTP method on | ||
any path (except those being with `/admin/` or `/static/`). The system will dump all data into a | ||
`TEXT` field and additionally attempts to store the incoming data that has the `Content-Type` | ||
header of `application/json` into a JSON field for easy viewing. It also will keep track of the | ||
method used, the time the webhook was received, the incoming path, any query parameters as well as | ||
any headers in the request. The service will always save the data no matter what and return a 204 | ||
response (no content) unless it fails to decode the json, in which case it will return a 400 | ||
instead with the error from the json decoder and the data only stored in the `TEXT` field. | ||
### Example: | ||
`curl -X POST http://127.0.0.1:8181/foo/bar?process=webhook -H "Content-Type: application/json" -d "{\"test\":{\"data\": \"nested\"}}"` | ||
You can login to the Django Admin and see all the details of the call. The view of the data in the | ||
admin is read-only. | ||
## Help and support | ||
If you need help or find a bug or would like to ask for a feature (you could build it, see | ||
contributing below). Please first search to see if the issue exists on the github page. If not, | ||
please open a new ticket and explain in as much detail as possible how to recreate the issue or | ||
what feature you'd like to see. | ||
|
||
## Contributing and development | ||
This is an opensource project, contributions are welcome. Please follow the guidelines to | ||
contribute to this project. | ||
|
||
### Setup | ||
1. Use `pip` to install the additional `dev-requirements.txt`. | ||
|
||
### Coding standards | ||
Before submitting any code please be sure you have done the following: | ||
- Run coding stands tools, these are isort, black and flake8. They should all pass. | ||
- Run tox and check all tests have passed and that your code coverage is 95% or above. | ||
|
||
### Testing | ||
Every bit of code you submit must be fully tested. | ||
All testing is done using pytest, please follow pytest style testing (not unittest). | ||
You can simply use tox to run the tests: `tox -e py39`. This supports environments | ||
`py36` - `py39`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
1.0.0-beta |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
pip | ||
tox | ||
tox-pip-extensions | ||
isort | ||
flake8 | ||
factory-boy | ||
pytest | ||
pytest-django | ||
pytest-cov | ||
pytest-mock | ||
pytest-xdist | ||
freezegun | ||
black | ||
django-coverage-plugin | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
version: "3.4" | ||
services: | ||
db: | ||
image: postgres | ||
environment: | ||
- POSTGRES_DB=postgres | ||
- POSTGRES_USER=postgres | ||
- POSTGRES_PASSWORD=postgres | ||
|
||
django: | ||
build: . | ||
environment: | ||
- DB_NAME=webhook_catchall | ||
- DB_USER=postgres | ||
- DB_PASS=postgres | ||
- DB_HOST=db | ||
- DB_PORT=5432 | ||
ports: | ||
- "8181:80" | ||
links: | ||
- db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/usr/bin/env python | ||
"""Django's command-line utility for administrative tasks.""" | ||
import os | ||
import sys | ||
|
||
|
||
def main(): | ||
"""Run administrative tasks.""" | ||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webhook_catchall.settings") | ||
try: | ||
from django.core.management import execute_from_command_line | ||
except ImportError as exc: | ||
raise ImportError( | ||
"Couldn't import Django. Are you sure it's installed and " | ||
"available on your PYTHONPATH environment variable? Did you " | ||
"forget to activate a virtual environment?" | ||
) from exc | ||
execute_from_command_line(sys.argv) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#!/bin/sh | ||
# Borrowed from https://docs.docker.com/compose/startup-order/ | ||
# wait-for-postgres.sh | ||
|
||
x=0 | ||
PGCONNECT=postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/postgres | ||
printenv | ||
echo $PGCONNECT | ||
until psql $PGCONNECT -c '\q'; do | ||
if [ $x -gt 10 ]; then | ||
echo "Cannot find postgres, aborting" | ||
exit 8 | ||
fi | ||
echo "Postgres is unavailable - sleeping..." | ||
sleep 3 | ||
x=$(($x+1)) | ||
done | ||
|
||
echo "Postgres is up!" | ||
cd /app || exit 1 | ||
psql ${PGCONNECT} -tc "SELECT 1 FROM pg_database WHERE datname = '${DB_NAME}'" | grep -q 1 || psql ${PGCONNECT} -c "CREATE DATABASE \"${DB_NAME}\" WITH OWNER '${DB_USER}'" | ||
|
||
ADMIN_USER=${ADMIN_USER:-"admin"} | ||
ADMIN_PASS=${ADMIN_PASS:-"admin"} | ||
|
||
echo "Running migrations" | ||
python manage.py migrate | ||
echo "Creating default user" | ||
python manage.py create_default_superuser --username="${ADMIN_USER}" --password="${ADMIN_PASS}" | ||
echo "collecting static" | ||
mkdir -p /app/static | ||
python manage.py collectstatic --no-input |
Oops, something went wrong.