clientgone

command
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: BSD-3-Clause Imports: 6 Imported by: 0

Documentation

Overview

Command clientgone rewrites a page to a destination that stops accepting bytes partway through, which is what a browser closing a connection looks like from inside a handler.

$ clientgone -budget 100
the destination accepted 99 bytes of rewritten output and then failed, with 760 bytes
of input offered to the rewriter
  reported by          Write
  errors.Is(gone)      true       from Write
  errors.Is(gone)      true       from Close, under ErrPoisoned=true
  links rewritten      2          the count when the rewrite stopped, not the page's total
  comments seen        2
  text chunks seen     6
  document end ran     false      <- a summary written there would not have run
  writes to the sink   30

What stops

Everything. Once the destination has refused a write, no further handler runs: the rewriter is abandoned, later output chunks are dropped, and the error surfaces from the call that was running. That includes the document-end handler, which is where a rewrite naturally puts its summary - so a program that logs its totals there logs nothing at all on the run where the client went away.

The accounting has to live outside the handlers to survive, which is what this program does: the counters are fields, readable after the failure, and they say what the rewrite had reached rather than what the page contains. Those are different numbers and only one of them is available.

Which call reports it

The one that was running. A destination failure during Write surfaces there; the Writer is poisoned, so every later Write and the Close report it again, wrapped - errors.Is finds the destination's own error through all of it.

Close can be the call that fails, but only when Close is the call that writes. Measured:

document                     written during Close
<p>text</p>                  nothing
<p>unclosed text             nothing
<script>var a =              nothing
<p>a</p                      the unfinished end tag
<div a="x                    the unfinished attribute
<!--unclosed                 the unfinished comment
<p>text</p><                 the bare less-than
any document, with a handler appending at the document end

-closes prints that table from a live measurement rather than from this comment.

So a document that ends cleanly, or in the middle of text, has already been handed over entirely by the time Close is called, and Close cannot discover a broken destination. A document that ends inside a token has not.

What the destination keeps

What it accepted. The rewriter does not retract anything, so a client that disconnected after 100 bytes has 100 bytes of a rewritten page - well-formed as far as it goes, and a short version of a document it asked for. Nothing can be done about that from inside the rewrite; it is an argument for buffering the output when a partial response is worse than no response, which is what examples/gip/mixed does.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL