Skip to content

Conversation

3bb
Copy link

@3bb 3bb commented Mar 18, 2018

Timeout is a 'must have' option for urequests-lib. We got a lot of problems caused by this missing option. I know not all micropython ports supports timemout but in this case they will receive assertion error 'Socket does not support timeout'. Thank you !

@3bb 3bb changed the title Add timeout option urequests: Add timeout option Mar 18, 2018
@3bb
Copy link
Author

3bb commented Apr 24, 2018

@pfalcon any chance to merge it ?

@pfalcon
Copy link
Contributor

pfalcon commented Apr 24, 2018

This is not a complete implementation, it uses extended API not available for all MicroPython ports. Portable implementation would use uselect.poll() (and would increase code size noticeably, so would require separate consideration).

@krismc
Copy link

krismc commented Jun 23, 2019

Anybody know how to get timeouts working in Pycom's version of urequests (below)?
import usocket

class Response:

def __init__(self, f):
    self.raw = f
    self.encoding = "utf-8"
    self._cached = None

def close(self):
    if self.raw:
        self.raw.close()
        self.raw = None
    self._cached = None

@property
def content(self):
    if self._cached is None:
        try:
            self._cached = self.raw.read()
        finally:
            self.raw.close()
            self.raw = None
    return self._cached

@property
def text(self):
    return str(self.content, self.encoding)

def json(self):
    import ujson
    return ujson.loads(self.content)

def request(method, url, data=None, json=None, headers={}, stream=None):
try:
proto, dummy, host, path = url.split("/", 3)
except ValueError:
proto, dummy, host = url.split("/", 2)
path = ""
if proto == "http:":
port = 80
elif proto == "https:":
import ussl
port = 443
else:
raise ValueError("Unsupported protocol: " + proto)

if ":" in host:
    host, port = host.split(":", 1)
    port = int(port)

#  ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM)     cause 2 arguments Vs 4 error
ai = usocket.getaddrinfo(host, port)
ai = ai[0]

s = usocket.socket(ai[0], ai[1], ai[2])

if timeout is not None:
    assert hasattr(usocket.socket, 'settimeout'), 'Socket does not support timeout'
    s.settimeout(timeout)

try:
    s.connect(ai[-1])
    if proto == "https:":
        s = ussl.wrap_socket(s, server_hostname=host)
    s.write(b"%s /%s HTTP/1.0\r\n" % (method, path))
    if not "Host" in headers:
        s.write(b"Host: %s\r\n" % host)
    # Iterate over keys to avoid tuple alloc
    for k in headers:
        s.write(k)
        s.write(b": ")
        s.write(headers[k])
        s.write(b"\r\n")
    if json is not None:
        assert data is None
        import ujson
        data = ujson.dumps(json)
        s.write(b"Content-Type: application/json\r\n")
    if data:
        s.write(b"Content-Length: %d\r\n" % len(data))
    s.write(b"\r\n")
    if data:
        s.write(data)

    l = s.readline()
    #print(l)
    l = l.split(None, 2)
    status = int(l[1])
    reason = ""
    if len(l) > 2:
        reason = l[2].rstrip()
    while True:
        l = s.readline()
        if not l or l == b"\r\n":
            break
        #print(l)
        if l.startswith(b"Transfer-Encoding:"):
            if b"chunked" in l:
                raise ValueError("Unsupported " + l)
        elif l.startswith(b"Location:") and not 200 <= status <= 299:
            raise NotImplementedError("Redirects not yet supported")
except OSError:
    s.close()
    raise

resp = Response(s)
resp.status_code = status
resp.reason = reason
return resp

def head(url, **kw):
return request("HEAD", url, **kw)

def get(url, **kw):
return request("GET", url, **kw)

def post(url, **kw):
return request("POST", url, **kw)

def put(url, **kw):
return request("PUT", url, **kw)

def patch(url, **kw):
return request("PATCH", url, **kw)

def delete(url, **kw):
return request("DELETE", url, **kw)

Copy link

@liddlem liddlem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it needs to have a timeout.

@andrewleech andrewleech mentioned this pull request Jun 20, 2022
@andrewleech
Copy link
Contributor

A version of this has been rebased and merged in a3d6d29 as part of #500. @3bb I maintained your authorship on the commit however removed the assert based on review comments - if the port does not include this timeout functionality a similar AttributeError exception will be raised already.

@andrewleech andrewleech closed this Jul 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants