resterr

package module
v0.0.0-...-58265df Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2024 License: MIT Imports: 8 Imported by: 5

README

resterr

resterr is a Go package designed to together with proper propagation of errors through an application handle the logging and mapping of logic errors to RESTful errors. It helps log original errors, map them to predefined REST errors, and ensures unmapped errors result in a 500 Internal Server Error. This package is particularly useful for structuring application errors and standardizing API error responses.

Features

  • Centralized error handling for REST APIs.
  • Logging of original errors while hiding internal details.
  • Mapping of application errors to REST errors.
  • Custom validation functions for REST errors.
  • Standardized JSON responses for errors.

Installation

To install resterr, use the following command:

go get github.com/alesr/resterr

Usage

Setting Up the Handler

First, initialize the logger and define your error mappings. Then, create the error handler using NewHandler.

package main

import (
	"context"
	"errors"
	"log/slog"
	"net/http"
	"os"

	"github.com/alesr/resterr"
)

var (
	ErrNotFound = errors.New("not found")
	ErrBadRequest = errors.New("bad request")
)

func main() {
	logger := slog.New(slog.NewTextHandler(os.Stdout))
	errorMap := map[error]resterr.RESTErr{
		ErrNotFound: {
			StatusCode: http.StatusNotFound,
			Message:    "The requested resource was not found",
		},
		ErrBadRequest: {
			StatusCode: http.StatusBadRequest,
			Message:    "The request was invalid",
		},
	}

	errHandler, err := resterr.NewHandler(logger, errorMap, resterr.WithValidationFn(validateRestErr))
	if err != nil {
		logger.Error("Failed to create handler", slog.String("error", err.Error()))
		return
	}

	http.HandleFunc("/example", func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		errHandler.Handle(ctx, w, fmt.Errorf("could not do process example request: %w",ErrNotFound)) // Example usage
	})

	http.ListenAndServe(":8080", nil)
}

func validateRestErr(restErr resterr.RESTErr) error {
	if restErr.StatusCode < 400 || restErr.StatusCode >= 600 {
		return errors.New("invalid status code")
	}
	return nil
}
Handling Errors

To handle errors in your HTTP handlers, use the Handle method of the Handler struct.

func exampleHandler(w http.ResponseWriter, r *http.Request) {
    errHandler, _ := resterr.NewHandler(logger, errorMap)

	ctx := r.Context()
	err := someFunctionThatMayFail()
	if err != nil {
		errHandler.Handle(ctx, w, err)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.Write([]byte("Success"))
}
Custom Validation Function

You can pass a custom validation function to the handler using the WithValidationFn option. This function will be used to validate each REST error during handler initialization.

func validateRestErr(restErr resterr.RESTErr) error {
	if restErr.StatusCode < 400 || restErr.StatusCode >= 600 {
		return errors.New("invalid status code")
	}
	return nil
}
Structs and Methods
RESTErr

Represents a RESTful error.

type RESTErr struct {
	StatusCode int    `json:"status-code"`
	Message    string `json:"message"`
	json       []byte `json:"-"`
}
Handler

Handles errors by logging them and mapping them to REST errors.

type Handler struct {
	logger          *slog.Logger
	internalErrJSON []byte
	errorMap        map[error]*RESTErr
	validationFn    func(restErr RESTErr) error
}

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

License

This project is licensed under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Handler

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

Handler handles standard errors by logging them and looking for an equivalent REST error in the error map. Errors that are not mapped result in internal server errors.

func NewHandler

func NewHandler(logger *slog.Logger, errMap map[error]RESTErr, opts ...Option) (*Handler, error)

NewHandler returns a REST error handler. It pre-processes the JSON values for REST errors.

func (*Handler) Handle

func (h *Handler) Handle(ctx context.Context, w Writer, err error)

Handle logs the original error and checks for the error in the error -> REST error map provided at initialization. If the error is present in the map, it writes the REST error as JSON. Otherwise, it writes a JSON indicating an internal server error.

type Option

type Option func(h *Handler)

Option applies custom behavior to the handler.

func WithValidationFn

func WithValidationFn(fn func(restErr RESTErr) error) Option

WithValidationFn is an option to set a custom validation function for REST errors.

type RESTErr

type RESTErr struct {
	StatusCode int    `json:"status-code"`
	Message    string `json:"message"`
	// contains filtered or unexported fields
}

RESTErr represents a RESTful error. The json field is used to pre-marshal the error into JSON format.

func (RESTErr) Error

func (r RESTErr) Error() string

Error implements the error interface.

type Writer

type Writer interface {
	Write([]byte) (int, error)
	WriteHeader(statusCode int)
	Header() http.Header
}

Writer defines the interface for writing error data.

Jump to

Keyboard shortcuts

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