Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/error boundary #6

Merged
merged 4 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python 3.11.0
13 changes: 13 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import time
from typing import Any

import pytest


@pytest.fixture
def sleepless(monkeypatch: Any) -> None:

def sleep(seconds: int) -> None:
pass

monkeypatch.setattr(time, 'sleep', sleep)
21 changes: 20 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "connector-http"
version = "0.2.0"
version = "1.0.0"
description = "Make HTTP Requests available to SpiffWorkflow Service Tasks"
authors = ["Jon Herron <[email protected]>"]
readme = "README.md"
Expand All @@ -9,6 +9,9 @@ packages = [{include = "connector_http", from = "src" }]
[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.2"
spiffworkflow-connector-command = {git = "https://github.com/sartography/spiffworkflow-connector-command.git", rev = "main"}
# spiffworkflow-connector-command = {develop = true, path = "../spiffworkflow-connector-command"}



[tool.poetry.group.dev.dependencies]
Expand Down
10 changes: 7 additions & 3 deletions src/connector_http/commands/get_request.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@

import requests
from typing import Any

import requests # type: ignore
from spiffworkflow_connector_command.command_interface import CommandResultDictV1
from spiffworkflow_connector_command.command_interface import ConnectorCommand

class GetRequest:

class GetRequest(ConnectorCommand):
def __init__(self,
url: str,
headers: dict[str, str] | None = None,
Expand All @@ -16,7 +20,7 @@ def __init__(self,
self.basic_auth_username = basic_auth_username
self.basic_auth_password = basic_auth_password

def execute(self, config, task_data):
def execute(self, _config: Any, _task_data: Any) -> CommandResultDictV1:
auth = None
if self.basic_auth_username is not None and self.basic_auth_password is not None:
auth = (self.basic_auth_username, self.basic_auth_password)
Expand Down
90 changes: 11 additions & 79 deletions src/connector_http/commands/get_request_v2.py
Original file line number Diff line number Diff line change
@@ -1,88 +1,20 @@
import json
import time
from typing import Any

import requests
import requests # type: ignore
from spiffworkflow_connector_command.command_interface import CommandResultDictV2
from spiffworkflow_connector_command.command_interface import ConnectorCommand

from connector_http.http_request_base import HttpRequestBase

class GetRequestV2:

class GetRequestV2(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,
attempts: int | None = None, **kwargs: Any
):
self.url = url
self.headers = headers or {}
self.params = params or {}
self.basic_auth_username = basic_auth_username
self.basic_auth_password = basic_auth_password

HttpRequestBase.__init__(self, **kwargs)
if not isinstance(attempts, int) or attempts < 1 or attempts > 10:
attempts = 1

self.attempts = attempts

def execute(self, config, task_data):
logs = []

def log(msg):
logs.append(f"[{time.time()}] {msg}")

log("Will execute")

auth = None
if self.basic_auth_username is not None and self.basic_auth_password is not None:
auth = (self.basic_auth_username, self.basic_auth_password)
log("Set auth")

attempt = 1

while attempt <= self.attempts:
response = {}
status = 0
mimetype = "application/json"

if attempt > 1:
log("Sleeping before next attempt")
time.sleep(1)

log(f"Will attempt {attempt} of {self.attempts}")
api_response = None

try:
log(f"Will call {self.url}")
api_response = requests.get(self.url, self.params, headers=self.headers, auth=auth, timeout=300)
log(f"Did call {self.url}")

log("Will parse response")
status = api_response.status_code
response = json.loads(api_response.text)
log("Did parse response")
except Exception as e:
log(f"Did catch exception: {e}")
if len(response) == 0:
response = f'{"error": {e}, "raw_response": {api_response.text}}',
if status == 0:
status = 500
finally:
log(f"Did attempt {attempt} of {self.attempts}")

if status // 100 != 5:
break

attempt += 1

log("Did execute")

result = {
"response": {
"api_response": response,
"spiff__logs": logs,
},
"status": status,
"mimetype": mimetype,
}

return result
def execute(self, _config: Any, _task_data: dict) -> CommandResultDictV2:
return self.run_request(requests.get)
8 changes: 5 additions & 3 deletions src/connector_http/commands/post_request.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from typing import Any

import requests
import requests # type: ignore
from spiffworkflow_connector_command.command_interface import CommandResultDictV1
from spiffworkflow_connector_command.command_interface import ConnectorCommand


class PostRequest:
class PostRequest(ConnectorCommand):
def __init__(self,
url: str,
headers: dict[str, str] | None,
Expand All @@ -17,7 +19,7 @@ def __init__(self,
self.basic_auth_password = basic_auth_password
self.data = data

def execute(self, config, task_data):
def execute(self, _config: Any, _task_data: Any) -> CommandResultDictV1:
auth = None
if self.basic_auth_username is not None and self.basic_auth_password is not None:
auth = (self.basic_auth_username, self.basic_auth_password)
Expand Down
68 changes: 7 additions & 61 deletions src/connector_http/commands/post_request_v2.py
Original file line number Diff line number Diff line change
@@ -1,66 +1,12 @@
import json
import time
from typing import Any

import requests
import requests # type: ignore
from spiffworkflow_connector_command.command_interface import CommandResultDictV2
from spiffworkflow_connector_command.command_interface import ConnectorCommand

from connector_http.http_request_base import HttpRequestBase

class PostRequestV2:
def __init__(self,
url: str,
headers: dict[str, str] | None = None,
basic_auth_username: str | None = None,
basic_auth_password: str | None = None,
data: dict[str, Any] | None = None,
):
self.url = url
self.headers = headers or {}
self.basic_auth_username = basic_auth_username
self.basic_auth_password = basic_auth_password
self.data = data

def execute(self, config, task_data):
logs = []

def log(msg):
logs.append(f"[{time.time()}] {msg}")

response = {}
status = 0
mimetype = "application/json"

log("Will execute")

auth = None
if self.basic_auth_username is not None and self.basic_auth_password is not None:
auth = (self.basic_auth_username, self.basic_auth_password)
log("basic auth has been set")

try:
log(f"Will call {self.url} with data {self.data}")
api_response = requests.post(self.url, headers=self.headers, auth=auth, json=self.data, timeout=300)
log(f"Did call {self.url}")

log(f"Will parse response with status code {api_response.status_code}")
status = api_response.status_code
response = json.loads(api_response.text) if api_response.text else {}
log("Did parse response")
except Exception as e:
log(f"Did catch exception: {e}")
if len(response) == 0:
response = f'{"error": {e}, "raw_response": {api_response.text}}',
if status == 0:
status = 500
finally:
log("Did execute")

result = {
"response": {
"api_response": response,
"spiff__logs": logs,
},
"status": status,
"mimetype": mimetype,
}

return result
class PostRequestV2(ConnectorCommand, HttpRequestBase):
def execute(self, _config: Any, _task_data: dict) -> CommandResultDictV2:
return self.run_request(requests.post)
Loading
Loading