twisted / twisted/klein

When a client has already closed the connection, error handlers registered with `@klein.app.Klein(...).handle_errors()` do not get invoked, and instead a traceback is always logged

Open
#840 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
838
Forks
123
Avg merge
7h 58m
Merged PRs (30d)
12

Description

When the user(client) closes the connection the defer.CancelledError may interrupt any await operation.

This makes the code in API like

try:
    do_work()
except Exception:
    raise APIError()

to cause logs such as

Unhandled Error Processing Request.
Traceback (most recent call last):
...

located here https://github.com/twisted/klein/blob/a15e4176da46fade1bae34136bdd1d65770bc27f/src/klein/_resource.py#L270

I would consider calling the user-defined callbacks still on a an exception on a finished request.
Although the error handler can not or should not write any response down - some other handled behaviour might be done.

I was emulating this locally with this code snippet

import socket
from urllib.parse import urlparse

url = 'http://127.0.0.1:8000/'

def emulate_abrupt_disconnect(url: str) -> None:
    parsed_url = urlparse(url)
    host = parsed_url.hostname
    port = parsed_url.port or 80
    path = parsed_url.path + ('?' + parsed_url.query if parsed_url.query else '')

    request = (
        f"GET {path} HTTP/1.1\r\n"
        f"Host: {host}\r\n"
        "User-Agent: PythonSocketClient/1.0\r\n"
        "Connection: close\r\n"
        "\r\n"
    )
    with socket.create_connection((host, port), timeout=5) as sock:
        sock.sendall(request.encode('utf-8'))
        # Abruptly close the socket without reading the response
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()

emulate_abrupt_disconnect(url)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at src/klein/_resource.py around line 270 and reproduce the abrupt disconnect with the socket example in the issue. Trace how defer.CancelledError is handled when an await is interrupted, then verify that registered handle_errors callbacks are invoked for a finished request without producing the unhandled traceback.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.