diff --git a/frappe/integrations/doctype/webhook/test_webhook.py b/frappe/integrations/doctype/webhook/test_webhook.py index 8284db7fd3..7235447662 100644 --- a/frappe/integrations/doctype/webhook/test_webhook.py +++ b/frappe/integrations/doctype/webhook/test_webhook.py @@ -206,3 +206,59 @@ class TestWebhook(FrappeTestCase): enqueue_webhook(doc, wh) log = frappe.get_last_doc("Webhook Request Log") self.assertEqual(len(json.loads(log.response)["json"]), 3) + + def test_webhook_with_dynamic_url_enabled(self): + wh_config = { + "doctype": "Webhook", + "webhook_doctype": "Note", + "webhook_docevent": "after_insert", + "enabled": 1, + "request_url": "https://httpbin.org/anything/{{ doc.doctype }}", + "is_dynamic_url": 1, + "request_method": "POST", + "request_structure": "JSON", + "webhook_json": "{}", + "meets_condition": "Yes", + "webhook_headers": [ + { + "key": "Content-Type", + "value": "application/json", + } + ], + } + + with get_test_webhook(wh_config) as wh: + doc = frappe.new_doc("Note") + doc.title = "Test Webhook Note" + enqueue_webhook(doc, wh) + log = frappe.get_last_doc("Webhook Request Log") + self.assertEqual(json.loads(log.response)["url"], "https://httpbin.org/anything/Note") + + def test_webhook_with_dynamic_url_disabled(self): + wh_config = { + "doctype": "Webhook", + "webhook_doctype": "Note", + "webhook_docevent": "after_insert", + "enabled": 1, + "request_url": "https://httpbin.org/anything/{{doc.doctype}}", + "is_dynamic_url": 0, + "request_method": "POST", + "request_structure": "JSON", + "webhook_json": "{}", + "meets_condition": "Yes", + "webhook_headers": [ + { + "key": "Content-Type", + "value": "application/json", + } + ], + } + + with get_test_webhook(wh_config) as wh: + doc = frappe.new_doc("Note") + doc.title = "Test Webhook Note" + enqueue_webhook(doc, wh) + log = frappe.get_last_doc("Webhook Request Log") + self.assertEqual( + json.loads(log.response)["url"], "https://httpbin.org/anything/{{doc.doctype}}" + ) diff --git a/frappe/integrations/doctype/webhook/webhook.json b/frappe/integrations/doctype/webhook/webhook.json index c4fc4f675d..cfb2a2e01c 100644 --- a/frappe/integrations/doctype/webhook/webhook.json +++ b/frappe/integrations/doctype/webhook/webhook.json @@ -18,8 +18,9 @@ "html_condition", "sb_webhook", "request_url", - "request_method", + "is_dynamic_url", "cb_webhook", + "request_method", "request_structure", "sb_security", "enable_security", @@ -202,6 +203,13 @@ { "fieldname": "section_break_28", "fieldtype": "Section Break" + }, + { + "default": "0", + "description": "On checking this option, URL will be treated like a jinja template string", + "fieldname": "is_dynamic_url", + "fieldtype": "Check", + "label": "Is Dynamic URL?" } ], "links": [ @@ -210,7 +218,7 @@ "link_fieldname": "webhook" } ], - "modified": "2023-05-21 15:42:58.844826", + "modified": "2023-05-22 16:30:10.740512", "modified_by": "Administrator", "module": "Integrations", "name": "Webhook", diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py index 7d168c659f..1b56a1b129 100644 --- a/frappe/integrations/doctype/webhook/webhook.py +++ b/frappe/integrations/doctype/webhook/webhook.py @@ -115,29 +115,34 @@ def enqueue_webhook(doc, webhook) -> None: webhook: Webhook = frappe.get_doc("Webhook", webhook.get("name")) headers = get_webhook_headers(doc, webhook) data = get_webhook_data(doc, webhook) - r = None + if webhook.is_dynamic_url: + request_url = frappe.render_template(webhook.request_url, get_context(doc)) + else: + request_url = webhook.request_url + + r = None for i in range(3): try: r = requests.request( method=webhook.request_method, - url=webhook.request_url, + url=request_url, data=json.dumps(data, default=str), headers=headers, timeout=5, ) r.raise_for_status() frappe.logger().debug({"webhook_success": r.text}) - log_request(webhook.name, doc.name, webhook.request_url, headers, data, r) + log_request(webhook.name, doc.name, request_url, headers, data, r) break except requests.exceptions.ReadTimeout as e: frappe.logger().debug({"webhook_error": e, "try": i + 1}) - log_request(webhook.name, doc.name, webhook.request_url, headers, data) + log_request(webhook.name, doc.name, request_url, headers, data) except Exception as e: frappe.logger().debug({"webhook_error": e, "try": i + 1}) - log_request(webhook.name, doc.name, webhook.request_url, headers, data, r) + log_request(webhook.name, doc.name, request_url, headers, data, r) sleep(3 * i + 1) if i != 2: continue