shuttle

package module
v2.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2025 License: MIT Imports: 12 Imported by: 0

README

SMARTY DISCLAIMER: Subject to the terms of the associated license agreement, this software is freely available for your use. This software is FREE, AS IN PUPPIES, and is a gift. Enjoy your new responsibility. This means that while we may consider enhancement requests, we may or may not choose to entertain requests at our sole and absolute discretion.

Shuttle

Purpose

Shuttle transforms HTTP requests into intention-revealing, user instructions to be processed by the application. After processing the given operation, shuttle then renders the results of that operation back to the underlying HTTP response.

How to Use:

See the code in the /sample folder.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrDeserializationFailure indicates that there was some kind of problem deserializing the request stream.
	ErrDeserializationFailure = errors.New("failed to deserialize the stream into the instance provided")

	// ErrSerializationFailure indicates that there was some kind of problem serializing the structure to the response stream.
	ErrSerializationFailure = errors.New("failed to serialize the instance into the stream provided")
)
View Source
var Options singleton

Functions

func NewHandler

func NewHandler(options ...option) http.Handler

func ReadNumericPathElement

func ReadNumericPathElement(rawPath, upstreamElement string) uint64

func ReadPathElement

func ReadPathElement(rawPath, upstreamElement string) string

Types

type BaseInputModel

type BaseInputModel struct{}

BaseInputModel allows enables struct embedding such that other InputModels don't necessarily need to re-implement each method.

func (*BaseInputModel) Bind

func (*BaseInputModel) Bind(*http.Request) error

func (*BaseInputModel) Reset

func (*BaseInputModel) Reset()

func (*BaseInputModel) Validate

func (*BaseInputModel) Validate([]error) int

type BinaryResult

type BinaryResult struct {

	// StatusCode, if provided, use this value, otherwise HTTP 200.
	StatusCode int

	// ContentType, if provided, use this value.
	ContentType string

	// ContentDisposition, if provided, use this value.
	ContentDisposition string

	// Headers, if provided, are added to the response
	Headers map[string][]string

	// Content, if provided, use this value, otherwise no content will be written to the response stream.
	Content []byte
}

BinaryResult provides the ability render a result which contains binary data.

type CSV added in v2.2.0

type CSV interface {
	// Header returns all the column names for the CSV
	Header() []string
	// CSV returns an iterator that returns one row at a time to be rendered to the CSV
	CSV() iter.Seq[[]string]
}

CSV instances provide the ability to render CSV responses

type DeserializeBody

type DeserializeBody interface {
	Body() any
}

DeserializeBody is an interface that is optionally implemented by a given InputModel and is used to provide the target instance into which the HTTP request body will be deserialized.

type Deserializer

type Deserializer interface {
	// Deserialize renders the decodes the source stream into the instance provided. If there are any problems, an error is returned.
	Deserialize(any, io.Reader) error
}

Deserializer instances provide the ability to transform an opaque byte stream into an instance of a structure.

type InputError

type InputError struct {

	// Fields indicates the exact location(s) of the errors including the part of the HTTP request itself this is
	// invalid. Valid field prefixes include "path", "query", "header", "form", and "body".
	Fields []string `json:"fields,omitempty"`

	// ID represents the unique, numeric contractual identifier that can be used to associate this error with a particular front-end error message, if any.
	ID int `json:"id,omitempty"`

	// Name represents the unique string-based, contractual value that can be used to associate this error with a particular front-end error message, if any.
	Name string `json:"name,omitempty"`

	// Message represents a friendly, user-facing message to indicate why there was a problem with the input.
	Message string `json:"message,omitempty"`

	// Context represents a error-specific value in the form a serializable instance that the client can use to get more understanding about the error itself.
	Context any `json:"context,omitempty"`
}

InputError represents some kind of problem with the calling HTTP request.

func (InputError) Error

func (this InputError) Error() string

type InputErrors

type InputErrors struct {
	Errors []error `json:"errors,omitempty"`
}

InputErrors represents a set of problems with the calling HTTP request.

type InputModel

type InputModel interface {
	// Reset clears the contents of the instance and prepares it for the next use.
	Reset()
	// Bind maps the values on the HTTP request provided to fields on the instance. If there are any problems and error
	// is returned which can then be rendered on the response using the configured callback.
	Bind(*http.Request) error
	// Validate ensures that the instance has all the necessary fields appropriately populated. The slice of errors
	// provided is a pre-allocated buffer in which to place any errors encountered during validation. It returns the
	// number of errors placed into the buffer provided.
	Validate([]error) int
}

InputModel represents user input from the HTTP request. Generally speaking, each type represents an operation, intention, or instruction. Each intention or operation should be a separate, well-named structure. By design in this library, each instance will be reusable and long lived.

As a best practice or design note and to assert application correctness, the fields of any given InputModel should be explicitly initialized and populated using garbage or junk values to ensure they are properly Reset.

type Monitor

type Monitor interface {
	HandlerCreated()
	RequestReceived()
	NotAcceptable()
	UnsupportedMediaType()
	Deserialize()
	DeserializeFailed()
	ParseForm()
	ParseFormFailed(error)
	Bind()
	BindFailed(error)
	Validate()
	ValidateFailed([]error)
	TextResult()
	BinaryResult()
	StreamResult()
	SerializeResult()
	NativeResult()
	SerializeFailed()
	ResponseStatus(int)
	ResponseFailed(error)
}

type Processor

type Processor interface {
	Process(context.Context, any) any
}

Processor represents the mechanism used to carry out the desired instruction or user-provided intention. The second value is deliberately left opaque to reduce library dependencies and to encourage proper type discovery of the InputModel provided.

Depending upon how the processor is implemented (e.g. stateless and shared vs stateful between unique requests), the result returned can be allocated in the Processor instance and returned, or it can be a stateful field somewhere in the Processor's object graph.

For Processors that are shared and where each response pathway is stored as a field in the Processor's object graph, it may be helpful to follow the InputModel pattern of initializing with garbage or junk values. This will help to ensure that all fields are appropriately cleared and overwritten between requests.

The value returned by the processor may be a primitive type, a TextResult, BinaryResult, StreamResult, SerializeResult or the aforementioned types using a pointer. If the value returned implements the http.Handler interface, that method will be invoked to render the result directly using the underlying http.Request and http.ResponseWriter. If the value returned is not one of the aforementioned types, it will be serialized using either the requested HTTP Accept type or it will use the default serializer configured, if any.

type Reader

type Reader interface {
	Read(InputModel, *http.Request) any
}

Reader provides the ability to read values from the incoming HTTP request and to either manipulate the associated InputModel in some fashion or to otherwise short-circuit the request pipeline by returning a result to be rendered the caller's HTTP response stream. If a nil (meaning successful) result is returned, then processing continues.

type ResultContainer

type ResultContainer interface {
	SetContent(any)
	Result() any
}

ResultContainer sets the content on the underlying instance.

type SerializeResult

type SerializeResult struct {

	// StatusCode, if provided, use this value, otherwise HTTP 200.
	StatusCode int

	// ContentType, if provided, use this value.
	ContentType string

	// Headers, if provided, are added to the response
	Headers map[string][]string

	// Content, if provided, use this value, otherwise no content will be written to the response stream.
	Content any
}

SerializeResult provides the ability render a serialized result.

func (*SerializeResult) Result

func (this *SerializeResult) Result() any

func (*SerializeResult) SetContent

func (this *SerializeResult) SetContent(value any)

type Serializer

type Serializer interface {
	// Serialize renders the instance provided to the io.Writer. If there are any problems, an error is returned.
	Serialize(io.Writer, any) error
	// ContentType returns HTTP Content-Type header that will be used when writing to the HTTP response.
	ContentType() string
}

Serializer instances provide the ability to transform an instance of a structure into a byte stream.

func NewCSVSerializer added in v2.2.1

func NewCSVSerializer() Serializer

func NewJSONSerializer added in v2.2.1

func NewJSONSerializer() Serializer

type StreamResult

type StreamResult struct {

	// StatusCode, if provided, use this value, otherwise HTTP 200.
	StatusCode int

	// ContentType, if provided, use this value.
	ContentType string

	// ContentDisposition, if provided, use this value.
	ContentDisposition string

	// Headers, if provided, are added to the response
	Headers map[string][]string

	// Content, if provided, use this value, otherwise no content will be written to the response stream.
	Content io.Reader
}

StreamResult provides the ability render a result which is streamed from another source.

type TextResult

type TextResult struct {

	// StatusCode, if provided, use this value, otherwise HTTP 200.
	StatusCode int

	// ContentType, if provided, use this value.
	ContentType string

	// Headers, if provided, are added to the response
	Headers map[string][]string

	// Content, if provided, use this value, otherwise no content will be written to the response stream.
	Content string
}

TextResult provides the ability render a result which contains text.

type Writer

type Writer interface {
	Write(http.ResponseWriter, *http.Request, any)
}

Writer is responsible to render to result provided to the associated response stream.

Directories

Path Synopsis
app

Jump to

Keyboard shortcuts

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