Backend Development 11 min read

Critique and Refactoring of Volcengine Python SDK Request Signing

This article critiques the Volcengine Python SDK's convoluted request‑signing design, demonstrates the problems with its custom classes and static methods, and proposes cleaner solutions using the requests library's AuthBase and Session mechanisms to simplify signing and improve maintainability.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Critique and Refactoring of Volcengine Python SDK Request Signing

The author introduces Tetos, a Python library that unifies cloud TTS service interfaces.

While reviewing the Volcengine SDK, they notice inconsistent API designs and a convoluted request‑signing implementation that wraps the requests library in custom classes.

They pose the design question: how to expose a clean SDK for users when the underlying service requires a complex signature?

They show the original problematic code (class SAMIService and its common_json_handler ), pointing out unnecessary singletons, static methods, and double JSON encoding/decoding.

<code>class SAMIService(Service):
    _instance_lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not hasattr(SAMIService, "_instance"):
            with SAMIService._instance_lock:
                if not hasattr(SAMIService, "_instance"):
                    SAMIService._instance = object.__new__(cls)
        return SAMIService._instance

    def __init__(self):
        self.service_info = SAMIService.get_service_info()
        self.api_info = SAMIService.get_api_info()
        super(SAMIService, self).__init__(self.service_info, self.api_info)

    @staticmethod
    def get_service_info():
        api_url = 'open.volcengineapi.com'
        service_info = ServiceInfo(api_url, {}, Credentials('', '', 'sami', 'cn-north-1'), 10, 10)
        return service_info

    @staticmethod
    def get_api_info():
        api_info = {"GetToken": ApiInfo("POST", "/", {"Action": "GetToken", "Version": "2021-07-27"}, {}, {})}
        return api_info

    def common_json_handler(self, api, body):
        params = dict()
        try:
            body = json.dumps(body)
            res = self.json(api, params, body)
            res_json = json.loads(res)
            return res_json
        except Exception as e:
            try:
                res_json = json.loads(str(e))
                return res_json
            except:
                raise Exception(str(e))

if __name__ == '__main__':
    sami_service = SAMIService()
    sami_service.set_ak(ACCESS_KEY)
    sami_service.set_sk(SECRET_KEY)
    req = {"appkey": APPKEY, "token_version": AUTH_VERSION, "expiration": 3600}
    resp = sami_service.common_json_handler("GetToken", req)
    try:
        print("response task_id=%s status_code=%d status_text=%s expires_at=%s\n\t token=%s" % (
            resp["task_id"], resp["status_code"], resp["status_text"], resp["expires_at"], resp["token"]))
    except:
        print("get token failed, ", resp)</code>

They propose simplifying the flow by using a plain function, by directly calling requests.post , and by moving the signature step into a requests.auth.AuthBase implementation.

<code>def common_json_handler(service, api, body):
    params = dict()
    try:
        body = json.dumps(body)
        res = service.json(api, params, body)
        res_json = json.loads(res)
        return res_json
    except Exception as e:
        # ...
        ...
</code>

A custom authentication class can be written as:

<code>class VolcAuth(AuthBase):
    def __init__(self, service_info, credentials):
        self.service_info = service_info
        self.credentials = credentials

    def __call__(self, r):
        # new_sign implementation (omitted)
        new_sign(r, self.service_info, self.credentials)
        return r

auth = VolcAuth(service_info, credentials)
res = requests.post(url, json=body, auth=auth)
</code>

Alternatively, a session subclass can inject the signature in send :

<code>class VolcSession(requests.Session):
    def send(self, request, **kwargs):
        new_sign(request, service_info, credentials)
        return super().send(request, **kwargs)
</code>

The author also mentions a reference implementation for httpx and shows that the refactored version reduces the code from hundreds of lines to about sixty, demonstrating the benefit of understanding library internals.

In conclusion, the SDK appears to be a direct translation from another language, and the author suggests using the standard extension points of the requests library to keep the interface minimal and maintainable.

backendSDKpythonhttpDesignrequestsrequest signing
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.