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.