webhooks_worker.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  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 extras.constants import WEBHOOK_CT_JSON, WEBHOOK_CT_X_WWW_FORM_ENCODED, OBJECTCHANGE_ACTION_CHOICES
  8. @job('default')
  9. def process_webhook(webhook, data, model_class, event, timestamp):
  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_class._meta.model_name,
  17. 'data': data
  18. }
  19. headers = {
  20. 'Content-Type': webhook.get_http_content_type_display(),
  21. }
  22. params = {
  23. 'method': 'POST',
  24. 'url': webhook.payload_url,
  25. 'headers': headers
  26. }
  27. if webhook.http_content_type == WEBHOOK_CT_JSON:
  28. params.update({'data': json.dumps(payload, cls=JSONEncoder)})
  29. elif webhook.http_content_type == WEBHOOK_CT_X_WWW_FORM_ENCODED:
  30. params.update({'data': payload})
  31. prepared_request = requests.Request(**params).prepare()
  32. if webhook.secret != '':
  33. # Sign the request with a hash of the secret key and its content.
  34. hmac_prep = hmac.new(
  35. key=webhook.secret.encode('utf8'),
  36. msg=prepared_request.body.encode('utf8'),
  37. digestmod=hashlib.sha512
  38. )
  39. prepared_request.headers['X-Hook-Signature'] = hmac_prep.hexdigest()
  40. with requests.Session() as session:
  41. session.verify = webhook.ssl_verification
  42. response = session.send(prepared_request)
  43. if response.status_code >= 200 and response.status_code <= 299:
  44. return 'Status {} returned, webhook successfully processed.'.format(response.status_code)
  45. else:
  46. raise requests.exceptions.RequestException(
  47. "Status {} returned, webhook FAILED to process.".format(response.status_code)
  48. )