actionheader

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package actionheader selects one application action from a configured HTTP request header. It uses only the standard library, so native HTTP servers and Lambda adapters can share the same selection rules. Consumers own action metadata, registry lookup, authorization and HTTP responses.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrMissing means the configured header has no represented values.
	// An absent header and a nil or empty value slice are all missing.
	ErrMissing = errors.New("actionheader: missing action")

	// ErrAmbiguous means the header has multiple represented values or a value containing a comma.
	// Gateway payload 2.0 combines duplicates with commas;
	// a literal comma cannot be distinguished from combined values.
	ErrAmbiguous = errors.New("actionheader: ambiguous action")

	// ErrInvalid means the single action value is empty after trimming outer spaces and tabs, or does not satisfy the HTTP token grammar.
	ErrInvalid = errors.New("actionheader: invalid action")
)

Functions

This section is empty.

Types

type Selector

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

Selector selects an action from a configured request header. Construct it with NewSelector; its zero value is unconfigured. A Selector is immutable, safe to copy, and safe for concurrent use.

Example
package main

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/asteroid-computing/go-lambda-edge/actionheader"
)

// These are consumer-owned middleware and metadata, not actionheader API types.
type actionKey struct{}

func processActionHeaders(selector actionheader.Selector, next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		action, err := selector.Parse(r.Header)
		if err != nil {
			http.Error(w, "invalid action selection", http.StatusBadRequest)
			return
		}
		ctx := context.WithValue(r.Context(), actionKey{}, action)
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

func main() {
	selector, err := actionheader.NewSelector("Action")
	if err != nil {
		fmt.Println(err)
		return
	}
	dispatcher := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		action, ok := r.Context().Value(actionKey{}).(string)
		if !ok {
			http.Error(w, "missing action metadata", http.StatusInternalServerError)
			return
		}
		// This example operation is public.
		// Protected operations must authorize this same selection before executing or publishing streaming output.
		switch action {
		case "service.ping":
			fmt.Fprintln(w, "pong")
		default:
			http.Error(w, "unknown action", http.StatusBadRequest)
		}
	})
	// The composed http.Handler serves native HTTP directly or goes to an edge adapter unchanged.
	handler := processActionHeaders(selector, dispatcher)
	r := httptest.NewRequest(http.MethodPost, "/", nil)
	r.Header.Set("Action", "service.ping")
	w := httptest.NewRecorder()
	handler.ServeHTTP(w, r)
	fmt.Println(w.Code)
	fmt.Print(w.Body.String())
}
Output:
200
pong

func NewSelector

func NewSelector(name string) (Selector, error)

NewSelector validates name as an HTTP field name and returns a selector. The name is required and matched case-insensitively; no default is inferred. On error, the returned selector is the zero value. Configuration errors are separate from ErrMissing, ErrAmbiguous and ErrInvalid.

func (Selector) Parse

func (s Selector) Parse(headers http.Header) (string, error)

Parse returns the single action in headers, trimming only outer SP/HTAB and preserving case. An action must be a nonempty HTTP token (RFC 9110 §5.6.2). Parse inspects all case-insensitive aliases, including noncanonical map keys. Multiple values are ambiguous even if identical; a comma is also ambiguous. Multiplicity and comma checks take precedence over token validation. Duplicates already lost by a gateway or earlier proxy cannot be detected.

On failure Parse returns an empty string and ErrMissing, ErrAmbiguous or ErrInvalid, matchable with errors.Is. An unconfigured selector instead returns a configuration error. Errors do not include supplied header values. Parse does not modify headers or write an HTTP response. Callers must not mutate headers concurrently with Parse. Select once and use that same action for authorization and execution.

Jump to

Keyboard shortcuts

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