Help us shape the future of Go! Take the 2026 Go Developer Survey

http

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package http serves Octomaton's endpoints: GitHub's webhook deliveries and the Kubernetes probes.

Index

Constants

View Source
const MaxBodyBytes = 25 << 20

MaxBodyBytes is the largest payload accepted (GitHub caps payloads at 25 MB).

View Source
const SignatureHeader = "X-Hub-Signature-256"

SignatureHeader carries the HMAC-SHA256 signature of the request body.

View Source
const WebhookPath = "/github/hooks"

WebhookPath is where GitHub delivers the App's webhooks.

Variables

This section is empty.

Functions

func Sign

func Sign(secret, body []byte) string

Sign returns the X-Hub-Signature-256 header value for body (used by tests and tools).

func VerifySignature

func VerifySignature(secrets [][]byte, body []byte, header string) bool

VerifySignature reports whether header ("sha256=<hex>") is the HMAC-SHA256 of body keyed with any one of secrets, so deliveries signed with an old or a new secret both pass while the App's secret is rotated. Every secret is tried, each compared in constant time; an empty secret never verifies.

Types

type Decoder

type Decoder interface {
	// Handles reports whether Decode handles an event, by its X-GitHub-Event name.
	Handles(event string) bool
	// Decode turns a delivery into an event. It returns no event, and the reason, for deliveries
	// Octomaton ignores, and an error for payloads it cannot parse.
	Decode(event, delivery string, body []byte) (ci.Event, string, error)
}

Decoder turns verified deliveries into events; the GitHub adapter's App implements it.

type Dedupe

type Dedupe struct {
	// contains filtered or unexported fields
}

Dedupe remembers recently seen delivery IDs (bounded LRU with a TTL) so that redelivered webhooks are processed once per replica, unless processing failed (Remove).

func NewDedupe

func NewDedupe(max int, ttl time.Duration) *Dedupe

NewDedupe creates a cache holding at most max IDs for ttl each.

func (*Dedupe) Add

func (d *Dedupe) Add(id string) bool

Add records id and reports whether it was not seen within the TTL.

func (*Dedupe) Remove

func (d *Dedupe) Remove(id string)

Remove forgets id, so that a redelivery is accepted (used when a delivery could not be queued, or its handling failed).

type EventHandler

type EventHandler interface {
	Handle(ctx context.Context, ev ci.Event) error
}

EventHandler does what an event asks for; the runs service implements it. It returns an error when it left part of the event undone, which a redelivery may do.

type Forwarder

type Forwarder interface {
	Forward(header http.Header, body []byte)
}

Forwarder receives verified push and ping deliveries (*relay.Relay implements it).

type Handler

type Handler struct {
	// Secrets are the App's webhook secrets: a delivery signed with any one of them is accepted.
	Secrets [][]byte
	Decoder Decoder
	Events  EventHandler
	Pool    *Pool
	Dedupe  *Dedupe
	Metrics *metrics.Metrics
	Logger  *slog.Logger
	// Relay, when set, receives verified push and ping deliveries.
	Relay Forwarder
}

Handler serves POST /github/hooks: it verifies signatures, decodes deliveries, drops duplicates and hands the events to a bounded worker pool. A delivery is a duplicate while an earlier copy is being handled or was handled; one whose handling failed is forgotten, so its redelivery (GitHub keeps the delivery's ID) is handled again.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Job

type Job struct {
	// Name describes the job in logs.
	Name string
	Run  func(ctx context.Context)
}

Job is a unit of asynchronous webhook processing.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool runs jobs on a fixed number of workers fed by a bounded queue.

func NewPool

func NewPool(workers, queueSize int, jobTimeout time.Duration, logger *slog.Logger, m *metrics.Metrics) *Pool

NewPool starts workers goroutines consuming a queue of queueSize jobs; each job runs with a timeout of jobTimeout.

func (*Pool) Shutdown

func (p *Pool) Shutdown(ctx context.Context) error

Shutdown stops accepting jobs and waits for queued and running jobs to finish; when ctx expires first, running jobs are cancelled.

func (*Pool) Submit

func (p *Pool) Submit(job Job) bool

Submit queues a job without blocking; it returns false when the queue is full or the pool is shutting down.

type Readiness

type Readiness struct {
	// Ping checks that the Kubernetes API server answers.
	Ping func(ctx context.Context) error
	// Leading reports whether this replica is the elected leader.
	Leading func() bool
	// Synced reports whether the leader's PipelineRun informer has synced.
	Synced func() bool
	// TTL is how long a Ping result is reused, so that frequent probes do not load the API server.
	TTL time.Duration
	// contains filtered or unexported fields
}

Readiness answers the readiness probe. A replica is ready while the Kubernetes API server answers and, on the leader, once the PipelineRun informer has synced; a replica shutting down never is.

func (*Readiness) ServeHTTP

func (rd *Readiness) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server serves the webhook and the probes on one address.

func NewServer

func NewServer(address string, webhook http.Handler, readiness *Readiness) *Server

NewServer returns a server for address. Webhook requests are traced and measured with OpenTelemetry.

func (*Server) Run

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

Run serves until ctx is cancelled, then fails the readiness probe, stops accepting connections and waits up to shutdownTimeout for requests in flight. It returns an error only when the server cannot serve.

Jump to

Keyboard shortcuts

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