server

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

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

Examples

Constants

View Source
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

func New(cfg Config) (*Server, error)

New builds a Server from cfg. Storage is required. Configuration defaults are applied for any zero-valued fields.

func (*Server) HTTPServer

func (s *Server) HTTPServer() *http.Server

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

func (s *Server) Handler() http.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

func (s *Server) ListenAndServe(ctx context.Context) error

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

func (s *Server) ReloadCertificate() error

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.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, ln net.Listener) error

Serve pre-creates configured buckets and serves on ln until ctx is canceled, then performs a graceful shutdown. It returns nil on a clean shutdown.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the underlying HTTP server.

type TLSConfig added in v0.5.0

type TLSConfig struct {
	// CertFile and KeyFile are the PEM certificate and private key paths.
	CertFile string
	KeyFile  string
}

TLSConfig configures TLS termination with certificates reloaded from disk.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL