Documentation
¶
Overview ¶
Package httpsyproblem provides a standard interface for handling API error responses in web applications. It implements RFC 7807 which specifies a way to carry machine-readable details of errors in a HTTP response to avoid the need to define new error response formats for HTTP APIs.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Error ¶
func Error(w http.ResponseWriter, r *http.Request, err error)
Error replies to the request by calling err's handler if it implements http.Handler or with a plain text message otherwise.
Example (Json) ¶
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"github.com/askeladdk/httpsyproblem"
)
func main() {
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/", nil)
err := httpsyproblem.Wrap(http.StatusBadRequest, io.EOF)
err.(*httpsyproblem.Details).Instance = "/products/42"
httpsyproblem.Error(w, r, err)
fmt.Println(w.Result().Status)
_, _ = io.Copy(os.Stdout, w.Body)
}
Output: 400 Bad Request {"detail":"EOF","instance":"/products/42","status":400,"title":"Bad Request","type":"about:blank"}
Example (Text) ¶
package main
import (
"fmt"
"io"
"net/http/httptest"
"os"
"github.com/askeladdk/httpsyproblem"
)
func main() {
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/", nil)
httpsyproblem.Error(w, r, io.EOF)
fmt.Println(w.Result().Status)
_, _ = io.Copy(os.Stdout, w.Body)
}
Output: 500 Internal Server Error EOF
func StatusCode ¶
StatusCode reports the HTTP status code associated with err if it implements the StatusCode() int method, 500 Internal Server Error otherwise, or 200 OK if err is nil.
Example ¶
package main
import (
"fmt"
"io"
"net/http"
"github.com/askeladdk/httpsyproblem"
)
func main() {
fmt.Println(httpsyproblem.StatusCode(nil))
fmt.Println(httpsyproblem.StatusCode(io.EOF))
fmt.Println(httpsyproblem.StatusCode(httpsyproblem.Wrap(http.StatusBadRequest, io.EOF)))
}
Output: 200 500 400
func Wrap ¶
Wrap associates an error with a status code and wraps it in a Details. The Detail field is set to err.Error(). The Status and Title fields are set according to code or to StatusCode(err) if code is 0.
Example ¶
package main
import (
"fmt"
"io"
"net/http"
"github.com/askeladdk/httpsyproblem"
)
func main() {
// Errors are associated with 500 Internal Server Error by default.
err := io.EOF
fmt.Println(httpsyproblem.StatusCode(err), err)
// Wrap any error to associate it with a status code.
err = httpsyproblem.Wrap(http.StatusBadRequest, err)
fmt.Println(httpsyproblem.StatusCode(err), err)
// Wrapping an already wrapped error changes the status code but preserves the details.
err = httpsyproblem.Wrap(http.StatusNotFound, err)
fmt.Println(httpsyproblem.StatusCode(err), err)
fmt.Println(err.(*httpsyproblem.Details).Detail)
}
Output: 500 EOF 400 Bad Request 404 Not Found EOF
Types ¶
type Details ¶
type Details struct {
// A human-readable explanation specific to this occurrence of the problem.
Detail string `json:"detail,omitempty" xml:"detail,omitempty"`
// A URI reference that identifies the specific occurrence of the problem.
// It may or may not yield further information if dereferenced.
Instance string `json:"instance,omitempty" xml:"instance,omitempty"`
// The HTTP status code ([RFC7231], Section 6)
// generated by the origin server for this occurrence of the problem.
Status int `json:"status,omitempty" xml:"status,omitempty"`
// A short, human-readable summary of the problem
// type. It SHOULD NOT change from occurrence to occurrence of the
// problem, except for purposes of localization (e.g., using
// proactive content negotiation; see [RFC7231], Section 3.4).
Title string `json:"title,omitempty" xml:"title,omitempty"`
// A URI reference [RFC3986] that identifies the
// problem type. This specification encourages that, when
// dereferenced, it provide human-readable documentation for the
// problem type (e.g., using HTML [W3C.REC-html5-20141028]). When
// this member is not present, its value is assumed to be
// "about:blank".
Type string `json:"type,omitempty" xml:"type,omitempty"`
// XMLName is needed to marshal to XML.
XMLName xml.Name `json:"-" xml:"urn:ietf:rfc:7807 problem"`
// contains filtered or unexported fields
}
Details implements the RFC 7807 model and can marshaled to JSON and XML.
Additional fields can be added by embedding Details inside another struct:
type MoreDetails struct {
httpsyproblem.Details
TraceID string `json:"trace_id" xml:"trace_id"`
}
func New ¶
New returns a Details with the Detail, Status and Title fields set according to code and err.
func (*Details) ServeHTTP ¶
func (details *Details) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler and replies to the request with a problem details object in JSON or XML format depending on the Accept header header. Panics if an error occurred while marshaling.
func (*Details) StatusCode ¶
StatusCode implements the interface used by StatusCode.
