Skip to main content

Manage outbound HTTP connections using Curl & CurlMulti

Project description

Manage outbound HTTP connections using Curl & CurlMulti

Description

mcurl is a Python wrapper for libcurl with a high-level API that makes it easy to interact with the libcurl easy and multi interfaces. It was originally created for the Px proxy server which uses libcurl to handle upstream proxy authentication.

Usage

mcurl can be installed using pip:

pip install pymcurl

Binary packages are provided the following platforms:

  • aarch64-linux-gnu
  • aarch64-linux-musl
  • arm64-mac
  • i686-linux-gnu
  • x86_64-linux-gnu
  • x86_64-linux-musl
  • x86_64-macos
  • x86_64-windows

mcurl leverages cffi to interface with libcurl and all binary dependencies are sourced from binarybuilder.org. auditwheel on Linux, delocate on MacOS and delvewheel on Windows are used to bundle the shared libraries into the wheels.

Thanks to cffi and Py_LIMITED_API, these mcurl binaries should work on any Python from v3.2 onwards.

Easy interface

import mcurl

mcurl.dprint = print

c = mcurl.Curl('http://httpbin.org/get')
c.set_debug()
c.buffer()
ret = c.perform()
if ret == 0:
    ret, resp = c.get_response()
    headers = c.get_headers()
    data = c.get_data()
    print(f"Response: {resp}\n\n{headers}{data}")

Multi interface

import mcurl

mcurl.dprint = print

m = mcurl.MCurl()

c1 = mcurl.Curl('http://httpbin.org/get')
c1.set_debug()
c1.buffer()
m.add(c1)

data = "test8192".encode("utf-8")
c2 = mcurl.Curl('https://httpbin.org/post', 'POST')
c2.set_debug()
c2.buffer(data=data)
c2.set_headers({"Content-Length": len(data)})
m.add(c2)

ret1 = m.do(c1)
ret2 = m.do(c2)

if ret1:
    c1.get_response()
    c1.get_headers()
    c1.get_data()
    print(f"Response: {c1.get_response()}\n\n" +
          f"{c1.get_headers()}{c1.get_data()}")
else:
    print(f"Failed with error: {c1.errstr}")

if ret2:
    c2.get_response()
    c2.get_headers()
    c2.get_data()
    print(f"Response: {c2.get_response()}\n\n" +
          f"{c2.get_headers()}{c2.get_data()}")
else:
    print(f"Failed with error: {c2.errstr}")

m.close()

libcurl API

The libcurl API can be directly accessed as is done in mcurl if preferred.

from _libcurl_cffi import lib as libcurl
from _libcurl_cffi import ffi

url = "http://httpbin.org/get"
curl = ffi.new("char []", url.encode("utf-8"))

easy = libcurl.curl_easy_init()
libcurl.curl_easy_setopt(easy, libcurl.CURLOPT_URL, curl)
cerr = libcurl.curl_easy_perform(easy)

API reference

NAME
    mcurl - Manage outbound HTTP connections using Curl & CurlMulti

CLASSES
    builtins.object
        Curl
        MCurl

    class Curl(builtins.object)
     |  Curl(url, method='GET', request_version='HTTP/1.1', connect_timeout=60)
     |
     |  Helper class to manage a curl easy instance
     |
     |  Methods defined here:
     |
     |  __del__(self)
     |      Destructor - clean up resources
     |
     |  __init__(self, url, method='GET', request_version='HTTP/1.1', connect_timeout=60)
     |      Initialize curl instance
     |
     |      method = GET, POST, PUT, CONNECT, etc.
     |      request_version = HTTP/1.0, HTTP/1.1, etc.
     |
     |  bridge(self, client_rfile=None, client_wfile=None, client_hfile=None)
     |      Bridge curl reads/writes to sockets specified
     |
     |      Reads POST/PATCH data from client_rfile
     |      Writes data back to client_wfile
     |      Writes headers back to client_hfile
     |
     |  buffer(self, data=None)
     |      Setup buffers to bridge curl perform
     |
     |  get_activesocket(self)
     |      Return active socket for this easy instance
     |
     |  get_data(self, encoding='utf-8')
     |      Return data written by curl perform to buffer()
     |
     |      encoding = "utf-8" by default, change or set to None if bytes preferred
     |
     |  get_headers(self, encoding='utf-8')
     |      Return headers written by curl perform to buffer()
     |
     |      encoding = "utf-8" by default, change or set to None if bytes preferred
     |
     |  get_primary_ip(self)
     |      Return primary IP address of this easy instance
     |
     |  get_proxyauth_used(self)
     |      Return which proxy auth method was used for this easy instance
     |
     |  get_response(self)
     |      Return response code of completed request
     |
     |  get_used_proxy(self)
     |      Return whether proxy was used for this easy instance
     |
     |  perform(self)
     |      Perform the easy handle
     |
     |  reset(self, url, method='GET', request_version='HTTP/1.1', connect_timeout=60)
     |      Reuse existing curl instance for another request
     |
     |  set_auth(self, user, password=None, auth='ANY')
     |      Set proxy authentication info - call after set_proxy() to enable auth caching
     |
     |  set_debug(self, enable=True)
     |      Enable debug output
     |
     |  set_follow(self, enable=True)
     |      Set curl to follow 3xx responses
     |
     |  set_headers(self, xheaders)
     |      Set headers to send
     |
     |  set_insecure(self, enable=True)
     |      Set curl to ignore SSL errors
     |
     |  set_proxy(self, proxy, port=0, noproxy=None)
     |      Set proxy options - returns False if this proxy server has auth failures
     |
     |  set_transfer_decoding(self, enable=False)
     |      Set curl to turn off transfer decoding - let client do it
     |
     |  set_tunnel(self, tunnel=True)
     |      Set to tunnel through proxy if no proxy or proxy + auth
     |
     |  set_useragent(self, useragent)
     |      Set user agent to send
     |
     |  set_verbose(self, enable=True)
     |      Set verbose mode
     |

    class MCurl(builtins.object)
     |  MCurl(debug_print=None)
     |
     |  Helper class to manage a curl multi instance
     |
     |  Methods defined here:
     |
     |  __init__(self, debug_print=None)
     |      Initialize multi interface
     |
     |  add(self, curl: mcurl.Curl)
     |      Add a Curl handle to perform
     |
     |  close(self)
     |      Stop any running transfers and close this multi handle
     |
     |  do(self, curl: mcurl.Curl)
     |      Add a Curl handle and peform until completion
     |
     |  remove(self, curl: mcurl.Curl)
     |      Remove a Curl handle once done
     |
     |  select(self, curl: mcurl.Curl, client_sock, idle=30)
     |      Run select loop between client and curl
     |
     |  setopt(self, option, value)
     |      Configure multi options
     |
     |  stop(self, curl: mcurl.Curl)
     |      Stop a running curl handle and remove

FUNCTIONS
    curl_version()
        Get curl version as numeric representation

    cvp2pystr(cvoidp)
        Convert void * to Python string

    debug_callback(easy, infotype, data, size, userp)
        Prints out curl debug info and headers sent/received

    dprint(_)

    get_curl_features()
        Get all supported feature names from version info data

    get_curl_vinfo()
        Get curl version info data

    getauth(auth)
        Return auth value for specified authentication string

        Supported values can be found here: https://curl.se/libcurl/c/CURLOPT_HTTPAUTH.html

        Skip the CURLAUTH_ portion in input - e.g. getauth("ANY")

        To control which methods are available during proxy detection:
          Prefix NO to avoid method - e.g. NONTLM => ANY - NTLM
          Prefix SAFENO to avoid method - e.g. SAFENONTLM => ANYSAFE - NTLM
          Prefix ONLY to support only that method - e.g ONLYNTLM => ONLY + NTLM

    gethash(easy)
        Return hash value for easy to allow usage as a dict key

    header_callback(buffer, size, nitems, userdata)

    multi_timer_callback(multi, timeout_ms, userp)

    print_curl_version()
        Display curl version information

    py2cbool(pbool)
        Convert Python bool to long

    py2clong(plong)
        Convert Python int to long

    py2cstr(pstr)
        Convert Python string to char *

    py2custr(pstr)
        Convert Python string to char *

    read_callback(buffer, size, nitems, userdata)

    sanitized(msg)
        Hide user sensitive data from debug output

    socket_callback(easy, sock_fd, ev_bitmask, userp, socketp)

    sockopt_callback(clientp, sock_fd, purpose)

    write_callback(buffer, size, nitems, userdata)

    yield_msgs(data, size)
        Generator for curl debug messages

Building mcurl

mcurl is built using gcc on Linux, clang on MacOS and mingw-x64 on Windows. The shared libraries are downloaded from binarybuilder.org using jbb for Linux and Windows. Custom libcurl binaries that include kerberos support on Linux and remove the libssh2 dependency are included. MacOS includes the libcurl binaries and dependencies installed via brew.

cibuildwheel is used to build all the artifacts.

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 Distributions

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

pymcurl-8.12.1.1-cp32-abi3-win_amd64.whl (1.0 MB view details)

Uploaded CPython 3.2+Windows x86-64

pymcurl-8.12.1.1-cp32-abi3-musllinux_1_2_x86_64.whl (5.5 MB view details)

Uploaded CPython 3.2+musllinux: musl 1.2+ x86-64

pymcurl-8.12.1.1-cp32-abi3-musllinux_1_2_aarch64.whl (5.2 MB view details)

Uploaded CPython 3.2+musllinux: musl 1.2+ ARM64

pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.6 MB view details)

Uploaded CPython 3.2+manylinux: glibc 2.17+ x86-64

pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_i686.manylinux2014_i686.whl (5.4 MB view details)

Uploaded CPython 3.2+manylinux: glibc 2.17+ i686

pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (5.3 MB view details)

Uploaded CPython 3.2+manylinux: glibc 2.17+ ARM64

pymcurl-8.12.1.1-cp32-abi3-macosx_15_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.2+macOS 15.0+ ARM64

pymcurl-8.12.1.1-cp32-abi3-macosx_12_0_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.2+macOS 12.0+ x86-64

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-win_amd64.whl.

File metadata

  • Download URL: pymcurl-8.12.1.1-cp32-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.2+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 087ae746b8030dda538d3200807563c65ab54e8440fcb4073b176f3b2d601a26
MD5 13b74e6fdd0e769e89e1b3cbf0e318f2
BLAKE2b-256 b06d770f8973cae521c6f8a3e165e4d0dc23c829a62342ccf5fe930ca765c256

See more details on using hashes here.

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 76381a516f319d5e2b5b5618668c8a471871182ea1994618f9ea3ccb0e29b003
MD5 cf426687f5f5b1b2e88826a6d4fe0eb3
BLAKE2b-256 a90b4261a48c29ae78b1290d4a9c8beb4b440523409877f4228ca5187f78435b

See more details on using hashes here.

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 1a0253fca4bd1c2cca5ee0aeedb3df6efe1caa1459c14b5bec3bb27f865c2b47
MD5 d86885b0f2bc785eade3274730e5af07
BLAKE2b-256 d39ee1dbaf3a3cb0a05f1d84a01ab2266c1be974c9dcad85e94d1b5fff0a62ae

See more details on using hashes here.

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b2ac4651442d0247b157fd64ce18cd1a9d38c57c58570f25dab61570fbd15330
MD5 e7ef56761e8ea6957439afc1df278983
BLAKE2b-256 08f7ccb9a148ffd750bcb900024abc96d4c5dbc3b1c321fc07b72a31dd79cfc2

See more details on using hashes here.

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a4e86802b192802475de9a276d8c6d1d47a57e8ca3ea34449ce854e8388b8b5f
MD5 147a77e3c892c77b75dbf0eb70a22344
BLAKE2b-256 0a039788f1ae242699d428cd354ec2253de738e6dde73a303db35edaeea2110e

See more details on using hashes here.

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 af742654687cf8c3e253afd85144674c57756b2474465ce20230bcf98f955022
MD5 4592179e5537f856b1ba004fac47d623
BLAKE2b-256 e772a82b749e030d8484e444fd342128f8be7a4f6003df6238edeafb73fb84e3

See more details on using hashes here.

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 a528201926dedbe500d8959b8f27bf184894d62bce9bbb1047232660355ac504
MD5 2a35e203376a33b62fbd150a0bc36b86
BLAKE2b-256 178de510c7488332b884d071c7d9c8b763451c2776cc230f35d1b3a7a332694e

See more details on using hashes here.

File details

Details for the file pymcurl-8.12.1.1-cp32-abi3-macosx_12_0_x86_64.whl.

File metadata

File hashes

Hashes for pymcurl-8.12.1.1-cp32-abi3-macosx_12_0_x86_64.whl
Algorithm Hash digest
SHA256 40212880389007bebb72a3469da51689535bca7da0a6c63a64cbfd229ccf65d7
MD5 87e6c7cd8b9e77a9f83f39a8c8f16a29
BLAKE2b-256 3d3b259363438f653674eadfc4ab90853e82d621235a65e24dbb95cde748bbbb

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