Skip to content

requests.post() is called with no timeout, so an unresponsive endpoint blocks the caller indefinitely #175

Description

@nadermx

Summary

APIOperationBase.execute() calls requests.post() with no timeout, so an
unresponsive endpoint blocks the calling thread indefinitely.

Where

authorizenet/apicontrollersbase.py (current master):

self._httpResponse = requests.post(self.endpoint, data=xmlRequest,
                                   headers=constants.headers,
                                   proxies=proxyDictionary)

grep -c timeout authorizenet/apicontrollersbase.py returns 0. requests
has no default timeout, so this waits as long as the socket stays open.

Why it matters

In a web application this is a stuck worker rather than a slow request. We hit
it on a checkout path: the charge itself was approved and settled, and the
follow-up API call in the same request stalled long enough for the WSGI server
to kill the worker. The customer saw a 502 and re-purchased; the first charge
had settled and the account was never activated, because the code that would
have activated it never ran.

A timeout converts that into the None response the SDK's callers already
handle, which is recoverable — the post-charge steps still run.

Suggested fix

A conservative default with an override, e.g.:

# module level
DEFAULT_HTTP_TIMEOUT = (5, 30)   # (connect, read)

self._httpResponse = requests.post(
    self.endpoint, data=xmlRequest, headers=constants.headers,
    proxies=proxyDictionary,
    timeout=getattr(self, 'timeout', DEFAULT_HTTP_TIMEOUT))

Exposing it as a settable attribute on the controller (or via
utility.helper.getproperty, consistent with how the proxy settings are read)
would let integrators tune it without forking.

Note the read timeout must be generous enough for the slowest transactional
call, and integrators should be warned in the docs that a read timeout on a
payment request is not safe to retry blindly — the request may have been
processed.

Happy to open a PR.

Version

Observed on 1.1.4; unchanged on current master.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions