Skip to content

Commit 1692142

Browse files
authored
enhance Curl class to handle None curl cases (#631)
1 parent 6abebcb commit 1692142

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

curl_cffi/curl.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ def setopt(self, option: CurlOpt, value: Any) -> int:
207207
Returns:
208208
0 if no error, see ``CurlECode``.
209209
"""
210+
if self._curl is None:
211+
return 0 # silently ignore if curl handle is None
210212
input_option = {
211213
# this should be int in curl, but cffi requires pointer for void*
212214
# it will be convert back in the glue c code.
@@ -308,18 +310,28 @@ def getinfo(self, option: CurlInfo) -> Union[bytes, int, float, list]:
308310
0x100000: ffi.string,
309311
0x200000: int,
310312
0x300000: float,
313+
0x400000: list,
311314
0x500000: int,
312315
0x600000: int,
313316
}
314-
c_value = ffi.new(ret_option[option & 0xF00000])
317+
318+
option_type = option & 0xF00000
319+
320+
if self._curl is None:
321+
if option_type == 0x100000:
322+
return b""
323+
return ret_cast_option[option_type]()
324+
325+
c_value = ffi.new(ret_option[option_type])
315326
ret = lib.curl_easy_getinfo(self._curl, option, c_value)
316327
self._check_error(ret, "getinfo", option)
317328
# cookielist and ssl_engines starts with 0x400000, see also: const.py
318-
if option & 0xF00000 == 0x400000:
329+
if option_type == 0x400000:
319330
return slist_to_list(c_value[0])
320331
if c_value[0] == ffi.NULL:
321332
return b""
322-
return ret_cast_option[option & 0xF00000](c_value[0])
333+
334+
return ret_cast_option[option_type](c_value[0])
323335

324336
def version(self) -> bytes:
325337
"""Get the underlying libcurl version."""
@@ -335,6 +347,8 @@ def impersonate(self, target: str, default_headers: bool = True) -> int:
335347
Returns:
336348
0 if no error.
337349
"""
350+
if self._curl is None:
351+
return 0 # silently ignore if curl handle is None
338352
return lib.curl_easy_impersonate(
339353
self._curl, target.encode(), int(default_headers)
340354
)
@@ -356,6 +370,9 @@ def perform(self, clear_headers: bool = True, clear_resolve: bool = True) -> Non
356370
Raises:
357371
CurlError: if the perform was not successful.
358372
"""
373+
if self._curl is None:
374+
raise CurlError("Cannot perform request on closed handle.")
375+
359376
# make sure we set a cacert store
360377
self._ensure_cacert()
361378

@@ -369,12 +386,14 @@ def perform(self, clear_headers: bool = True, clear_resolve: bool = True) -> Non
369386
self.clean_handles_and_buffers(clear_headers, clear_resolve)
370387

371388
def upkeep(self) -> int:
389+
if self._curl is None:
390+
return 0 # silently ignore if curl handle is None
372391
return lib.curl_easy_upkeep(self._curl)
373392

374393
def clean_handles_and_buffers(
375394
self, clear_headers: bool = True, clear_resolve: bool = True
376395
) -> None:
377-
"""Clean up handles and buffers after ``perform`` and ``close``,
396+
"""Clean up handles and buffers after ``perform`` and ``close``,
378397
called at the end of ``perform`` and ``close``."""
379398
self._write_handle = None
380399
self._header_handle = None
@@ -400,6 +419,8 @@ def duphandle(self) -> Curl:
400419
401420
This is not a full copy of entire curl object in python. For example, headers
402421
handle is not copied, you have to set them again."""
422+
if self._curl is None:
423+
raise CurlError("Cannot duplicate closed handle.")
403424
new_handle = lib.curl_easy_duphandle(self._curl)
404425
c = Curl(cacert=self._cacert, debug=self._debug, handle=new_handle)
405426
return c
@@ -478,6 +499,9 @@ def ws_recv(self, n: int = 1024) -> tuple[bytes, CurlWsFrame]:
478499
Raises:
479500
CurlError: if failed.
480501
"""
502+
if self._curl is None:
503+
raise CurlError("Cannot receive websocket data on closed handle.")
504+
481505
buffer = ffi.new("char[]", n)
482506
n_recv = ffi.new("size_t *")
483507
p_frame = ffi.new("struct curl_ws_frame **")
@@ -503,6 +527,9 @@ def ws_send(self, payload: bytes, flags: CurlWsFlag = CurlWsFlag.BINARY) -> int:
503527
Raises:
504528
CurlError: if failed.
505529
"""
530+
if self._curl is None:
531+
raise CurlError("Cannot send websocket data on closed handle.")
532+
506533
n_sent = ffi.new("size_t *")
507534
buffer = ffi.from_buffer(payload)
508535
ret = lib.curl_ws_send(self._curl, buffer, len(payload), n_sent, 0, flags)

0 commit comments

Comments
 (0)