Skip to content

Commit

Permalink
docs(prism-agent): add basic webhook code snippet (#589)
Browse files Browse the repository at this point in the history
* fix(prism-agent): correctly format bearer token in Authorization header (add 'Bearer' prefix)

* docs(prism-agent): add Python code snippet for basic webhook logging incoming requests

* chore(prism-agent): log events in webhook publisher at 'debug' level
  • Loading branch information
bvoiturier authored Jul 13, 2023
1 parent 5661f8c commit cf207fc
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
93 changes: 93 additions & 0 deletions docs/docusaurus/webhooks/webhook.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,99 @@ attempt. Please note that the number of retries and the interval duration are cu
By default, this retry mechanism provides a reasonable level of reliability for delivering webhook notifications,
allowing for temporary network issues or intermittent failures.

### A basic Webhook implementation for logging requests

In the following example, we will demonstrate a simple Python code snippet that sets up a webhook endpoint and logs
incoming HTTP requests to the console. This basic implementation can serve as a starting point for building more
advanced webhook systems.

In the provided Python code snippet, the port on which the webhook listener will listen for incoming requests should be
passed as a command-line parameter. This allows flexibility in starting multiple webhooks in parallel, which is useful
when testing multiple locally running agents, e.g. for a holder, an issuer, and/or a verifier.

```python
#!/usr/bin/env python3
"""
Very simple HTTP server in python for logging requests
Usage::
./server.py [<port>]
"""
import logging
import json
from http.server import BaseHTTPRequestHandler, HTTPServer

grey = "\x1b[38;20m"
yellow = "\x1b[33;20m"
green = "\x1b[32;20m"
red = "\x1b[31;20m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"

consoleHandler = logging.StreamHandler()
formatter = logging.Formatter(f"""%(asctime)s - %(levelname)s - %(name)s
--------------------------------------- request ---------------------------------------
{green}%(method)s %(path)s{reset}
%(headers)s
{yellow}%(data)s{reset}
-----------------------------------
"""
)
consoleHandler.setFormatter(formatter)
consoleHandler.setLevel(logging.INFO)

logger = logging.getLogger('http-request')
logger.setLevel(logging.INFO)
logger.addHandler(consoleHandler)

class S(BaseHTTPRequestHandler):

def _set_response(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()

def do_GET(self):
logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers))
self._set_response()
self.wfile.write("GET request for {}".format(self.path).encode('utf-8'))

def do_POST(self):
content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
post_data = self.rfile.read(content_length) # <--- Gets the data itself
json_obj = json.loads(post_data.decode('utf-8'))
json_data = json.dumps(json_obj, indent=2)
logger.info(msg="Request content", extra={
'method': "POST",
'path': str(self.path),
'headers': str(self.headers),
'data': json_data
})
self._set_response()
self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))

def log_message(self, format, *args):
pass


def run(server_class=HTTPServer, handler_class=S, port=80):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()


if __name__ == '__main__':
from sys import argv

if len(argv) == 2:
run(port=int(argv[1]))
else:
run()
```

## Conclusion

Congratulations! You've learned about webhook notifications in PRISM Agent. By leveraging this feature, you can receive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class WebhookPublisher(appConfig: AppConfig, notificationService: EventNotificat

private val config = appConfig.agent.webhookPublisher
private val baseHeaders =
config.apiKey.map(key => Headers.authorization(key)).getOrElse(Headers.empty) ++
config.apiKey.map(key => Headers.bearerAuthorizationHeader(key)).getOrElse(Headers.empty) ++
Headers.contentType(HeaderValues.applicationJson)

private val parallelism = config.parallelism match {
Expand Down Expand Up @@ -68,7 +68,7 @@ class WebhookPublisher(appConfig: AppConfig, notificationService: EventNotificat
encoder: JsonEncoder[A]
): ZIO[Client, UnexpectedError, Unit] = {
for {
_ <- ZIO.log(s"Sending event: $event to HTTP webhook URL: $url.")
_ <- ZIO.logDebug(s"Sending event: $event to HTTP webhook URL: $url.")
response <- Client
.request(
url = url.toString,
Expand Down

0 comments on commit cf207fc

Please sign in to comment.