From 2e86ed58ecbdcda7fe2e429bb2307abef16c75a5 Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Mon, 26 Aug 2019 15:09:17 +0530 Subject: [PATCH] feat: allow forming JSON requests in webhook --- .../integrations/doctype/webhook/webhook.js | 28 +++++++++++++++++++ .../integrations/doctype/webhook/webhook.json | 24 ++++++++++++++-- .../integrations/doctype/webhook/webhook.py | 24 ++++++++++++---- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/frappe/integrations/doctype/webhook/webhook.js b/frappe/integrations/doctype/webhook/webhook.js index d9e074f199..b6a758d271 100644 --- a/frappe/integrations/doctype/webhook/webhook.js +++ b/frappe/integrations/doctype/webhook/webhook.js @@ -28,6 +28,30 @@ frappe.webhook = { frappe.meta.get_docfield("Webhook Data", "fieldname", frm.doc.name).options = [""].concat(fields); }); } + }, + + set_request_headers: (frm) => { + if (frm.doc.request_structure) { + let header_value; + if (frm.doc.request_structure == "Form URL-Encoded") { + header_value = "application/x-www-form-urlencoded"; + } else if (frm.doc.request_structure == "JSON") { + header_value = "application/json"; + } + + if (header_value) { + let header_row = (frm.doc.webhook_headers || []).find(row => row.key === 'Content-Type'); + if (header_row) { + frappe.model.set_value(header_row.doctype, header_row.name, "value", header_value); + } else { + frm.add_child("webhook_headers", { + "key": "Content-Type", + "value": header_value + }); + } + frm.refresh(); + } + } } }; @@ -36,6 +60,10 @@ frappe.ui.form.on('Webhook', { frappe.webhook.set_fieldname_select(frm); }, + request_structure: (frm) => { + frappe.webhook.set_request_headers(frm); + }, + webhook_doctype: (frm) => { frappe.webhook.set_fieldname_select(frm); } diff --git a/frappe/integrations/doctype/webhook/webhook.json b/frappe/integrations/doctype/webhook/webhook.json index b1fd05649f..c62edd9274 100644 --- a/frappe/integrations/doctype/webhook/webhook.json +++ b/frappe/integrations/doctype/webhook/webhook.json @@ -14,10 +14,13 @@ "html_condition", "sb_webhook", "request_url", + "cb_webhook", + "request_structure", "sb_webhook_headers", "webhook_headers", "sb_webhook_data", - "webhook_data" + "webhook_data", + "webhook_json" ], "fields": [ { @@ -93,13 +96,30 @@ "label": "Webhook Data" }, { + "depends_on": "eval: !doc.request_structure || doc.request_structure == \"Form URL-Encoded\"", "fieldname": "webhook_data", "fieldtype": "Table", "label": "Data", "options": "Webhook Data" + }, + { + "fieldname": "cb_webhook", + "fieldtype": "Column Break" + }, + { + "fieldname": "request_structure", + "fieldtype": "Select", + "label": "Request Structure", + "options": "\nForm URL-Encoded\nJSON" + }, + { + "depends_on": "eval: doc.request_structure == \"JSON\"", + "fieldname": "webhook_json", + "fieldtype": "Code", + "label": "JSON Request Body" } ], - "modified": "2019-08-14 01:39:44.060261", + "modified": "2019-08-26 00:38:14.611267", "modified_by": "Administrator", "module": "Integrations", "name": "Webhook", diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py index b5310a523b..b21fe1ee30 100644 --- a/frappe/integrations/doctype/webhook/webhook.py +++ b/frappe/integrations/doctype/webhook/webhook.py @@ -14,6 +14,7 @@ from six.moves.urllib.parse import urlparse import frappe from frappe import _ from frappe.model.document import Document +from frappe.utils.jinja import validate_template class Webhook(Document): @@ -24,6 +25,7 @@ class Webhook(Document): self.validate_docevent() self.validate_condition() self.validate_request_url() + self.validate_request_body() self.validate_repeating_fields() def on_update(self): @@ -51,6 +53,14 @@ class Webhook(Document): except Exception as e: frappe.throw(_("Check Request URL"), exc=e) + def validate_request_body(self): + if self.request_structure: + if self.request_structure == "Form URL-Encoded": + self.webhook_json = None + elif self.request_structure == "JSON": + validate_template(self.webhook_json) + self.webhook_data = [] + def validate_repeating_fields(self): """Error when Same Field is entered multiple times in webhook_data""" webhook_data = [] @@ -73,13 +83,17 @@ def enqueue_webhook(doc, webhook): for h in webhook.webhook_headers: if h.get("key") and h.get("value"): headers[h.get("key")] = h.get("value") + if webhook.webhook_data: for w in webhook.webhook_data: - for k, v in doc.as_dict().items(): - if k == w.fieldname: - if isinstance(v, datetime.datetime): - v = frappe.utils.get_datetime_str(v) - data[w.key] = v + value = doc.get(w.fieldname) + if isinstance(value, datetime.datetime): + value = frappe.utils.get_datetime_str(value) + data[w.key] = value + elif webhook.webhook_json: + data = frappe.render_template(webhook.webhook_json, get_context(doc)) + data = json.loads(data) + for i in range(3): try: r = requests.post(webhook.request_url, data=json.dumps(data), headers=headers, timeout=5)