Python multiple PATCH gives http.client.CannotSendRequest: Request-sent

5k Views Asked by At

I have an issue when I try to update the type of user (Base or Licensed) with Zoom API. I need to give licenses automatically to a group of users. It works only for the first user, and when I try to update the second one, I get this error:

Traceback (most recent call last):
  File "C:\Users\dmv\Documents\ZoomLicenseProj\Test\LicenseManager.py", line 58, in <module>
    conn.request("PATCH", url_update, headers=headers, body=params)
  File "C:\Users\dmv\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 1255, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\dmv\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 1266, in _send_request
    self.putrequest(method, url, **skips)
  File "C:\Users\dmv\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 1092, in putrequest
    raise CannotSendRequest(self.__state)
http.client.CannotSendRequest: Request-sent

I'm not able to understand why it works just for the first one, and then it crashes. I don't think is useful, but I even tried to put a sleep of 2 minutes between every call, same issue. Here's my code:

import sys
import jwt
import http.client
import datetime
import json

# Go to 
# Then get API Key, API Secret and insert below
api_key = 'XXX'
api_sec = 'XXXXXX'

payload = {
'iss':api_key,
'exp': datetime.datetime.now() + datetime.timedelta(hours=2)
}

jwt_encoded = str(jwt.encode(payload, api_sec), 'utf-8')

conn = http.client.HTTPSConnection("api.zoom.us")

headers = {
'authorization': "Bearer %s" % jwt_encoded,
'content-type': "application/json"
}
licensedMemberUpdate = {'type' : '2'}
baseMemberUpdate = {'type' : '1'}

conn.request("GET", "/v2/groups", headers=headers)

res = conn.getresponse()
response_string = res.read().decode('utf-8')
response_obj = json.loads(response_string)

if 'groups' in response_obj:
    groups = response_obj['groups']
    for group in groups:
        if 'Test_LicenseManager' in group['name']:
            group_id = group['id']
            
            conn.request("GET", "/v2/groups/" + group_id + "/members", headers=headers)
            res = conn.getresponse()
            response_string = res.read().decode('utf-8')
            members_list = json.loads(response_string)['members']
            
            json_lic = json.dumps(licensedMemberUpdate)
            json_base = json.dumps(baseMemberUpdate)
            
            for member in members_list:
                url_update = "/v2/users/%s" % member['email']
                
                conn.request("PATCH", url_update, headers=headers, body=json_base)
                
                #res = conn.getresponse()
                #response_obj = res.status
1

There are 1 best solutions below

1
On BEST ANSWER

From the http.client documentation:

An HTTPConnection instance represents one transaction with an HTTP server.

As I don't have access to the zoom API, I tested the behavior using a simple get request to google.com:

import http.client

conn = http.client.HTTPSConnection("google.com")

for _ in range(10):
    conn.request("GET", "/")
    res = conn.getresponse()

Results in the same error you get: http.client.ResponseNotReady: Request-sent. Instead, open a new connection for each request:

import http.client

for _ in range(10):
    conn = http.client.HTTPSConnection("google.com")
    conn.request("GET", "/")
    res = conn.getresponse()

As an alternative, I (And the authors of http.client) suggest using requests as a high-level HTTP client, which is very well documented and easy to use.