reply

package
v0.0.13 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAlreadySent    = errors.New("reply: can not send more data, response already sent")
	ErrPresetNotFound = errors.New("reply: preset not found")
)

Functions

This section is empty.

Types

type Client

type Client struct {
	Finalizer      Finalizer      // Runs before sending
	Transformer    Transformer    // Transforms payload
	CodeAliases    CodeAliases    // Maps error codes to HTTP status
	DefaultHeaders DefaultHeaders // Default response headers
	PaginationType PaginationType // "page" or "offset". Default: "offset"
	DebugMode      bool           // If true, includes debug info in responses. Default: false
	// contains filtered or unexported fields
}

Client holds global config for Reply instances.

func NewClient

func NewClient(config Client) *Client

Create a new client with given configuration.

Example:

var Client = reply.NewClient(reply.Client{
	Finalizer: finalizer,
	Transformer: transformer,
	CodeAliases    map[string]int{
		"SERVER_ERROR": 500,
		"BAD_REQUEST": 400,
	},
	DefaultHeaders map[string]string{
		"Content-Type": "application/json",
	},
	DebugMode: os.GetEnv("GO_ENV") != "production"
})

func (*Client) AddPreset added in v0.0.11

func (r *Client) AddPreset(name string, preset Preset)

AddPreset register reply value preset to client

Example:

Client.AddPreset("RESOURCE_NOT_FOUND", func(rp *Reply, args ...any) *Reply {
	resource := "resource"
	if len(args) > 0 {
		resourceArg, ok := args[0].(string)
		if ok {
			resource = resourceArg
		}
	}

	return rp.Error("NOT_FOUND", resource+" not found.")
})

func (*Client) AddSenderPreset added in v0.0.11

func (r *Client) AddSenderPreset(name string, preset SendPreset)

AddSenderPreset register reply sender preset to client

Example:

Client.AddSenderPreset("RESOURCE_NOT_FOUND", func(rp *Reply, args ...any) error {
	resource := "resource"
	if len(args) > 0 {
		resourceArg, ok := args[0].(string)
		if ok {
			resource = resourceArg
		}
	}

	return rp.Error("NOT_FOUND", resource+" not found.").FailJSON()
})

func (*Client) New

func (c *Client) New(adapter adapter.Adapter) *Reply

Create a new reply.

Example:

rp := Client.New(nethttpadapter.AdaptHttp(w, r))
// ...
rp.Success(datas).OkJSON()

func (*Client) Use added in v0.0.11

func (c *Client) Use(adapter adapter.Adapter) *Reply

Reuse instance or create new Reply instance.

Example:

rp := Client.Use(nethttpadapter.AdaptHttp(w, r))
// ...
rp.Success(datas).OkJSON()

type CodeAliases added in v0.0.8

type CodeAliases map[string]int

CodeAliases maps error codes to HTTP status codes.

type DefaultHeaders added in v0.0.8

type DefaultHeaders map[string]string

DefaultHeaders defines default headers to include in every response.

type ErrorOption added in v0.0.11

type ErrorOption func(*ErrorPayload)

ErrorOption defines function to build options in ErrorPayload.

func WithDetails added in v0.0.11

func WithDetails(details string) ErrorOption

WithDetails returns ErrorOption to build error with details.

func WithFields added in v0.0.11

func WithFields(fields FieldsError) ErrorOption

WithFields returns ErrorOption to build error with fields error.

type ErrorPayload

type ErrorPayload struct {
	Code    string      `json:"code" xml:"code"`                           // Machine-readable error code
	Message string      `json:"message" xml:"message"`                     // Human-readable message
	Details string      `json:"details,omitempty" xml:"details,omitempty"` // Optional debug details
	Fields  FieldsError `json:"fields,omitempty" xml:"fields,omitempty"`   // Fields causing the error (if any)
}

ErrorPayload defines the error response body.

Example:

ErrorPayload{Code: "NOT_FOUND", Message: "User not found"}

func (*ErrorPayload) Error added in v0.0.13

func (e *ErrorPayload) Error() string

type FieldsError added in v0.0.11

type FieldsError map[string]string

FieldsError defines key-value of field-error.

type Finalizer added in v0.0.8

type Finalizer func(client *Reply)

Finalizer defines a function to run before sending the response.

type Meta

type Meta struct {
	Status     string      `json:"status" xml:"status"`                               // "SUCCESS" or "ERROR"
	Info       string      `json:"information,omitempty" xml:"information,omitempty"` // Optional info message
	Pagination *Pagination `json:"pagination,omitempty" xml:"pagination,omitempty"`   // Pagination info if applicable
	Timestamp  int64       `json:"timestamp" xml:"timestamp"`                         // TImestamp of replied time
	Tokens     Tokens      `json:"tokens,omitempty" xml:"tokens,omitempty"`           // Optional tokens (e.g. auth)
	Debug      any         `json:"debug,omitempty,omitzero" xml:"debug,omitempty"`    // Optional debug info
}

Meta contains reply metadata.

Example:

Meta{Status: "SUCCESS", Info: "Fetched 10 items"}

type Pagination

type Pagination struct {
	Next    int  `json:"next" xml:"next"`                       // Next page/offset
	HasNext bool `json:"hasNext" xml:"hasNext"`                 // True if more results exist
	Current int  `json:"current" xml:"current"`                 // Current page/offset
	Total   int  `json:"total,omitempty" xml:"total,omitempty"` // Total data, available if use total paginate
}

Pagination holds pagination metadata, embedded in Meta when needed.

Example:

Pagination{Next: 20, HasNext: true, Current: 0}

type PaginationType added in v0.0.8

type PaginationType string

PaginationType defines the pagination strategy.

const (
	// PaginationPage indicates page-based pagination.
	PaginationPage PaginationType = "page"
	// PaginationOffset indicates offset-based pagination.
	PaginationOffset PaginationType = "offset"
)

type Preset added in v0.0.11

type Preset func(rp *Reply, args ...any) *Reply

Preset defines a function to reuse reply value.

type Reply

type Reply struct {
	Payload any // Transformed payload. Only available after reply
	// contains filtered or unexported fields
}

Reply is the main HTTP response helper with chained methods.

func (*Reply) AddHeader

func (r *Reply) AddHeader(key, value string) *Reply

AddHeader appends a value to a response header. Unlike SetHeader, this allows multiple values for the same header key.

Example:

rp.AddHeader("Set-Cookie", "session=abc123")

func (*Reply) AddHeaders

func (r *Reply) AddHeaders(headers map[string]string) *Reply

AddHeaders appends multiple values to response headers. Each key-value pair is added without replacing existing values.

Example:

rp.AddHeaders(map[string]string{
    "X-Custom-Header": "value1",
    "X-Debug-Info": "enabled",
})

func (*Reply) CreatedBinary

func (r *Reply) CreatedBinary() error

CreatedBinary is a shortcut for ReplyBinary with http.StatusCreated (201).

func (*Reply) CreatedHTML

func (r *Reply) CreatedHTML() error

CreatedHTML sends status 201 Created with HTML body.

func (*Reply) CreatedJSON

func (r *Reply) CreatedJSON() error

CreatedJSON sends status 201 Created with JSON body.

func (*Reply) CreatedStream

func (r *Reply) CreatedStream() error

CreatedStream sends status 201 Created with stream body.

func (*Reply) CreatedText

func (r *Reply) CreatedText() error

CreatedText sends status 201 Created with plain text body.

func (*Reply) CreatedXML

func (r *Reply) CreatedXML() error

CreatedXML sends status 201 Created with XML body.

func (*Reply) Data

func (r *Reply) Data() any

Data returns a copy of the data from internal envelope. Modifying the returned value does not affect the original.

func (*Reply) Debug added in v0.0.11

func (r *Reply) Debug(messages ...any) *Reply

Debug sets debug messages to envelope.

func (*Reply) Defer

func (r *Reply) Defer(funcs ...func()) *Reply

Defer registers one or more functions to be executed before the response is sent. These functions are executed in the order they were registered. Useful for cleanup operations, logging, or committing/rolling back transactions.

Example:

rp.Defer(func() { tx.Rollback() })
rp.Defer(func() { log.Println("Response sent") })
rp.Success(data).OkJSON() // deferred funcs execute before sending

func (*Reply) DeleteHeader

func (r *Reply) DeleteHeader(key string) *Reply

DeleteHeader removes a response header by key.

Example:

rp.DeleteHeader("X-Powered-By")

func (*Reply) DeleteHeaders

func (r *Reply) DeleteHeaders(keys []string) *Reply

DeleteHeaders removes multiple response headers by their keys.

Example:

rp.DeleteHeaders([]string{"X-Powered-By", "X-API-Version"})

func (*Reply) Envelope

func (r *Reply) Envelope() ReplyEnvelope

Envelope returns a copy of the internal envelope. Modifying the returned value does not affect the original.

func (*Reply) Error

func (r *Reply) Error(code, message string, options ...ErrorOption) *Reply

Error sets reply status to "ERROR" and attaches an error payload.

func (*Reply) FailJSON

func (r *Reply) FailJSON(code ...int) error

FailJSON sends a JSON response with an error status. If code is provided, use it; otherwise, retrieve from CodeAliases or default to 500.

func (*Reply) FailXML

func (r *Reply) FailXML(code ...int) error

FailXML sends a XML response with an error status. If code is provided, use it; otherwise, retrieve from CodeAliases or default to 500.

func (*Reply) GetHeader

func (r *Reply) GetHeader(key string) string

GetHeader retrieves the value of a response header by key. Returns an empty string if the header doesn't exist.

Example:

contentType := rp.GetHeader("Content-Type")

func (*Reply) GetHeaders

func (r *Reply) GetHeaders(keys []string) []string

GetHeaders retrieves multiple response header values by their keys. Returns a slice of values in the same order as the input keys. Empty strings are returned for headers that don't exist.

Example:

values := rp.GetHeaders([]string{"Content-Type", "X-API-Version"})

func (*Reply) Info added in v0.0.7

func (r *Reply) Info(information string) *Reply

Info sets info to reply meta information.

func (*Reply) Meta

func (r *Reply) Meta() Meta

Meta returns a copy of the meta from internal envelope. Modifying the returned value does not affect the original.

func (*Reply) NoContent

func (r *Reply) NoContent()

NoContent sends no content response with status 204

Example:

rp.NoContent()

func (*Reply) OkBinary

func (r *Reply) OkBinary() error

OkBinary is a shortcut for ReplyBinary with http.StatusOK (200).

func (*Reply) OkHTML

func (r *Reply) OkHTML() error

OkHTML is a shortcut for ReplyHTML with status 200 OK.

func (*Reply) OkJSON

func (r *Reply) OkJSON() error

OkJSON is a shortcut for ReplyJSON with status 200 OK.

func (*Reply) OkStream

func (r *Reply) OkStream() error

OkStream is a shortcut for ReplyStream with status 200 OK.

func (*Reply) OkText

func (r *Reply) OkText() error

OkText is a shortcut for ReplyText with status 200 OK.

func (*Reply) OkXML

func (r *Reply) OkXML() error

OkXML is a shortcut for ReplyXML with status 200 OK.

func (*Reply) PaginateCursor

func (r *Reply) PaginateCursor(limit, current int) *Reply

Create pagination information in meta data with cursor based (data to send + 1). Auto cut data.

Example:

rp.Success(datas).PaginateCursor(limit, current).OkJSON()

func (*Reply) PaginateTotal

func (r *Reply) PaginateTotal(limit, current, total int) *Reply

Create pagination information in meta data with total based.

Example:

rp.Success(datas).PaginateTotal(limit, current, total).OkJSON()

func (*Reply) Redirect

func (r *Reply) Redirect(statusCode int, url string)

Redirect sends a redirect response with given status code.

Example:

rp.Redirect(http.StatusMovedPermanently, "https://github.com/chesta132")

func (*Reply) ReplyBinary

func (r *Reply) ReplyBinary(code int) error

ReplyBinary sends a binary response using the adapter's BinarySender. If Data is not []byte, it logs an error and sends an empty body.

Example:

rp.Success(imageData).OkBinary()

func (*Reply) ReplyHTML

func (r *Reply) ReplyHTML(code int) error

ReplyHTML sends an HTML string response with the specified status code. The Data in *Reply must be a string; if not, it will be treated as an empty string and an error will be logged. The string is automatically escaped before sending.

Example:

rp.Success("<p>Hello & welcome!</p>").ReplyHTML(http.StatusOK) // -> <p>Hello &amp; welcome!</p>

func (*Reply) ReplyJSON

func (r *Reply) ReplyJSON(code int) error

ReplyJSON sends a JSON-formatted response with the specified status code. The Payload in *Reply will be automatically encoded.

Example:

rp.Success(Data{Msg: "ok"}).ReplyJSON(http.StatusOK) // -> {"msg":"ok"}

func (*Reply) ReplyStream

func (r *Reply) ReplyStream(code int) error

ReplyStream sends a streaming response with the specified status code. Data must be of type Stream; otherwise, logs an error and sends an empty stream.

Example:

rp.Success(reply.Stream{Data: file, ContentType: "image/png"}).
ReplyStream(http.StatusOK) // streams the file as PNG

func (*Reply) ReplyText

func (r *Reply) ReplyText(code int) error

ReplyText sends a plain text response with the specified status code. Data must be a string; if not, logs an error and sends empty string.

Example:

rp.Success("Hello world!").ReplyText(http.StatusOK) // -> Hello world!

func (*Reply) ReplyXML

func (r *Reply) ReplyXML(code int) error

ReplyXML sends an XML-formatted response with the specified status code. Payload will be marshaled to XML automatically.

Example:

rp.Success(User{ID: 1, Name: "Chesta"}).ReplyXML(http.StatusOK)
// -> <User><ID>1</ID><Name>Chesta</Name></User>

func (*Reply) SendPreset added in v0.0.11

func (r *Reply) SendPreset(name string, args ...any) (err error)

SendPreset sends response with registered sender preset. return joined ErrPresetNotFound if preset not exist

Example:

err := rp.SendPreset("RESOURCE_NOT_FOUND", "user")
if errors.Is(reply.ErrPresetNotFound) {
	rp.Error("NOT_FOUND", "user not found.").
		Debug("preset RESOURCE_NOT_FOUND not found").
		FailJSON()
} else {
	return err
}

func (*Reply) SetCookies

func (r *Reply) SetCookies(cookies ...http.Cookie) *Reply

SetCookies adds one or more HTTP cookies to the response headers. Each cookie is converted to its string representation and added to the Set-Cookie header. Empty cookie strings are skipped.

Example:

rp.SetCookies(
  http.Cookie{Name: "access_token", Value: accessToken},
  http.Cookie{Name: "refresh_token", Value: refreshToken},
)

func (*Reply) SetHeader

func (r *Reply) SetHeader(key, value string) *Reply

SetHeader sets a single response header, replacing any existing values. Use this when you want to ensure only one value exists for a header.

Example:

rp.SetHeader("Content-Type", "application/json")

func (*Reply) SetHeaders

func (r *Reply) SetHeaders(headers map[string]string) *Reply

SetHeaders sets multiple response headers at once, replacing any existing values. Each key-value pair in the map will replace existing headers with the same key.

Example:

rp.SetHeaders(map[string]string{
    "X-API-Version": "v2.0",
    "Cache-Control": "no-cache",
})

func (*Reply) Success

func (r *Reply) Success(data any) *Reply

Success sets reply status to "SUCCESS" and attaches data.

func (*Reply) Tokens added in v0.0.8

func (r *Reply) Tokens(tokens Tokens) *Reply

Tokens sets tokens to reply meta tokens.

func (*Reply) UsePreset added in v0.0.11

func (r *Reply) UsePreset(name string, args ...any) (instance *Reply, exists bool)

UsePreset get preset from registered preset in client. return self instance and false if named preset don't exists

Example:

rp, exists := rp.UsePreset("RESOURCE_NOT_FOUND", "user")
if exists {
	rp.Info("user with id " + userId + " not found").FailJSON()
} else {
	rp.Error("NOT_FOUND", "user not found").
		Info("user with id " + userId + " not found").
		Debug("preset RESOURCE_NOT_FOUND not found").
		FailJSON()
}

type ReplyEnvelope

type ReplyEnvelope struct {
	Meta Meta `json:"meta" xml:"meta"` // Metadata section
	Data any  `json:"data" xml:"data"` // Payload data
}

ReplyEnvelope is the standard API response envelope.

Example:

ReplyEnvelope{Meta: Meta{Status: "SUCCESS"}, Data: user}

type SendPreset added in v0.0.11

type SendPreset func(rp *Reply, args ...any) error

SendPreset defines a function to reuse reply value sender.

type Stream

type Stream struct {
	Data        io.Reader // Stream source
	ContentType string    // MIME type of the stream
}

Stream enables streaming responses (files, SSE, etc.).

Example:

Stream{Data: fileReader, ContentType: "video/mp4"}

type Tokens added in v0.0.8

type Tokens map[string]string

Tokens holds authentication or session tokens.

type Transformer added in v0.0.8

type Transformer func(client *Reply) any

Transformer defines a function to transform the payload before sending.

Jump to

Keyboard shortcuts

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