Documentation
¶
Overview ¶
Package puma is a pure-Go (no cgo) reimplementation of Ruby's puma gem — the threaded Rack web server — matching the shape of the MRI `puma` gem.
It builds the server machinery on the Go standard library's net/http, and treats the Rack application as an injectable host seam: a RackApp is any value implementing the Rack `call(env)` contract
Call(env map[string]any) (status int, headers map[string][]string, body [][]byte)
The server accepts HTTP connections, translates each request into a Rack environment Hash (REQUEST_METHOD, SCRIPT_NAME, PATH_INFO, QUERY_STRING, SERVER_NAME/PORT, HTTP_* headers, rack.input, rack.url_scheme, CONTENT_TYPE / CONTENT_LENGTH, REMOTE_ADDR, …), invokes the application through a bounded ThreadPool, and writes the returned status/headers/body back to the client.
The MRI-faithful surface mirrors puma's Ruby classes: Server (with AddTCPListener / AddSSLListener / Run / Stop / Halt / GracefulShutdown), Configuration and DSL (bind, port, threads, workers, environment, on_worker_boot), ThreadPool, Launcher and [Const].
The application seam keeps the package free of any Ruby runtime: go-embedded-ruby supplies the Ruby Rack app through RackApp; here the app is a plain Go value, so the whole server is exercised in-process with real HTTP round-trips. Cluster (multi-worker fork) mode is out of scope for a single-process embed; the threaded single-process server is implemented faithfully.
This is the server for go-embedded-ruby, a sibling of go-ruby-rack (the Rack value types), go-ruby-sinatra and go-ruby-regexp.
Index ¶
- Constants
- Variables
- func StatusText(code int) string
- type Configuration
- type DSL
- type HTTPParserError
- type Launcher
- type LowlevelError
- type Options
- type RackApp
- type RackAppFunc
- type Server
- func (s *Server) AddSSLListener(host string, port int, cfg *tls.Config) (net.Addr, error)
- func (s *Server) AddTCPListener(host string, port int) (net.Addr, error)
- func (s *Server) AddUnixListener(path string) (net.Addr, error)
- func (s *Server) GracefulShutdown()
- func (s *Server) Halt()
- func (s *Server) Run()
- func (s *Server) Running() bool
- func (s *Server) Stop()
- func (s *Server) ThreadPool() *ThreadPool
- type ThreadPool
Constants ¶
const ServerSoftware = "puma " + Version
ServerSoftware is the SERVER_SOFTWARE / Server-header value, mirroring Puma::Const::PUMA_SERVER_STRING ("puma <version>").
const Version = "6.4.2"
Version is the puma-compatible version string reported in SERVER_SOFTWARE and the Server header. It mirrors Puma::Const::PUMA_VERSION / VERSION.
Variables ¶
var HTTPStatusCodes = map[int]string{
100: "Continue",
101: "Switching Protocols",
102: "Processing",
200: "OK",
201: "Created",
202: "Accepted",
203: "Non-Authoritative Information",
204: "No Content",
205: "Reset Content",
206: "Partial Content",
207: "Multi-Status",
208: "Already Reported",
226: "IM Used",
300: "Multiple Choices",
301: "Moved Permanently",
302: "Found",
303: "See Other",
304: "Not Modified",
305: "Use Proxy",
307: "Temporary Redirect",
308: "Permanent Redirect",
400: "Bad Request",
401: "Unauthorized",
402: "Payment Required",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
407: "Proxy Authentication Required",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
411: "Length Required",
412: "Precondition Failed",
413: "Payload Too Large",
414: "URI Too Long",
415: "Unsupported Media Type",
416: "Range Not Satisfiable",
417: "Expectation Failed",
418: "I'm A Teapot",
421: "Misdirected Request",
422: "Unprocessable Entity",
423: "Locked",
424: "Failed Dependency",
426: "Upgrade Required",
428: "Precondition Required",
429: "Too Many Requests",
431: "Request Header Fields Too Large",
451: "Unavailable For Legal Reasons",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
505: "HTTP Version Not Supported",
506: "Variant Also Negotiates",
507: "Insufficient Storage",
508: "Loop Detected",
510: "Not Extended",
511: "Network Authentication Required",
}
HTTPStatusCodes maps an HTTP status code to its reason phrase. It mirrors Puma::Const::HTTP_STATUS_CODES and is used when writing the status line.
Functions ¶
func StatusText ¶
StatusText returns the reason phrase for an HTTP status code, mirroring Puma's lookup into HTTP_STATUS_CODES with an "CUSTOM" fallback for unknown codes (as puma writes "<code> <text>" on the status line).
Types ¶
type Configuration ¶
type Configuration struct {
// contains filtered or unexported fields
}
Configuration is a faithful port of Puma::Configuration: the evaluated result of a config block, exposing the accumulated Options.
func NewConfiguration ¶
func NewConfiguration(blocks ...func(*DSL)) *Configuration
NewConfiguration evaluates zero or more config blocks against a fresh DSL seeded with DefaultOptions, mirroring Puma::Configuration.new { |c| ... }.
func (*Configuration) Options ¶
func (c *Configuration) Options() *Options
Options returns the configuration's accumulated options.
type DSL ¶
type DSL struct {
// contains filtered or unexported fields
}
DSL is a faithful port of Puma::DSL: the receiver of a puma config block. Each method records an option; the accumulated options are read back through a Configuration. Mirrors the puma config file DSL (bind, port, threads, …).
func (*DSL) Bind ¶
Bind adds a listener URL ("tcp://host:port", "ssl://host:port", "unix:///path"). Mirrors Puma::DSL#bind.
func (*DSL) Environment ¶
Environment sets the Rack environment, mirroring Puma::DSL#environment.
func (*DSL) OnWorkerBoot ¶
OnWorkerBoot registers a hook run once at worker boot, mirroring Puma::DSL#on_worker_boot.
func (*DSL) Port ¶
Port binds a TCP listener on the given port (host defaults to "0.0.0.0"), mirroring Puma::DSL#port(port, host = nil).
type HTTPParserError ¶
type HTTPParserError struct {
Message string
}
HTTPParserError mirrors Puma::HttpParserError — the error raised when an incoming request cannot be parsed into a valid HTTP message.
func NewHTTPParserError ¶
func NewHTTPParserError(msg string) *HTTPParserError
NewHTTPParserError builds an HTTPParserError with the given message.
func (*HTTPParserError) Error ¶
func (e *HTTPParserError) Error() string
type Launcher ¶
type Launcher struct {
// contains filtered or unexported fields
}
Launcher is a faithful port of Puma::Launcher: it takes a Configuration and a Rack app, opens the configured binds as listeners, runs the on_worker_boot hooks and starts the Server. Cluster (multi-process) mode is out of scope; the single worker runs in-process.
func NewLauncher ¶
func NewLauncher(config *Configuration, app RackApp) *Launcher
NewLauncher builds a launcher for the configuration and Rack app, mirroring Puma::Launcher.new(conf). The app is the Rack seam the launcher serves.
func (*Launcher) Halt ¶
func (l *Launcher) Halt()
Halt immediately stops the launched server, mirroring Puma::Launcher#halt.
func (*Launcher) Run ¶
Run opens every configured bind, fires the on_worker_boot hooks and starts serving, returning immediately (the server runs in the background). Mirrors Puma::Launcher#run for the single-process case. Use Stop / Halt to tear down.
type LowlevelError ¶
type LowlevelError func(err any, env map[string]any) (status int, headers map[string][]string, body [][]byte)
LowlevelError is the hook invoked when a Rack call raises (panics) or the server cannot otherwise produce a response, mirroring Puma::Server#lowlevel_error(e, env). It returns the Rack tuple written to the client. err is the recovered value; env is the request environment.
type Options ¶
type Options struct {
// Min / Max threads bound the Rack-call thread pool.
MinThreads int
MaxThreads int
// Workers is the cluster worker count. Cluster mode (fork) is out of scope
// for the single-process embed; the value is carried for surface parity.
Workers int
// Environment names the Rack environment ("development" / "production").
Environment string
// Binds are the listener URLs ("tcp://host:port", "ssl://host:port",
// "unix:///path"). Consumed by [Launcher].
Binds []string
// OnWorkerBoot hooks run once per (single) worker at boot, receiving the
// worker index (always 0 in single-process mode).
OnWorkerBoot []func(int)
// Lowlevel overrides the error handler; nil uses [defaultLowlevelError].
Lowlevel LowlevelError
// contains filtered or unexported fields
}
Options configures a Server / Launcher, mirroring the puma options Hash.
func DefaultOptions ¶
func DefaultOptions() *Options
DefaultOptions returns the puma defaults: threads 0..5, one worker, the "development" environment.
type RackApp ¶
type RackApp interface {
Call(env map[string]any) (status int, headers map[string][]string, body [][]byte)
}
RackApp is the injectable host seam: any value implementing the Rack `call(env)` contract. The server translates each incoming HTTP request into a Rack environment Hash, invokes Call, and writes the returned tuple back.
It returns the Rack `[status, headers, body]` triple: an integer status, a header map (each key mapping to one-or-more values), and a body as a sequence of byte chunks (each chunk is written and flushed in order, modelling Rack's enumerable body / streaming).
type RackAppFunc ¶
RackAppFunc adapts a plain function to the RackApp interface, mirroring how a Ruby Proc (`->(env){ ... }`) is a valid Rack app.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a faithful port of Puma::Server: a threaded Rack web server over one or more listeners. It accepts connections through net/http, shapes each request into a Rack env, runs the app through a bounded ThreadPool and writes the response back.
func NewServer ¶
NewServer builds a server for app with the given options (nil uses DefaultOptions), mirroring Puma::Server.new(app, options).
func (*Server) AddSSLListener ¶
AddSSLListener binds a TLS listener on host:port with the given config and returns the resolved local address, mirroring Puma::Server#add_ssl_listener.
func (*Server) AddTCPListener ¶
AddTCPListener binds a plain-HTTP TCP listener on host:port and returns the resolved local address, mirroring Puma::Server#add_tcp_listener. A port of 0 selects an ephemeral port.
func (*Server) AddUnixListener ¶
AddUnixListener binds a Unix-domain listener at path, mirroring puma's `unix://` binds. It returns the listener address. Unix sockets are only available on non-Windows platforms; see addUnixListener.
func (*Server) GracefulShutdown ¶
func (s *Server) GracefulShutdown()
GracefulShutdown is an alias for a bounded graceful stop, mirroring puma's graceful shutdown that drains in-flight requests before exiting.
func (*Server) Halt ¶
func (s *Server) Halt()
Halt performs an immediate shutdown: connections are closed at once and the pool is torn down without waiting to drain. Mirrors Puma::Server#halt.
func (*Server) Run ¶
func (s *Server) Run()
Run starts serving on every added listener and returns immediately, mirroring Puma::Server#run (which returns a thread handle). Use Stop / Halt / GracefulShutdown to tear the server down. It is a no-op if already running.
func (*Server) Stop ¶
func (s *Server) Stop()
Stop performs a graceful shutdown: it stops accepting new connections, lets in-flight requests finish, then drains the thread pool. Mirrors Puma::Server#stop(true) / graceful stop.
func (*Server) ThreadPool ¶
func (s *Server) ThreadPool() *ThreadPool
ThreadPool returns the server's Rack-call thread pool.
type ThreadPool ¶
type ThreadPool struct {
// contains filtered or unexported fields
}
ThreadPool is a faithful port of Puma::ThreadPool: a pool of worker threads (goroutines) that runs scheduled blocks, growing on demand from Min up to Max and reaping idle workers back down to Min. Concurrency of Rack calls is bounded by Max; excess work waits in the backlog.
func NewThreadPool ¶
func NewThreadPool(min, max int) *ThreadPool
NewThreadPool builds a pool bounded by [min, max] worker threads and immediately spawns the minimum, mirroring Puma::ThreadPool.new(min, max).
func (*ThreadPool) Backlog ¶
func (tp *ThreadPool) Backlog() int
Backlog returns the number of scheduled blocks not yet picked up by a worker.
func (*ThreadPool) Schedule ¶
func (tp *ThreadPool) Schedule(work func())
Schedule enqueues a block to run on the pool, spawning an extra worker (up to Max) when the backlog outgrows the idle workers. It is a no-op after Shutdown.
func (*ThreadPool) Shutdown ¶
func (tp *ThreadPool) Shutdown()
Shutdown stops accepting new work, wakes every worker and blocks until all in-flight and backlogged blocks have drained. Mirrors Puma::ThreadPool#shutdown.
func (*ThreadPool) Spawned ¶
func (tp *ThreadPool) Spawned() int
Spawned returns the current number of live worker threads.
func (*ThreadPool) Trim ¶
func (tp *ThreadPool) Trim(force bool)
Trim requests that one idle worker above Min exit. With force it also trims when no worker is currently idle. Mirrors Puma::ThreadPool#trim.
