go-ruby-cgi

Ruby's CGI escaping & query-parsing methods in pure Go โ€” MRI-compatible, no cgo.

pure Go ยท zero cgo CGI-compatible Escape / Unescape EscapeURIComponent EscapeHTML / UnescapeHTML EscapeElement ParseQuery MRI byte-exact 100% coverage 6 arches
Documentation GitHub
Documentation (MkDocs Material + mike) License: BSD-3-Clause Go 1.26.4+ Coverage 100%

go-ruby-cgi is a pure-Go (no cgo) reimplementation of the escaping and query-parsing surface of Ruby's CGI utility methods โ€” the deterministic core of MRI 4.0.5's CGI.escape / CGI.unescape, the HTML-entity helpers, the URI-component helpers, the element helpers and CGI.parse. Every method matches the system ruby byte-for-byte, with no Ruby runtime. URL/form escaping, HTML-entity coding and query parsing are pure, deterministic string transforms, so they live here as pure Go; the request/response cycle, cookies, multipart handling and the HTML-generation DSL are out of scope by design โ€” this library is the compute core only. It was extracted from rbgo into a reusable standalone library: no dependency on the Ruby runtime, the dependency runs the other way. It is the CGI backend for go-embedded-ruby, bound by rbgo as a native module just like go-ruby-yaml, go-ruby-regexp and go-ruby-erb โ€” differential-tested against MRI, 100% coverage, CI green across 6 arches and 3 OSes.

Escape / Unescape ready

application/x-www-form-urlencoded: every byte outside the unreserved set Aโ€“Z aโ€“z 0โ€“9 - . _ ~ is percent-encoded (uppercase hex), a space becomes +, and Unescape decodes +โ†’space and %XX, leaving malformed escapes verbatim โ€” it never raises.

EscapeURIComponent / UnescapeURIComponent ready

Like the form encoders but a space is %20 (and Unescape does not treat + as a space) โ€” CGI.escapeURIComponent / CGI.unescapeURIComponent.

EscapeHTML / UnescapeHTML ready

Encodes & < > " ' (the apostrophe as &#39;); decoding recognises those five names plus &apos;, decimal &#NN; and hex &#xHH; / &#XHH; numeric entities (emitting raw UTF-8 bytes, surrogates included, exactly as MRI does), rejecting unknown or overflowing entities verbatim.

EscapeElement / UnescapeElement ready

HTML-(un)escape only the start/end tags of named elements, matching the element name case-insensitively at a word boundary โ€” CGI.escapeElement / CGI.unescapeElement.

ParseQuery ready

CGI.parse: split on & and ;, form-decode keys and values, accumulate repeated keys, and return an empty slice for a bare key. (In MRI 4.0 CGI.parse ships in the separate cgi gem.)

Differential oracle & coverage ready

Deterministic golden tests (which alone hold coverage at 100%) plus a differential oracle: a corpus run through the system ruby (CGI.escape, CGI.unescapeHTML, CGI.parse, โ€ฆ) and compared byte-for-byte; 100% coverage, gofmt + go vet clean, green across all six 64-bit Go arches and three OSes.

A faithful port of Ruby's CGI escaping and query-parsing methods in pure Go, cgo disabled, so it cross-compiles and embeds anywhere. It percent-encodes form and URI components, encodes and decodes HTML entities (named, decimal and hex numeric), escapes named element tags, and parses query strings โ€” every transform deterministic and dependency-free. Validated differentially against the system ruby binary โ€” CGI.escape, CGI.unescapeHTML, CGI.parse compared byte-for-byte. It is a standalone, reusable module extracted from rbgo's internals, and the CGI backend for the sibling org github.com/go-embedded-ruby.