Skip to main content

Helpful WebClient class to interact with APIs on the web

Project description

A conversational HTTP client library designed for human-centered API development, exploration, and debugging. The library is optimized for developers who value transparency, debugging capability, and workflow flexibility. It shines in scenarios involving API exploration, integration testing, and iterative development where understanding request/response patterns is crucial. Rather than hiding complexity behind abstractions, webclient-helper illuminates it through comprehensive debugging tools and direct access to underlying functionality.

Create an instance of WebClient and use the HTTP methods (OPTIONS, HEAD, GET, POST, PUT, PATCH, DELETE) to interact with an API. Every HTTP method includes immediate debugger access through debug=True.

The library assumes developer competence, provides full access to underlying session objects, and provides complete history preservation to enable analysis of API interaction patterns.

Install

pip install webclient-helper

Or, install with beautifulsoup4 and lxml (for HTML parsing support)

Install system requirements for lxml

sudo apt-get install -y libxml2 libxslt1.1 libxml2-dev libxslt1-dev

or

brew install libxml2

Install with pip

pip install webclient-helper[bs4]

QuickStart

Example with the GitHub API

Here’s a minimal example showing the library’s core philosophy in action:

Note: Before using the GitHub API, generate a “personal access token” at https://github.com/settings/tokens/new and save to your local ~/.bashrc or ~/.zshrc file (export GITHUB_ACCESS_TOKEN="ghp_vx...").

Review https://docs.github.com/en/rest/reference for endpoints to hit.

import webclient_helper as wh
from os import getenv

access_token = getenv('GITHUB_ACCESS_TOKEN')

client = wh.WebClient(
    token=access_token,
    token_type='token',
    base_url='https://api.github.com'
)

# Simple request with automatic history tracking
repos = client.GET('/user/repos')
print(f"Found {len(repos.json())} repositories")

# Interactive debugging with full context preservation
response = client.GET('/user/repos', params={'per_page': 5}, debug=True)
# This drops into PDB with complete access to response, session, and request context

# Explore your entire API session interactively
client.history_explorer()  # Launches IPython with selectable response history

This example demonstrates several key benefits: zero-boilerplate setup for common APIs, automatic request history preservation for pattern analysis, embedded debugging that doesn’t require separate tooling, and interactive exploration tools that help you understand API behavior through direct investigation.

Example with custom login method on a subclass

Here’s an example for creating test clients on your team’s internal platform:

import webclient_helper as wh


class SomeClient(wh.WebClient):
    def login(self):
        headers = {'Content-Type': 'application/json'}
        data = {'email': self._username, 'password': self._password}
        response = self.session.post(
            self._base_url + '/api/login',
            headers=headers,
            json=data
        )
        self._token = response.json().get('access_token')
        self._token_type = 'Bearer'

    def get_something(self, params=None, debug=False):
        return self.GET(
            '/api/something',
            params=params,
            debug=debug
        )


some_client = SomeClient(
    username='myuser',
    password='mypass',
    base_url='https://somewhere.com',
)

something1 = some_client.get_something(params={'x': 1, 'y': 5})
something2 = some_client.get_something(params={'x': 2, 'y': 10})

API Overview

WebClient Class

  • ``WebClient(username=None, password=None, token=None, token_type=None, base_url=’’, user_agent=None, content_type=’application/json’, extra_headers={})`` - Main HTTP client for conversational API interactions

    • username: if specified, set auth on session (requires password)

    • password: if specified, set auth on session (requires username)

    • token: if specified, use this token in the “Authorization” header (requires token_type)

    • token_type: if specified, use as part of the value in the “Authorization” header

    • base_url: base url for service/API that a subclass would interact with

    • user_agent: if specified, set “User-Agent” header

    • content_type: content type for requests (defaults to ‘application/json’)

    • extra_headers: a dict of extra headers to set on the session

    • Returns: WebClient instance with session management and authentication handling

    • Internal calls: self.set_session()

  • ``WebClient.GET(url, headers=None, params=None, debug=False, retry=False, **kwargs)`` - Send a GET request with automatic history tracking

    • url: url/endpoint (automatically prepends base_url if url starts with ‘/’)

    • headers: dict of headers to update on the session before making request

    • params: a dict with query string vars and values

    • debug: if True, enter debugger before returning with full context access

    • retry: if True and initial response is “401 Unauthorized”, recreate session and retry

    • **kwargs: passed to underlying session_method for complete requests library access

    • Returns: requests.Response object

    • Internal calls: wh.session_method(), self.set_session(), wh.get_summary_from_response()

  • ``WebClient.POST(url, headers=None, data=None, json=None, debug=False, retry=False, **kwargs)`` - Send a POST request with data or JSON payload

    • url: url/endpoint (automatically prepends base_url if url starts with ‘/’)

    • headers: dict of headers to update on the session before making request

    • data: a dict to send in the body (non-JSON)

    • json: a dict to send in the body as JSON

    • debug: if True, enter debugger before returning with full context access

    • retry: if True and initial response is “401 Unauthorized”, recreate session and retry

    • **kwargs: passed to underlying session_method for complete requests library access

    • Returns: requests.Response object

    • Internal calls: wh.session_method(), self.set_session(), wh.get_summary_from_response()

  • ``WebClient.PUT(url, headers=None, data=None, debug=False, retry=False, **kwargs)`` - Send a PUT request for resource updates

    • url: url/endpoint (automatically prepends base_url if url starts with ‘/’)

    • headers: dict of headers to update on the session before making request

    • data: a dict to send in the body (non-JSON)

    • debug: if True, enter debugger before returning with full context access

    • retry: if True and initial response is “401 Unauthorized”, recreate session and retry

    • **kwargs: passed to underlying session_method for complete requests library access

    • Returns: requests.Response object

    • Internal calls: wh.session_method(), self.set_session(), wh.get_summary_from_response()

  • ``WebClient.PATCH(url, headers=None, data=None, debug=False, retry=False, **kwargs)`` - Send a PATCH request for partial resource updates

    • url: url/endpoint (automatically prepends base_url if url starts with ‘/’)

    • headers: dict of headers to update on the session before making request

    • data: a dict to send in the body (non-JSON)

    • debug: if True, enter debugger before returning with full context access

    • retry: if True and initial response is “401 Unauthorized”, recreate session and retry

    • **kwargs: passed to underlying session_method for complete requests library access

    • Returns: requests.Response object

    • Internal calls: wh.session_method(), self.set_session(), wh.get_summary_from_response()

  • ``WebClient.DELETE(url, headers=None, debug=False, retry=False, **kwargs)`` - Send a DELETE request for resource removal

    • url: url/endpoint (automatically prepends base_url if url starts with ‘/’)

    • headers: dict of headers to update on the session before making request

    • debug: if True, enter debugger before returning with full context access

    • retry: if True and initial response is “401 Unauthorized”, recreate session and retry

    • **kwargs: passed to underlying session_method for complete requests library access

    • Returns: requests.Response object

    • Internal calls: wh.session_method(), self.set_session(), wh.get_summary_from_response()

  • ``WebClient.OPTIONS(url, headers=None, debug=False, retry=False, **kwargs)`` - Send an OPTIONS request for capability discovery

    • url: url/endpoint (automatically prepends base_url if url starts with ‘/’)

    • headers: dict of headers to update on the session before making request

    • debug: if True, enter debugger before returning with full context access

    • retry: if True and initial response is “401 Unauthorized”, recreate session and retry

    • **kwargs: passed to underlying session_method for complete requests library access

    • Returns: requests.Response object

    • Internal calls: wh.session_method(), self.set_session(), wh.get_summary_from_response()

  • ``WebClient.HEAD(url, headers=None, debug=False, retry=False, **kwargs)`` - Send a HEAD request for metadata retrieval

    • url: url/endpoint (automatically prepends base_url if url starts with ‘/’)

    • headers: dict of headers to update on the session before making request

    • debug: if True, enter debugger before returning with full context access

    • retry: if True and initial response is “401 Unauthorized”, recreate session and retry

    • **kwargs: passed to underlying session_method for complete requests library access

    • Returns: requests.Response object

    • Internal calls: wh.session_method(), self.set_session(), wh.get_summary_from_response()

  • ``WebClient.history_explorer(return_selections=False)`` - Interactive exploration of request history

    • return_selections: if True, return the selections from history instead of launching IPython

    • Returns: None by default, or selected history items if return_selections=True

    • Internal calls: ih.make_selections(), ih.start_ipython()

  • ``WebClient.set_session()`` - Create new session object and invoke login method if defined

    • Returns: None (modifies self.session in place)

    • Internal calls: self.is_login_defined, wh.new_requests_session(), self.login()

  • ``WebClient.is_login_defined`` (property) - Return True if a login method is defined

    • Returns: Boolean indicating whether custom login method is implemented

    • Internal calls: None

Utility Functions

  • ``get_domain(url)`` - Extract domain from URL with www prefix removal

    • url: URL string to extract domain from

    • Returns: Domain string with ‘www.’ prefix removed

    • Internal calls: None

  • ``new_requests_session(username=None, password=None, user_agent=None, content_type=None, extra_headers={})`` - Create new requests Session with authentication and headers

    • username: if specified, set auth on session (requires password)

    • password: if specified, set auth on session (requires username)

    • user_agent: if specified, set “User-Agent” header on session

    • content_type: if specified, set “Content-Type” header on session

    • extra_headers: a dict of extra_headers to set on the session

    • Returns: configured requests.Session object

    • Internal calls: None

  • ``session_method(method, url, session=None, headers=None, debug=False, **kwargs)`` - Core HTTP request function with debugging support

    • method: HTTP method (options, head, get, post, put, patch, delete)

    • url: url/endpoint to request

    • session: a session object (creates new one if None)

    • headers: dict of headers to update on the session before making request

    • debug: if True, enter debugger before returning

    • **kwargs: additional kwargs that requests.Session.request accepts

      • params: Dictionary or bytes to be sent in the query string for the Request

      • data: Dictionary, list of tuples, bytes, or file-like object to send in the body of the Request

      • json: json to send in the body of the Request

      • cookies: Dict or CookieJar object to send with the Request

      • files: Dictionary of ‘filename’: file-like-objects for multipart encoding upload

      • auth: Auth tuple or callable to enable Basic/Digest/Custom HTTP Auth

      • timeout: How long to wait for the server to send data before giving up, as a float, or a (connect timeout, read timeout) tuple

      • allow_redirects: Set to True by default

      • proxies: Dictionary mapping protocol or protocol and hostname to the URL of the proxy

      • stream: whether to immediately download the response content. Defaults to False

      • verify: Either a boolean, in which case it controls whether we verify the server’s TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to True

      • cert: if String, path to ssl client cert file (.pem). If Tuple, (‘cert’, ‘key’) pair

    • Returns: requests.Response object or None if request fails

    • Internal calls: new_requests_session(), get_summary_from_response()

  • ``get_summary_from_response(response)`` - Generate standardized response summary string

    • response: requests.Response object to summarize

    • Returns: String with status code, method, URL, and elapsed time

    • Internal calls: None

  • ``get_soup(url_file_or_string, xml=False, session=None, warn=True)`` - Universal content parser for URLs, files, or strings

    • url_file_or_string: a string that is either a url to fetch, a file to read, or a string containing HTML/XML content (may also be bytes that are utf-8 encoded)

    • xml: if True, parse content as XML instead of HTML (requires lxml)

    • session: a session object for URL fetching

    • warn: if True, issue a warning if bs4 package is not installed

    • Returns: BeautifulSoup object or None if BeautifulSoup not available

    • Internal calls: session_method()

  • ``download_file(url, localfile=’’, session=None)`` - Download file with progressive backoff and stream support

    • url: URL string to download

    • localfile: local file path (auto-generated if empty)

    • session: a session object for downloading

    • Returns: None (downloads file to local filesystem)

    • Internal calls: session_method(), new_requests_session()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

webclient_helper-0.0.8-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

Details for the file webclient_helper-0.0.8-py3-none-any.whl.

File metadata

File hashes

Hashes for webclient_helper-0.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 25a6ee1630870d70c69f8e020f7c93e1f82e873e991da8560bdb526a6597280d
MD5 0697a1fcac528eb53bcf27de0c6fa86f
BLAKE2b-256 98f815d150a72b8872e920ca3ebbe6e02b82f08314026c5a7962b8d7073dd126

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page