Search code examples
pythoncurlpycurl

How to cancel a curl request from a WRITEFUNCTION?


I have a curl request in python which outputs a large amount of data to a writefunction (CURLOPT_WRITEFUNCTION). I want to be able to cancel the curl request from the writefunction if a certain condition is met. I've tried using ch.close(), but that errors saying that it cant close a request while its being performed. Any other way to get it to stop from a writefunction? Heres my code:

    self.ch = pycurl.Curl()

    self.ch.setopt(pycurl.URL, file_url)
    self.ch.setopt(pycurl.CONNECTTIMEOUT, 60)
    self.ch.setopt(pycurl.WRITEFUNCTION, self.WriteWrapper)
    self.ch.setopt(pycurl.HEADERFUNCTION, self.ParseHeaders)
    self.ch.setopt(pycurl.FOLLOWLOCATION, True)
    self.ch.setopt(pycurl.COOKIE, cookies[file_host])
    self.ch.setopt(pycurl.HTTPHEADER, self.headers_received)

    self.ch.perform()
    self.ch.close()


def do_POST(self):
    return self.do_GET()

def WriteWrapper(self, data):
    if self.do_curl_request:
        try:
            return self.wfile.write(data)
        except:
            self.ch.close() # This doesn't work :(

Solution

  • pycurl raises an error if the number returned from your write function isn't equal to the number it thinks it's writing, so returning -1 or raising an exception inside your write function will cause it to raise pycurl.error. Note that returning 'None' is interpreted as 'all bytes written'.

    >>> class Writer:
    ...   def __init__(self):
    ...     self.count = 0
    ...   def write(self, data):
    ...     print "Write called", len(data)
    ...     return -1
    ...
    >>> curl = pycurl.Curl()
    >>> writer = Writer()
    >>> curl.setopt(pycurl.WRITEFUNCTION, writer.write)
    >>> curl.setopt(pycurl.URL, "file:///some_big_file.txt")
    >>> curl.perform()
    Write called 16383
    pycurl.error: invalid return value for write callback -1 16383
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    pycurl.error: (23, 'Failed writing body (0 != 16383)')