Webhooks raising exception in v2.7.1 #3181

Closed
opened 2025-12-29 18:26:24 +01:00 by adam · 1 comment
Owner

Originally created by @candlerb on GitHub (Jan 17, 2020).

A previously-working webhook has stopped working in 2.7

Environment

  • Python version: 3.5.2
  • NetBox version: 2.7.1

Steps to Reproduce

  1. Running webhook - mine is to netbox-webhook-dnsupdate
  2. Change something which should trigger the webhook
  3. Check backend status at /admin/webhook-backend-status/
  4. Click on the "Failed Jobs" number

Expected Behavior

Webhook to work as before

Observed Behavior

Shown in web interface backend status for the job:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/rq/worker.py", line 812, in perform_job
    rv = job.perform()
  File "/usr/local/lib/python3.5/dist-packages/rq/job.py", line 588, in perform
    self._result = self._execute()
  File "/usr/local/lib/python3.5/dist-packages/rq/job.py", line 594, in _execute
    return self.func(*self.args, **self.kwargs)
  File "/opt/netbox/netbox/extras/webhooks_worker.py", line 49, in process_webhook
    msg=prepared_request.body.encode('utf8'),
AttributeError: 'NoneType' object has no attribute 'encode'
Originally created by @candlerb on GitHub (Jan 17, 2020). A previously-working webhook has stopped working in 2.7 ### Environment * Python version: 3.5.2 * NetBox version: 2.7.1 ### Steps to Reproduce 1. Running webhook - mine is to [netbox-webhook-dnsupdate](https://github.com/candlerb/netbox-webhook-dnsupdate) 2. Change something which should trigger the webhook 3. Check backend status at `/admin/webhook-backend-status/` 4. Click on the "Failed Jobs" number ### Expected Behavior Webhook to work as before ### Observed Behavior Shown in web interface backend status for the job: ``` Traceback (most recent call last): File "/usr/local/lib/python3.5/dist-packages/rq/worker.py", line 812, in perform_job rv = job.perform() File "/usr/local/lib/python3.5/dist-packages/rq/job.py", line 588, in perform self._result = self._execute() File "/usr/local/lib/python3.5/dist-packages/rq/job.py", line 594, in _execute return self.func(*self.args, **self.kwargs) File "/opt/netbox/netbox/extras/webhooks_worker.py", line 49, in process_webhook msg=prepared_request.body.encode('utf8'), AttributeError: 'NoneType' object has no attribute 'encode' ```
adam added the type: bugstatus: accepted labels 2025-12-29 18:26:24 +01:00
adam closed this issue 2025-12-29 18:26:24 +01:00
Author
Owner

@candlerb commented on GitHub (Jan 17, 2020):

If you make this patch:

--- /opt/netbox/netbox/extras/webhooks_worker.py.orig	2020-01-17 09:06:49.290100942 +0000
+++ /opt/netbox/netbox/extras/webhooks_worker.py	2020-01-17 14:38:50.299963724 +0000
@@ -39,6 +39,8 @@
         params.update({'data': json.dumps(payload, cls=JSONEncoder)})
     elif webhook.http_content_type == WEBHOOK_CT_X_WWW_FORM_ENCODED:
         params.update({'data': payload})
+    else:
+        raise RuntimeError("Boom")

     prepared_request = requests.Request(**params).prepare()

Then the exception changes to "Boom".

In the database I have:

netbox=# select name,http_content_type from extras_webhook;
   name    | http_content_type
-----------+-------------------
 dnsupdate | application/json
(1 row)

(and the web interface displays it as "JSON" in the drop-down)

This seems to fix it:

--- /opt/netbox/netbox/extras/webhooks_worker.py.orig	2020-01-17 09:06:49.290100942 +0000
+++ /opt/netbox/netbox/extras/webhooks_worker.py	2020-01-17 14:48:00.065982061 +0000
@@ -6,8 +6,7 @@
 from django_rq import job
 from rest_framework.utils.encoders import JSONEncoder

-from .choices import ObjectChangeActionChoices
-from .constants import *
+from .choices import ObjectChangeActionChoices, WebhookContentTypeChoices


 @job('default')
@@ -35,10 +34,12 @@
         'headers': headers
     }

-    if webhook.http_content_type == WEBHOOK_CT_JSON:
+    if webhook.http_content_type == WebhookContentTypeChoices.CONTENTTYPE_JSON:
         params.update({'data': json.dumps(payload, cls=JSONEncoder)})
-    elif webhook.http_content_type == WEBHOOK_CT_X_WWW_FORM_ENCODED:
+    elif webhook.http_content_type == WebhookContentTypeChoices.CONTENTTYPE_FORMDATA:
         params.update({'data': payload})
+    else:
+        raise RuntimeError("Boom")

     prepared_request = requests.Request(**params).prepare()

I'm somewhat fazed as to why the non-existent constants WEBHOOK_CT_JSON and WEBHOOK_CT_X_WWW_FORM_ENCODED didn't raise an exception in the first place. I had restarted Netbox after the upgrade - ah, but I didn't restart rqworker. I am guessing that when I added raise RuntimeError("Boom") it re-imported the source module automatically, but kept the old constants.

@candlerb commented on GitHub (Jan 17, 2020): If you make this patch: ``` --- /opt/netbox/netbox/extras/webhooks_worker.py.orig 2020-01-17 09:06:49.290100942 +0000 +++ /opt/netbox/netbox/extras/webhooks_worker.py 2020-01-17 14:38:50.299963724 +0000 @@ -39,6 +39,8 @@ params.update({'data': json.dumps(payload, cls=JSONEncoder)}) elif webhook.http_content_type == WEBHOOK_CT_X_WWW_FORM_ENCODED: params.update({'data': payload}) + else: + raise RuntimeError("Boom") prepared_request = requests.Request(**params).prepare() ``` Then the exception changes to "Boom". In the database I have: ``` netbox=# select name,http_content_type from extras_webhook; name | http_content_type -----------+------------------- dnsupdate | application/json (1 row) ``` (and the web interface displays it as "JSON" in the drop-down) This seems to fix it: ``` --- /opt/netbox/netbox/extras/webhooks_worker.py.orig 2020-01-17 09:06:49.290100942 +0000 +++ /opt/netbox/netbox/extras/webhooks_worker.py 2020-01-17 14:48:00.065982061 +0000 @@ -6,8 +6,7 @@ from django_rq import job from rest_framework.utils.encoders import JSONEncoder -from .choices import ObjectChangeActionChoices -from .constants import * +from .choices import ObjectChangeActionChoices, WebhookContentTypeChoices @job('default') @@ -35,10 +34,12 @@ 'headers': headers } - if webhook.http_content_type == WEBHOOK_CT_JSON: + if webhook.http_content_type == WebhookContentTypeChoices.CONTENTTYPE_JSON: params.update({'data': json.dumps(payload, cls=JSONEncoder)}) - elif webhook.http_content_type == WEBHOOK_CT_X_WWW_FORM_ENCODED: + elif webhook.http_content_type == WebhookContentTypeChoices.CONTENTTYPE_FORMDATA: params.update({'data': payload}) + else: + raise RuntimeError("Boom") prepared_request = requests.Request(**params).prepare() ``` I'm somewhat fazed as to why the non-existent constants `WEBHOOK_CT_JSON` and `WEBHOOK_CT_X_WWW_FORM_ENCODED` didn't raise an exception in the first place. I had restarted Netbox after the upgrade - ah, but I didn't restart rqworker. I am guessing that when I added `raise RuntimeError("Boom")` it re-imported the source module automatically, but kept the old constants.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#3181