Metadata-Version: 2.1
Name: webhook-utils
Version: 0.3.2
Summary: Short, well documented utilities for interacting with webhooks.
Home-page: https://github.com/tizz98/webhook-utils
License: MIT
Keywords: webhook,utils,utilities,webhooks
Author: Elijah Wilson
Author-email: dev.tizz98@gmail.com
Requires-Python: >=3.8,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Provides-Extra: examples
Provides-Extra: fastapi
Provides-Extra: httpx
Requires-Dist: fastapi (>=0.70.1,<0.71.0); extra == "fastapi" or extra == "examples"
Requires-Dist: httpx (>=0.21.1,<0.22.0); extra == "httpx" or extra == "examples"
Requires-Dist: requests (>=2.26.0,<3.0.0); extra == "fastapi"
Requires-Dist: rich (>=10.16.1,<11.0.0); extra == "examples"
Requires-Dist: uvicorn[standard] (>=0.16.0,<0.17.0); extra == "examples"
Project-URL: Repository, https://github.com/tizz98/webhook-utils
Description-Content-Type: text/markdown

# Webhook Utils

A set of utilities for interacting with [webhooks](https://webhooks.dev).

[![Test Webhook Utils](https://github.com/tizz98/webhook-utils/actions/workflows/main.yaml/badge.svg?branch=main)](https://github.com/tizz98/webhook-utils/actions/workflows/main.yaml)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/tizz98/py-paas/tree/main/LICENSE)
[![codecov](https://codecov.io/gh/tizz98/webhook-utils/branch/main/graph/badge.svg?token=HYT07K0ZHQ)](https://codecov.io/gh/tizz98/webhook-utils)
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/webhook-utils.svg)](https://pypi.python.org/pypi/webhook-utils/)

[Installation](#installation) | [Usage](#usage) | [HTTPX](#httpx) | [FastAPI](#fastapi) | [Contributing](CONTRIBUTING.md) | [End-to-End Examples](./examples/README.md)

## Installation

```shell
pip install webhook-utils
```

## Usage

### Crypto

Available hash algorithms for all methods are:
- `md5` (not recommended)
- `sha1`
- `sha256` (recommended)

Learn more about HMAC signatures [here](https://webhooks.dev/docs/auth/#hmac).

#### Generating HMAC signatures

Bare usage:
```python
from webhook_utils.crypto import generate_sha256_signature

print(generate_sha256_signature(b'secret-key', b'some-message'))
```

#### Comparing HMAC signatures

Bare usage:
```python
from webhook_utils.crypto import compare_sha256_signature

is_valid_signature = compare_sha256_signature(
    b'secret-key',
    b'some-message',
    'expected-signature',
)
if not is_valid_signature:
    raise ValueError('Invalid signature')
```

### Httpx

`webhook-utils` has a built-in `httpx.Auth` class that can be used to
automatically sign requests made with an `httpx.Client`.

An `X-Webhook-Signature` header will be added to all `POST` requests.
The signature will be generated using the `webhook_key` and the
provided signature method (defaults to `sha256`).

The header, signature, and http methods can be customized by passing
the `header_name`, `gen_signature_method`, and `methods` keyword arguments.

```shell
pip install webhook-utils[httpx]
```

```python
import httpx
from webhook_utils.contrib.httpx_auth import WebhookAuth
from webhook_utils.crypto import generate_sha1_signature

# Basic usage
auth = WebhookAuth("secret-key")
client = httpx.Client(auth=auth)


# Customized usage
auth = WebhookAuth(
    "secret-key",
    header_name="My-Webhook-Signature",
    gen_signature_method=generate_sha1_signature,
    methods={"POST", "PUT"},
)
client = httpx.Client(auth=auth)
client.post("https://example.com/webhook", json={"foo": "bar"})
```

### FastAPI

`webhook-utils` has a built-in `WebhookRouter` class that can be used to
wrap a `fastapi.APIRouter` to automatically verify incoming request signatures.

```shell
pip install webhook-utils[fastapi]
```

```python
from fastapi import FastAPI, APIRouter
from webhook_utils.contrib.fastapi import WebhookRouter

app = FastAPI()
webhook_router = WebhookRouter(
    APIRouter(prefix="/webhooks"),
    webhook_key="secret",
)


@webhook_router.on("/demo-webhook")
def demo_event_handler():
    return {"status": "ok"}


app.include_router(webhook_router.api_router)
```

## Publishing to PYPI

```shell
poetry build
# Verify that everything looks correct on test.pypi.org
poetry publish -r testpypi
poetry publish
```

