Skip to content

Conversation

@ryanking13
Copy link
Contributor

This adds HTMLRewriter class in Python SDK, which does proxy lifetime handling internally.

We have an example that uses HTMLRewriter, but it uses JS API directly which is slightly annoying to use in Python because of the proxy handling.

@ryanking13 ryanking13 requested review from a team as code owners January 22, 2026 09:04
Comment on lines +1348 to +1353
wrapped_body = js.ReadableStream.new(
to_js(
{"start": start_proxy},
dict_converter=Object.fromEntries,
)
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is basically the main job for this wrapper class, but it only provides start for now.

I considered adding cancel as well, but using cancel actually makes the proxy lifetime handling a lot much complicated as I found that even after calling cancel, there might be remaining task that tries to read the stream, and destroying the proxy too early would crash the code...

Comment on lines +16 to +18
# FIXME: The exception is caught correctly in Python-level,
# but workerd shows "uncaught exception" error which makes the test fail.
# await test_handler_error()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Passing a Python class that raise exception to the JS HTMLRewriter always makes the test fail even if I catch the error in Python (it is catched in the Python block but the test still fails). I am not sure if it is expected behavior or not.

workerd/server/server.c++:5882: debug: [ TEST ] python-htmlrewriter
workerd/io/worker.c++:2323: info: uncaught exception; source = Uncaught; stack = PythonError: Traceback (most recent call last):
  File "/session/metadata/worker.py", line 202, in text
    raise ValueError("Test error")
ValueError: Test error

    at new_error (pyodide-internal:generated/emscriptenSetup:19907:14)
    at wasm://wasm/020fb45e:wasm-function[261]:0x10f02c
    at wasm://wasm/020fb45e:wasm-function[262]:0x10f0f4
    at callPyObjectKwargs (pyodide-internal:generated/emscriptenSetup:22399:37)
    at Module.callPyObject (pyodide-internal:generated/emscriptenSetup:22444:18)
    at Function.apply (pyodide-internal:generated/emscriptenSetup:23275:60)
    at Object.apply (pyodide-internal:generated/emscriptenSetup:23118:20)
workerd/io/io-context.c++:430: info: uncaught exception; exception = workerd/jsg/_virtual_includes/iterator/workerd/jsg/value.h:1480: failed: jsg.Error: PythonError: Traceback (most recent call last):
  File "/session/metadata/worker.py", line 202, in text
    raise ValueError("Test error")
ValueError: Test error

Comment on lines +1349 to +1352
to_js(
{"start": start_proxy},
dict_converter=Object.fromEntries,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
to_js(
{"start": start_proxy},
dict_converter=Object.fromEntries,
)
start=start_proxy

@ryanking13 ryanking13 marked this pull request as draft January 22, 2026 16:20
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.

2 participants