seitime-frappe/frappe/integrations/utils.py
Akhil Narang 59ca074780
fix: only try JSON if content-type says so (#24936)
Keep NoneType as the fallback

Signed-off-by: Akhil Narang <me@akhilnarang.dev>
2024-02-19 15:29:22 +05:30

161 lines
4.5 KiB
Python

# Copyright (c) 2019, Frappe Technologies and contributors
# License: MIT. See LICENSE
import datetime
import json
from urllib.parse import parse_qs
import frappe
from frappe.utils import get_request_session
def make_request(method: str, url: str, auth=None, headers=None, data=None, json=None, params=None):
auth = auth or ""
data = data or {}
headers = headers or {}
try:
s = get_request_session()
response = frappe.flags.integration_request = s.request(
method, url, data=data, auth=auth, headers=headers, json=json, params=params
)
content_type = response.headers.get("content-type")
if content_type == "text/plain; charset=utf-8":
return parse_qs(response.text)
elif content_type.startswith("application/") and content_type.split(";")[0].endswith("json"):
return response.json()
elif response.text:
return response.text
else:
return
except Exception as exc:
frappe.log_error()
raise exc
def make_get_request(url: str, **kwargs):
"""Make a 'GET' HTTP request to the given `url` and return processed response.
You can optionally pass the below parameters:
* `headers`: Headers to be set in the request.
* `params`: Query parameters to be passed in the request.
* `auth`: Auth credentials.
"""
return make_request("GET", url, **kwargs)
def make_post_request(url: str, **kwargs):
"""Make a 'POST' HTTP request to the given `url` and return processed response.
You can optionally pass the below parameters:
* `headers`: Headers to be set in the request.
* `data`: Data to be passed in body of the request.
* `json`: JSON to be passed in the request.
* `params`: Query parameters to be passed in the request.
* `auth`: Auth credentials.
"""
return make_request("POST", url, **kwargs)
def make_put_request(url: str, **kwargs):
"""Make a 'PUT' HTTP request to the given `url` and return processed response.
You can optionally pass the below parameters:
* `headers`: Headers to be set in the request.
* `data`: Data to be passed in body of the request.
* `json`: JSON to be passed in the request.
* `params`: Query parameters to be passed in the request.
* `auth`: Auth credentials.
"""
return make_request("PUT", url, **kwargs)
def make_patch_request(url: str, **kwargs):
"""Make a 'PATCH' HTTP request to the given `url` and return processed response.
You can optionally pass the below parameters:
* `headers`: Headers to be set in the request.
* `data`: Data to be passed in body of the request.
* `json`: JSON to be passed in the request.
* `params`: Query parameters to be passed in the request.
* `auth`: Auth credentials.
"""
return make_request("PATCH", url, **kwargs)
def make_delete_request(url: str, **kwargs):
"""Make a 'DELETE' HTTP request to the given `url` and return processed response.
You can optionally pass the below parameters:
* `headers`: Headers to be set in the request.
* `data`: Data to be passed in body of the request.
* `json`: JSON to be passed in the request.
* `params`: Query parameters to be passed in the request.
* `auth`: Auth credentials.
"""
return make_request("DELETE", url, **kwargs)
def create_request_log(
data,
integration_type=None,
service_name=None,
name=None,
error=None,
request_headers=None,
output=None,
**kwargs,
):
"""
DEPRECATED: The parameter integration_type will be removed in the next major release.
Use is_remote_request instead.
"""
if integration_type == "Remote":
kwargs["is_remote_request"] = 1
elif integration_type == "Subscription Notification":
kwargs["request_description"] = integration_type
reference_doctype = reference_docname = None
if "reference_doctype" not in kwargs:
if isinstance(data, str):
data = json.loads(data)
reference_doctype = data.get("reference_doctype")
reference_docname = data.get("reference_docname")
integration_request = frappe.get_doc(
{
"doctype": "Integration Request",
"integration_request_service": service_name,
"request_headers": get_json(request_headers),
"data": get_json(data),
"output": get_json(output),
"error": get_json(error),
"reference_doctype": reference_doctype,
"reference_docname": reference_docname,
**kwargs,
}
)
if name:
integration_request.flags._name = name
integration_request.insert(ignore_permissions=True)
frappe.db.commit()
return integration_request
def get_json(obj):
return obj if isinstance(obj, str) else frappe.as_json(obj, indent=1)
def json_handler(obj):
if isinstance(obj, datetime.date | datetime.timedelta | datetime.datetime):
return str(obj)