improved logging when a client dies mid-POST;

igloo irc has an absolute time limit of 2 minutes before it just
disconnects mid-upload and that kinda looked like it had a buggy
multipart generator instead of just being funny

anticipating similar events in the future, also log the
client-selected boundary value to eyeball its yoloness
This commit is contained in:
ed 2024-01-10 23:59:43 +00:00
parent 86419b8f47
commit 024303592a
2 changed files with 26 additions and 7 deletions

View file

@ -2349,6 +2349,7 @@ class HttpCli(object):
files: list[tuple[int, str, str, str, str, str]] = []
# sz, sha_hex, sha_b64, p_file, fname, abspath
errmsg = ""
tabspath = ""
dip = self.dip()
t0 = time.time()
try:
@ -2446,6 +2447,8 @@ class HttpCli(object):
if not nullwrite:
atomic_move(tabspath, abspath)
tabspath = ""
files.append(
(sz, sha_hex, sha_b64, p_file or "(discarded)", fname, abspath)
)
@ -2491,6 +2494,12 @@ class HttpCli(object):
errmsg = vol_san(
list(self.asrv.vfs.all_vols.values()), unicode(ex).encode("utf-8")
).decode("utf-8")
try:
got = bos.path.getsize(tabspath)
t = "connection lost after receiving %s of the file"
self.log(t % (humansize(got),), 3)
except:
pass
td = max(0.1, time.time() - t0)
sz_total = sum(x[0] for x in files)

View file

@ -623,9 +623,14 @@ class _Unrecv(object):
while nbytes > len(ret):
ret += self.recv(nbytes - len(ret))
except OSError:
t = "client only sent {} of {} expected bytes".format(len(ret), nbytes)
t = "client stopped sending data; expected at least %d more bytes"
if not ret:
t = t % (nbytes,)
else:
t += ", only got %d"
t = t % (nbytes, len(ret))
if len(ret) <= 16:
t += "; got {!r}".format(ret)
t += "; %r" % (ret,)
if raise_on_trunc:
raise UnrecvEOF(5, t)
@ -1517,15 +1522,20 @@ class MultipartParser(object):
return ret
def parse(self) -> None:
boundary = get_boundary(self.headers)
self.log("boundary=%r" % (boundary,))
# spec says there might be junk before the first boundary,
# can't have the leading \r\n if that's not the case
self.boundary = b"--" + get_boundary(self.headers).encode("utf-8")
self.boundary = b"--" + boundary.encode("utf-8")
# discard junk before the first boundary
for junk in self._read_data():
self.log(
"discarding preamble: [{}]".format(junk.decode("utf-8", "replace"))
)
if not junk:
continue
jtxt = junk.decode("utf-8", "replace")
self.log("discarding preamble |%d| %r" % (len(junk), jtxt))
# nice, now make it fast
self.boundary = b"\r\n" + self.boundary