A Go implementation of RFC 7807/9457 - Problem Details for HTTP APIs.
This library implements the Problem Details standard based on:
- RFC 7807 (2016) - Original Problem Details specification
- RFC 9457 (2023) - Updated specification that obsoletes RFC 7807
- Full RFC 9457 compliance
- Go idiomatic Option pattern
- JSON serialization with
application/problem+jsonmedia type - Extensible with custom fields
- Zero external dependencies
go get github.com/lucasvillarinho/noproblem// Basic problem creation using Option pattern
problem := NewProblem("https://example.com/problems/validation", "Validation Error", 400,
WithDetail("Email is required"),
WithInstance("/api/users"),
WithExtra("field", "email"))
// Write as HTTP response
problem.WriteHTTPResponse(w)// Multiple options
problem := NewProblem("https://example.com/problems/validation", "Validation Error", 400,
WithDetail("Multiple validation errors"),
WithInstance("/api/users/123"),
WithExtra("email", "Email is required"),
WithExtra("age", "Age must be greater than 0"))
// Minimal problem
simple := NewProblem("https://example.com/problems/not-found", "Not Found", 404)
// With custom fields
custom := NewProblem("https://example.com/problems/custom", "Custom Problem", 422,
WithDetail("Custom error occurred"),
WithExtra("error_code", "CUSTOM_001"),
WithExtra("retry_after", 60))Echo
package main
import (
"net/http"
"github.com/labstack/echo/v4"
np "github.com/lucasvillarinho/noproblem"
)
func main() {
e := echo.New()
e.POST("/users", func(c echo.Context) error {
problem := np.NewProblem(
"https://example.com/problems/validation",
"Validation Error",
400,
np.WithDetail("Email is required"),
np.WithInstance(c.Request().URL.Path),
np.WithExtra("field", "email"),
)
c.Response().Header().Set("Content-Type", np.ContentTypeProblemJSON)
c.Response().WriteHeader(problem.Status)
return c.JSON(problem.Status, problem)
})
e.Logger.Fatal(e.Start(":8080"))
}Gin
package main
import (
"net/http"
"github.com/gin-gonic/gin"
np "github.com/lucasvillarinho/noproblem"
)
func main() {
r := gin.Default()
r.POST("/users", func(c *gin.Context) {
problem := np.NewProblem(
"https://example.com/problems/validation",
"Validation Error",
400,
np.WithDetail("Email is required"),
np.WithInstance(c.Request.URL.Path),
np.WithExtra("field", "email"),
)
c.Header("Content-Type", np.ContentTypeProblemJSON)
c.JSON(problem.Status, problem)
})
r.Run(":8080")
}Fiber
package main
import (
"github.com/gofiber/fiber/v2"
np "github.com/lucasvillarinho/noproblem"
)
func main() {
app := fiber.New()
app.Post("/users", func(c *fiber.Ctx) error {
problem := np.NewProblem(
"https://example.com/problems/validation",
"Validation Error",
400,
np.WithDetail("Email is required"),
np.WithInstance(c.Path()),
np.WithExtra("field", "email"),
)
c.Set("Content-Type", np.ContentTypeProblemJSON)
return c.Status(problem.Status).JSON(problem)
})
app.Listen(":8080")
}Standard HTTP
package main
import (
"log"
"net/http"
np "github.com/lucasvillarinho/noproblem"
)
func main() {
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
problem := np.NewProblem(
"https://example.com/problems/method-not-allowed",
"Method Not Allowed",
405,
np.WithDetail("Only POST method is allowed"),
np.WithInstance(r.URL.Path),
)
w.Header().Set("Content-Type", np.ContentTypeProblemJSON)
w.WriteHeader(problem.Status)
problem.WriteHTTPResponse(w)
return
}
problem := np.NewProblem(
"https://example.com/problems/validation",
"Validation Error",
400,
np.WithDetail("Email is required"),
np.WithInstance(r.URL.Path),
np.WithExtra("field", "email"),
)
w.Header().Set("Content-Type", np.ContentTypeProblemJSON)
w.WriteHeader(problem.Status)
problem.WriteHTTPResponse(w)
})
log.Fatal(http.ListenAndServe(":8080", nil))
}go test -vRFC 9457/7807 features implemented:
application/problem+jsonmedia type- All standard members:
type,title,status,detail,instance - Extension with additional members via
Extramap - Proper JSON serialization with custom marshaling
- HTTP response integration
Improvements over RFC 7807:
- Enhanced standardization
- Better interoperability guidance
- Maintains full backward compatibility
MIT License