From 8e4b36fe3706b070dbd0f828402b86c1536bde89 Mon Sep 17 00:00:00 2001 From: jasquat Date: Wed, 14 Feb 2024 10:39:04 -0500 Subject: [PATCH] added head, put, and delete commands w/ burnettk --- src/connector_http/commands/delete_request.py | 28 +++++++++ src/connector_http/commands/head_request.py | 31 ++++++++++ .../commands/post_request_v2.py | 9 ++- src/connector_http/commands/put_request.py | 26 ++++++++ .../unit/test_delete_request.py | 61 +++++++++++++++++++ .../connector_http/unit/test_head_request.py | 60 ++++++++++++++++++ tests/connector_http/unit/test_put_request.py | 61 +++++++++++++++++++ 7 files changed, 273 insertions(+), 3 deletions(-) create mode 100644 src/connector_http/commands/delete_request.py create mode 100644 src/connector_http/commands/head_request.py create mode 100644 src/connector_http/commands/put_request.py create mode 100644 tests/connector_http/unit/test_delete_request.py create mode 100644 tests/connector_http/unit/test_head_request.py create mode 100644 tests/connector_http/unit/test_put_request.py diff --git a/src/connector_http/commands/delete_request.py b/src/connector_http/commands/delete_request.py new file mode 100644 index 0000000..b2bf44d --- /dev/null +++ b/src/connector_http/commands/delete_request.py @@ -0,0 +1,28 @@ +from typing import Any + +import requests # type: ignore +from spiffworkflow_connector_command.command_interface import ConnectorCommand +from spiffworkflow_connector_command.command_interface import ConnectorProxyResponseDict + +from connector_http.http_request_base import HttpRequestBase + + +class DeleteRequest(ConnectorCommand, HttpRequestBase): + def __init__( + self, + url: str, + headers: dict[str, str] | None = None, + params: dict[str, str] | None = None, + data: dict[str, str] | None = None, + basic_auth_username: str | None = None, + basic_auth_password: str | None = None, + ): + HttpRequestBase.__init__( + self, url=url, headers=headers, basic_auth_username=basic_auth_username, basic_auth_password=basic_auth_password + ) + + self.params = params + self.data = data + + def execute(self, _config: Any, _task_data: dict) -> ConnectorProxyResponseDict: + return self.run_request(requests.delete) diff --git a/src/connector_http/commands/head_request.py b/src/connector_http/commands/head_request.py new file mode 100644 index 0000000..03fe0fd --- /dev/null +++ b/src/connector_http/commands/head_request.py @@ -0,0 +1,31 @@ +from typing import Any + +import requests # type: ignore +from spiffworkflow_connector_command.command_interface import ConnectorCommand +from spiffworkflow_connector_command.command_interface import ConnectorProxyResponseDict + +from connector_http.http_request_base import HttpRequestBase + + +class HeadRequest(ConnectorCommand, HttpRequestBase): + def __init__( + self, + url: str, + headers: dict[str, str] | None = None, + params: dict[str, str] | None = None, + basic_auth_username: str | None = None, + basic_auth_password: str | None = None, + attempts: int | None = None, + ): + HttpRequestBase.__init__( + self, url=url, headers=headers, basic_auth_username=basic_auth_username, basic_auth_password=basic_auth_password + ) + + self.params = params or {} + + if not isinstance(attempts, int) or attempts < 1 or attempts > 10: + attempts = 1 + self.attempts = attempts + + def execute(self, _config: Any, _task_data: dict) -> ConnectorProxyResponseDict: + return self.run_request(requests.head) diff --git a/src/connector_http/commands/post_request_v2.py b/src/connector_http/commands/post_request_v2.py index ad4f244..e441fdf 100644 --- a/src/connector_http/commands/post_request_v2.py +++ b/src/connector_http/commands/post_request_v2.py @@ -8,16 +8,19 @@ class PostRequestV2(ConnectorCommand, HttpRequestBase): - def __init__(self, + def __init__( + self, url: str, headers: dict[str, str] | None = None, data: dict[str, str] | None = None, basic_auth_username: str | None = None, basic_auth_password: str | None = None, ): - HttpRequestBase.__init__(self, url=url, headers=headers, basic_auth_username=basic_auth_username, basic_auth_password=basic_auth_password) + HttpRequestBase.__init__( + self, url=url, headers=headers, basic_auth_username=basic_auth_username, basic_auth_password=basic_auth_password + ) - self.data =data or {} + self.data = data or {} def execute(self, _config: Any, _task_data: dict) -> ConnectorProxyResponseDict: return self.run_request(requests.post) diff --git a/src/connector_http/commands/put_request.py b/src/connector_http/commands/put_request.py new file mode 100644 index 0000000..4404e07 --- /dev/null +++ b/src/connector_http/commands/put_request.py @@ -0,0 +1,26 @@ +from typing import Any + +import requests # type: ignore +from spiffworkflow_connector_command.command_interface import ConnectorCommand +from spiffworkflow_connector_command.command_interface import ConnectorProxyResponseDict + +from connector_http.http_request_base import HttpRequestBase + + +class PutRequest(ConnectorCommand, HttpRequestBase): + def __init__( + self, + url: str, + headers: dict[str, str] | None = None, + data: dict[str, str] | None = None, + basic_auth_username: str | None = None, + basic_auth_password: str | None = None, + ): + HttpRequestBase.__init__( + self, url=url, headers=headers, basic_auth_username=basic_auth_username, basic_auth_password=basic_auth_password + ) + + self.data = data or {} + + def execute(self, _config: Any, _task_data: dict) -> ConnectorProxyResponseDict: + return self.run_request(requests.put) diff --git a/tests/connector_http/unit/test_delete_request.py b/tests/connector_http/unit/test_delete_request.py new file mode 100644 index 0000000..ce1dd5c --- /dev/null +++ b/tests/connector_http/unit/test_delete_request.py @@ -0,0 +1,61 @@ +import json +from typing import Any +from unittest.mock import patch + +from connector_http.commands.delete_request import DeleteRequest + + +class TestDeleteRequest: + def test_delete_html_from_url(self) -> None: + request = DeleteRequest(url="http://example.com") + return_html = "Hey" + with patch("requests.delete") as mock_request: + mock_request.return_value.status_code = 200 + mock_request.return_value.ok = True + mock_request.return_value.text = return_html + response = request.execute(None, {}) + assert mock_request.call_count == 1 + + assert response["command_response"]["body"] == json.dumps({"raw_response": return_html}) + assert response["command_response"]["http_status"] == 200 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 + + def test_delete_json_from_url(self) -> None: + request = DeleteRequest(url="http://example.com") + return_json = {"hey": "we_return"} + with patch("requests.delete") as mock_request: + mock_request.return_value.status_code = 200 + mock_request.return_value.ok = True + mock_request.return_value.headers = {"Content-Type": "application/json"} + mock_request.return_value.text = json.dumps(return_json) + response = request.execute(None, {}) + assert mock_request.call_count == 1 + + assert response is not None + assert response["command_response"]["body"] == json.dumps(return_json) + assert response["command_response"]["http_status"] == 200 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 + + def test_delete_can_handle_500(self, sleepless: Any) -> None: + request = DeleteRequest(url="http://example.com") + return_json = {"error": "we_did_error"} + with patch("requests.delete") as mock_request: + mock_request.return_value.status_code = 500 + mock_request.return_value.headers = {"Content-Type": "application/json"} + mock_request.return_value.text = json.dumps(return_json) + response = request.execute(None, {}) + assert mock_request.call_count == 1 + + assert response is not None + assert response["command_response"]["body"] == json.dumps(return_json) + assert response["command_response"]["http_status"] == 500 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is not None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 diff --git a/tests/connector_http/unit/test_head_request.py b/tests/connector_http/unit/test_head_request.py new file mode 100644 index 0000000..2cdb3ed --- /dev/null +++ b/tests/connector_http/unit/test_head_request.py @@ -0,0 +1,60 @@ +import json +from typing import Any +from unittest.mock import patch + +from connector_http.commands.head_request import HeadRequest + + +class TestHeadRequest: + def test_head_html_from_url(self) -> None: + request = HeadRequest(url="http://example.com") + return_html = "Hey" + with patch("requests.head") as mock_request: + mock_request.return_value.status_code = 200 + mock_request.return_value.ok = True + mock_request.return_value.text = return_html + response = request.execute(None, {}) + + assert response is not None + assert response["command_response"]["body"] == json.dumps({"raw_response": return_html}) + assert response["command_response"]["http_status"] == 200 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 + + def test_head_json_from_url(self) -> None: + request = HeadRequest(url="http://example.com") + return_json = {"hey": "we_return"} + with patch("requests.head") as mock_request: + mock_request.return_value.status_code = 200 + mock_request.return_value.ok = True + mock_request.return_value.headers = {"Content-Type": "application/json"} + mock_request.return_value.text = json.dumps(return_json) + response = request.execute(None, {}) + + assert response is not None + assert response["command_response"]["body"] == json.dumps(return_json) + assert response["command_response"]["http_status"] == 200 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 + + def test_head_can_handle_500(self, sleepless: Any) -> None: + request = HeadRequest(url="http://example.com", attempts=3) + return_json = {"error": "we_did_error"} + with patch("requests.head") as mock_request: + mock_request.return_value.status_code = 500 + mock_request.return_value.headers = {"Content-Type": "application/json"} + mock_request.return_value.text = json.dumps(return_json) + response = request.execute(None, {}) + assert mock_request.call_count == 3 + + assert response is not None + assert response["command_response"]["body"] == json.dumps(return_json) + assert response["command_response"]["http_status"] == 500 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is not None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 diff --git a/tests/connector_http/unit/test_put_request.py b/tests/connector_http/unit/test_put_request.py new file mode 100644 index 0000000..ec2b687 --- /dev/null +++ b/tests/connector_http/unit/test_put_request.py @@ -0,0 +1,61 @@ +import json +from typing import Any +from unittest.mock import patch + +from connector_http.commands.put_request import PutRequest + + +class TestPutRequest: + def test_put_html_from_url(self) -> None: + request = PutRequest(url="http://example.com") + return_html = "Hey" + with patch("requests.put") as mock_request: + mock_request.return_value.status_code = 200 + mock_request.return_value.ok = True + mock_request.return_value.text = return_html + response = request.execute(None, {}) + assert mock_request.call_count == 1 + + assert response["command_response"]["body"] == json.dumps({"raw_response": return_html}) + assert response["command_response"]["http_status"] == 200 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 + + def test_put_json_from_url(self) -> None: + request = PutRequest(url="http://example.com") + return_json = {"hey": "we_return"} + with patch("requests.put") as mock_request: + mock_request.return_value.status_code = 200 + mock_request.return_value.ok = True + mock_request.return_value.headers = {"Content-Type": "application/json"} + mock_request.return_value.text = json.dumps(return_json) + response = request.execute(None, {}) + assert mock_request.call_count == 1 + + assert response is not None + assert response["command_response"]["body"] == json.dumps(return_json) + assert response["command_response"]["http_status"] == 200 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0 + + def test_put_can_handle_500(self, sleepless: Any) -> None: + request = PutRequest(url="http://example.com") + return_json = {"error": "we_did_error"} + with patch("requests.put") as mock_request: + mock_request.return_value.status_code = 500 + mock_request.return_value.headers = {"Content-Type": "application/json"} + mock_request.return_value.text = json.dumps(return_json) + response = request.execute(None, {}) + assert mock_request.call_count == 1 + + assert response is not None + assert response["command_response"]["body"] == json.dumps(return_json) + assert response["command_response"]["http_status"] == 500 + assert response["command_response"]["mimetype"] == "application/json" + assert response["error"] is not None + assert response["spiff__logs"] is not None + assert len(response["spiff__logs"]) > 0