problem

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2024 License: MIT Imports: 6 Imported by: 0

README

Problem

Codecov Go Report Card MIT License

Problem details for HTTP APIs per RFC-9457 standard.

This module provides the Problem struct which can be used to represent a problem in HTTP APIs. It implements the RFC-9457 standard.

It supports serializing and deserializing the Problem struct to and from JSON.

Usage

go-problem module provides an easy way to send the Problem struct as a response to the client.

Example with HTTP handler and middleware
package middleware

import (
    "net/http"
	
    "github.com/kodeart/go-problem"
)

func NotFoundHandler() http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        p := problem.Problem{
            Status:   http.StatusNotFound,
            Detail:   "No such API route",
            Title:    "Route Not Found",
            Instance: r.URL.Path,
        }
        p.JSON(w)
    }
}

// or with helper methods

func NotFoundHandler() http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        problem.New().
            WithStatus(http.StatusNotFound).
            WithDetail("No such API route").
            WithTitle("Route Not Found").
            WithInstance(r.URL.Path).
            JSON(w)
    }
}
package main

import (
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/kodeart/go-problem"
)

func main() {
    mux := chi.NewRouter()
    mux.NotFound(middleware.NotFoundHandler())

    ...

    mux.Get("/", func(w http.ResponseWriter, r *http.Request) {
        problem.New().
            WithStatus(http.StatusServiceUnavailable).
            WithExtension("maintenance", true).
            WithExtension("version", "1.0.0").
            JSON(w)
    })
}
Create a Problem with helpers
...
p := problem.New().
    WithStatus(http.StatusUnprocessableEntity).
    WithType("https://example.com/probs/out-of-credit").
    WithTitle("You do not have enough credit.").
    WithDetail("Your current balance is 30, but that costs 50.").
    WithInstance("/account/12345/msgs/abc").
    WithExtension("balance", 30).
    WithExtension("accounts", []string{
        "/account/12345",
        "/account/67890",
    })
}
Create a Problem directly
p := problem.Problem{
    Status:   http.StatusUnprocessableEntity,
    Type:     "https://example.com/probs/out-of-credit",
    Title:    "You do not have enough credit.",
    Detail:   "Your current balance is 30, but that costs 50.",
    Instance: "/account/12345/msgs/abc",
    Extensions: map[string]interface{}{
        "balance": 30,
        "accounts": []string{
            "/account/12345",
            "/account/67890",
		},
	},
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Problem

type Problem struct {
	Status     int            `json:"status,omitempty"`
	Instance   string         `json:"instance,omitempty"`
	Detail     string         `json:"detail,omitempty"`
	Title      string         `json:"title,omitempty"`
	Type       string         `json:"type,omitempty"`
	Extensions map[string]any `json:"-"`
}

Problem is a struct that represents a problem instance as defined in RFC-9457 (https://tools.ietf.org/html/rfc9457). All fields are optional.

func New

func New() *Problem

New returns a new Problem instance.

func (*Problem) JSON

func (p *Problem) JSON(w http.ResponseWriter)

JSON writes a JSON response to the client. Handles JSON encoding errors and returns an RFC-9457 compliant JSON error object.

func (Problem) MarshalJSON

func (p Problem) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface to serialize the Problem instance into RFC-9457 JSON format.

func (*Problem) UnmarshalJSON

func (p *Problem) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler interface to unserialize the JSON string into Problem structure as RFC-9457 implementation. [IMPORTANT]: built-in json.Unmarshaler converts numeric values to float64, so we need to convert status code back to int. The extension values are not converted, but are available.

func (*Problem) WithDetail

func (p *Problem) WithDetail(v string) *Problem

WithDetail sets the problem detail.

func (*Problem) WithExtension

func (p *Problem) WithExtension(key string, val any) *Problem

WithExtension adds key:value pairs to internal Extensions map. When JSON serialization is performed, these pairs are included in the JSON response as key:value to the final response.

func (*Problem) WithInstance

func (p *Problem) WithInstance(v string) *Problem

WithInstance sets the instance URI.

func (*Problem) WithStatus

func (p *Problem) WithStatus(v int) *Problem

WithStatus sets the status code.

func (*Problem) WithTitle

func (p *Problem) WithTitle(v string) *Problem

WithTitle sets the problem title.

func (*Problem) WithType

func (p *Problem) WithType(v string) *Problem

WithType sets the problem type.

func (*Problem) WithoutExtension

func (p *Problem) WithoutExtension(key string) *Problem

WithoutExtension removes a key from internal Extensions map. If the key does not exist, it does nothing.

Jump to

Keyboard shortcuts

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