Documentation
¶
Overview ¶
Package server provides an embeddable S3-compatible HTTP server.
It exposes the go-faster/fs S3 implementation as a library: construct a storage backend (for example github.com/go-faster/fs/storagefs) and either build a bare http.Handler to mount into your own server, or use the Server type for a turnkey HTTP server with health checks, timeouts and graceful shutdown.
The package deliberately does not pull in any observability stack. Wrap the handler yourself (for example with otelhttp) via Config.WrapHandler or by wrapping the result of NewHandler.
Index ¶
- Constants
- func NewHandler(store fs.Storage, opts ...HandlerOption) http.Handler
- type Config
- type HandlerOption
- type Server
- func (s *Server) HTTPServer() *http.Server
- func (s *Server) Handler() http.Handler
- func (s *Server) ListenAndServe(ctx context.Context) error
- func (s *Server) ReloadCertificate() error
- func (s *Server) Serve(ctx context.Context, ln net.Listener) error
- func (s *Server) Shutdown(ctx context.Context) error
- type TLSConfig
Examples ¶
Constants ¶
const ( DefaultAddr = ":8080" DefaultReadTimeout = 30 * time.Second DefaultWriteTimeout = 30 * time.Second DefaultIdleTimeout = 120 * time.Second DefaultHealthPath = "/health" DefaultReadyPath = "/ready" )
Default server configuration values.
Variables ¶
This section is empty.
Functions ¶
func NewHandler ¶
func NewHandler(store fs.Storage, opts ...HandlerOption) http.Handler
NewHandler returns the S3-compatible http.Handler for a storage backend, wiring the validation layer and the request router. Mount it into your own http.Server or mux to embed the S3 API. Options enable authentication and CORS.
Example ¶
ExampleNewHandler demonstrates the low-level API: build a bare http.Handler for a storage backend and mount it into your own server or mux.
package main
import (
"fmt"
"log"
"net/http"
"net/http/httptest"
"github.com/go-faster/fs/server"
"github.com/go-faster/fs/storagemem"
)
func main() {
store := storagemem.New()
h := server.NewHandler(store)
// Mount under a prefix in your own mux.
mux := http.NewServeMux()
mux.Handle("/s3/", http.StripPrefix("/s3", h))
ts := httptest.NewServer(mux)
defer ts.Close()
// Create a bucket via the embedded S3 API.
req, _ := http.NewRequest(http.MethodPut, ts.URL+"/s3/example-bucket", http.NoBody)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer func() { _ = resp.Body.Close() }()
fmt.Println(resp.StatusCode)
}
Output: 200
Types ¶
type Config ¶
type Config struct {
// Storage is the backend used to serve S3 operations. Required.
Storage fs.Storage
// Addr is the TCP address to listen on. Defaults to DefaultAddr (":8080").
Addr string
// ReadTimeout, WriteTimeout and IdleTimeout configure the underlying
// http.Server. Zero values fall back to the Default* constants.
ReadTimeout time.Duration
WriteTimeout time.Duration
IdleTimeout time.Duration
// HealthPath is the path serving a plaintext "OK" liveness check. Defaults to
// DefaultHealthPath ("/health"). Set to "-" to disable the health endpoint.
HealthPath string
// ReadyPath is the path serving a readiness check. Defaults to
// DefaultReadyPath ("/ready"). Set to "-" to disable it. Unlike health
// (liveness: the process is up), readiness reports whether the server can
// actually serve — see Ready.
ReadyPath string
// Ready is the readiness probe. When nil, the server is ready as soon as it
// is serving. When set, /ready runs it per request: a nil result is 200, a
// non-nil result is 503 with the error message (e.g. storage unreachable).
Ready func(context.Context) error
// Buckets are created (if absent) before the server begins serving in
// ListenAndServe / Serve.
Buckets []string
// Auth, if set, enables SigV4 authentication and grant-based authorization.
// Its snapshot can be hot-reloaded via (*auth.Store).Set. Nil serves
// anonymously.
Auth *auth.Store
// CORS, if non-empty, enables per-bucket CORS (preflight + headers).
CORS cors.Config
// TLS, if set, serves HTTPS with hot-reloadable certificates.
TLS *TLSConfig
// WrapHandler, if set, wraps the composed handler (health endpoint + S3
// router) before it is served. This is the injection point for
// observability or middleware, e.g. otelhttp.NewHandler or request logging.
WrapHandler func(http.Handler) http.Handler
}
Config configures a Server.
type HandlerOption ¶ added in v0.5.0
type HandlerOption func(*handlerOptions)
HandlerOption configures the handler built by NewHandler.
func WithAuth ¶ added in v0.5.0
func WithAuth(store *auth.Store) HandlerOption
WithAuth enables SigV4 authentication and grant-based authorization on the handler. Without it the handler serves anonymously (the library default).
func WithCORS ¶ added in v0.5.0
func WithCORS(cfg cors.Config) HandlerOption
WithCORS enables per-bucket CORS (OPTIONS preflight + response headers).
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is an embeddable S3-compatible HTTP server with health checks, timeouts and graceful shutdown.
Example ¶
ExampleServer demonstrates the high-level API: a turnkey server with a health endpoint, timeouts and graceful shutdown driven by a context.
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/go-faster/fs/server"
"github.com/go-faster/fs/storagemem"
)
func main() {
store := storagemem.New()
srv, err := server.New(server.Config{
Storage: store,
Addr: "127.0.0.1:0", // ephemeral port
Buckets: []string{"example-bucket"},
HealthPath: "/health",
// WrapHandler is the injection point for observability or middleware,
// e.g. otelhttp.NewHandler(h, "s3") or a request logger.
})
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
done := make(chan error, 1)
go func() { done <- srv.ListenAndServe(ctx) }()
// ... serve requests ...
time.Sleep(10 * time.Millisecond)
cancel() // trigger graceful shutdown
if err := <-done; err != nil {
log.Fatal(err)
}
fmt.Println("stopped cleanly")
}
Output: stopped cleanly
func New ¶
New builds a Server from cfg. Storage is required. Configuration defaults are applied for any zero-valued fields.
func (*Server) HTTPServer ¶
HTTPServer returns the underlying *http.Server, allowing callers to set advanced fields (ConnContext, BaseContext, ErrorLog, TLSConfig, ...) before calling ListenAndServe or Serve. The Handler, Addr and timeout fields are managed by New and should not be replaced.
func (*Server) Handler ¶
Handler returns the composed http.Handler (S3 router, optional health and readiness endpoints and Config.WrapHandler). It can be mounted directly without using ListenAndServe.
func (*Server) ListenAndServe ¶
ListenAndServe pre-creates configured buckets, listens on Config.Addr and serves until ctx is canceled, then performs a graceful shutdown. It returns nil on a clean shutdown.
func (*Server) ReloadCertificate ¶ added in v0.5.0
ReloadCertificate re-reads the TLS certificate and key from disk, applying them to new connections without interrupting the listener. It is a no-op when TLS is not configured.