Skip to content
/ herodot Public

A lightweight Go library for writing responses and errors to HTTP

License

Notifications You must be signed in to change notification settings

ory/herodot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

3179543 · Mar 18, 2025
Mar 18, 2025
Mar 18, 2025
Mar 18, 2025
Mar 18, 2025
Nov 3, 2022
Sep 22, 2022
Oct 2, 2020
Aug 3, 2023
Mar 12, 2025
May 26, 2020
Nov 24, 2016
Mar 18, 2025
Sep 22, 2022
Dec 4, 2024
Sep 22, 2022
Apr 7, 2023
Apr 7, 2023
Mar 18, 2025
Apr 11, 2023
Feb 21, 2023
Feb 21, 2023
Mar 18, 2025
Mar 18, 2025
Feb 21, 2023
Mar 18, 2025
Jun 26, 2023
Jun 26, 2023
Feb 21, 2023
Feb 21, 2023
Nov 2, 2022
Nov 2, 2022
Apr 7, 2023
Feb 21, 2023

herodot

Join the chat at https://slack.ory.sh/ Build Status Coverage Status


Herodot is a lightweight SDK for writing RESTful responses. It is comparable to render but provides easier error handling. The error model implements the well established Google API Design Guide. Herodot currently supports only JSON responses but can be extended easily.

Herodot is used by ORY Hydra and serves millions of requests already.

Installation

Herodot is versioned using go modules and works best with pkg/errors. To install it, run

go get -u github.com/ory/herodot

Upgrading

Tips on upgrading can be found in UPGRADE.md

Usage

Using Herodot is straightforward. The examples below will help you get started.

JSON

Herodot supplies an interface, allowing to return errors in many data formats like XML and others. Currently, it supports only JSON.

Write responses

var hd = herodot.NewJSONWriter(nil)

func GetHandler(rw http.ResponseWriter, r *http.Request) {
	// run your business logic here
	hd.Write(rw, r, map[string]interface{}{
	    "key": "value"
	})
}

type MyStruct struct {
	Key string `json:"key"`
}

func GetHandlerWithStruct(rw http.ResponseWriter, r *http.Request) {
	// business logic
	hd.Write(rw, r, &MyStruct{Key: "value"})
}

func PostHandlerWithStruct(rw http.ResponseWriter, r *http.Request) {
	// business logic
	hd.WriteCreated(rw, r, "/path/to/the/resource/that/was/created", &MyStruct{Key: "value"})
}

func SomeHandlerWithArbitraryStatusCode(rw http.ResponseWriter, r *http.Request) {
	// business logic
	hd.WriteCode(rw, r, http.StatusAccepted, &MyStruct{Key: "value"})
}

func SomeHandlerWithArbitraryStatusCode(rw http.ResponseWriter, r *http.Request) {
	// business logic
	hd.WriteCode(rw, r, http.StatusAccepted, &MyStruct{Key: "value"})
}

Dealing with errors

var writer = herodot.NewJSONWriter(nil)

func GetHandlerWithError(rw http.ResponseWriter, r *http.Request) {
    if err := someFunctionThatReturnsAnError(); err != nil {
        hd.WriteError(w, r, err)
        return
    }

    // ...
}

func GetHandlerWithErrorCode(rw http.ResponseWriter, r *http.Request) {
    if err := someFunctionThatReturnsAnError(); err != nil {
        hd.WriteErrorCode(w, r, http.StatusBadRequest, err)
        return
    }

    // ...
}

Errors

Herodot implements the error model of the well established Google API Design Guide. Additionally, it makes the fields request and reason available. A complete Herodot error response looks like this:

{
  "error": {
    "code": 404,
    "status": "some-status",
    "request": "foo",
    "reason": "some-reason",
    "details": [{ "foo": "bar" }],
    "message": "foo"
  }
}

To add context to your errors, implement herodot.ErrorContextCarrier. If you only want to set the status code of errors implement herodot.StatusCodeCarrier.