Repository navigation
Bind pure-Go webrick into rbgo (require "webrick") - #201
Closed
tannevaled wants to merge 1 commit into
Closed
tannevaled wants to merge 1 commit into
tannevaled wants to merge 1 commit into
Conversation
Bind github.com/go-ruby-webrick/webrick — the pure-Go (CGO=0) port of
Ruby's WEBrick HTTP server core — into rbgo so `require "webrick"` works
with no .rb file.
The library owns the deterministic request parse, response build, status
table and longest-prefix mount dispatch and does no socket I/O; this shell
maps that surface onto Ruby classes:
- WEBrick::HTTPServer.new(config) + #mount_proc { |req, res| … } / #mount
(AbstractServlet subclass or instance) / #unmount / #service / #config
(#start/#shutdown/#stop are the host accept-loop seam, no-ops here).
- WEBrick::HTTPRequest.new + #parse(str) and the parsed accessors
(request_method / path / query / headers / keep_alive? / body / each …).
- WEBrick::HTTPResponse.new with the status/header/body accessors,
#set_redirect, #set_error and #to_s (the wire bytes).
- WEBrick::HTTPServlet::AbstractServlet base class (do_<METHOD> contract).
- WEBrick::HTTPStatus: reason_phrase, the range predicates, and the Status
exception family (each named leaf carrying its code).
The request-handler seam — a mount_proc block or a servlet's do_<METHOD>
method — is the injectable Ruby code the engine leaves open. Because the
core does no I/O and starts no goroutines, #service is driven on the VM
goroutine under the GVL and the handler runs inline (vm.callBlock /
vm.send), so nothing leaks; a handler that raises a WEBrick::HTTPStatus is
recovered and rendered as the matching error response, exactly as
WEBrick::HTTPServer#run rescues HTTPStatus::Status.
Tests drive requests through the server object in-process (build a
HTTPRequest, dispatch via #service, assert the HTTPResponse) with no
listening socket. 100% coverage of the new files; -race clean; green on
all six 64-bit arches.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
Author
|
Superseded by the net-wave consolidation PR (single merge onto main; shared builtins/require/object_model). Work preserved verbatim; branch kept. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Binds github.com/go-ruby-webrick/webrick — the pure-Go (CGO=0) port of Ruby's WEBrick HTTP server core — into rbgo so
require "webrick"works with no.rbfile.Surface
The library owns the deterministic request parse, response build,
HTTPStatustable and longest-prefix mount dispatch, and does no socket I/O (the TCP accept loop is a host seam). This shell maps that onto Ruby classes:WEBrick::HTTPServer—.new(Port:, ServerName:, ServerSoftware:),#mount_proc(dir){ |req,res| … },#mount(dir, servlet)(anAbstractServletsubclass instantiated per request, or a pre-built instance),#unmount/#umount,#service(req, res),#config.#start/#run/#shutdown/#stopare the host accept-loop seam — no-ops here.WEBrick::HTTPRequest—.new(config=nil),#parse(str), and the parsed accessors:request_method,unparsed_uri,path,script_name,path_info,query_string,http_version,host,port,keep_alive?,content_length,content_type,body,query,[],each.WEBrick::HTTPResponse—.new(config=nil),#request=,status/status=,reason_phrase,status_line,[]/[]=,content_type/content_type=,content_length=,body/body=,chunked?/chunked=,keep_alive?,#set_redirect,#set_error,#to_s(the wire bytes).WEBrick::HTTPServlet::AbstractServlet— thedo_<METHOD>servlet base class.WEBrick::HTTPStatus—reason_phrase, the range predicates (info?…server_error?), and theStatusexception family (each named leaf carrying its code, with#code/#to_i/#reason_phrase).Request-handler seam
A
mount_procblock or a servlet'sdo_<METHOD>method is the injectable Ruby handler. Because the core does no I/O and starts no goroutines,#serviceis driven on the VM goroutine while it holds the GVL, so the handler runs inline (vm.callBlock/vm.send) with no extra goroutine and nothing to leak. A handler that raises aWEBrick::HTTPStatusunwinds as a Go panic through the library's dispatch back towebrickService, which recovers it and renders the matching error response — exactly asWEBrick::HTTPServer#runrescuesHTTPStatus::Status. A servlet is dispatched through a libraryAbstractServlet, soHEAD→GET, theOPTIONSAllow list andMethodNotAllowedcome from the library, over the Ruby methods.Tests / verification
Tests drive requests through the server object in-process (build a
HTTPRequest, dispatch via#service, assert theHTTPResponse) — no listening socket, no port bind.0;go vet0;gofmt -lclean.webrick.go,webrick_bind.go)../...suite green;-raceclean (no goroutine leaks).GOOS=linuxbuild green: amd64, arm64, riscv64, loong64, ppc64le, s390x.🤖 Generated with Claude Code