webhooks_worker.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import hashlib
  2. import hmac
  3. import json
  4. import requests
  5. from django_rq import job
  6. from rest_framework.utils.encoders import JSONEncoder
  7. from .constants import *
  8. @job('default')
  9. def process_webhook(webhook, data, model_name, event, timestamp, username, request_id):
  10. """
  11. Make a POST request to the defined Webhook
  12. """
  13. payload = {
  14. 'event': dict(OBJECTCHANGE_ACTION_CHOICES)[event].lower(),
  15. 'timestamp': timestamp,
  16. 'model': model_name,
  17. 'username': username,
  18. 'request_id': request_id,
  19. 'data': data
  20. }
  21. headers = {
  22. 'Content-Type': webhook.get_http_content_type_display(),
  23. }
  24. params = {
  25. 'method': 'POST',
  26. 'url': webhook.payload_url,
  27. 'headers': headers
  28. }
  29. if webhook.http_content_type == WEBHOOK_CT_JSON:
  30. params.update({'data': json.dumps(payload, cls=JSONEncoder)})
  31. elif webhook.http_content_type == WEBHOOK_CT_X_WWW_FORM_ENCODED:
  32. params.update({'data': payload})
  33. prepared_request = requests.Request(**params).prepare()
  34. if webhook.secret != '':
  35. # Sign the request with a hash of the secret key and its content.
  36. hmac_prep = hmac.new(
  37. key=webhook.secret.encode('utf8'),
  38. msg=prepared_request.body.encode('utf8'),
  39. digestmod=hashlib.sha512
  40. )
  41. prepared_request.headers['X-Hook-Signature'] = hmac_prep.hexdigest()
  42. with requests.Session() as session:
  43. session.verify = webhook.ssl_verification
  44. if webhook.ca_file_path:
  45. session.verify = webhook.ca_file_path
  46. response = session.send(prepared_request)
  47. if response.status_code >= 200 and response.status_code <= 299:
  48. return 'Status {} returned, webhook successfully processed.'.format(response.status_code)
  49. else:
  50. raise requests.exceptions.RequestException(
  51. "Status {} returned, webhook FAILED to process.".format(response.status_code)
  52. )