RRuna

Recover Middleware

Catch panic inside HTTP handlers and convert it into route errors

middleware/recover catches panic in the request chain. Without it, panic is handled by the underlying HTTP server, often interrupting the current connection and producing uncontrolled logs. With recover, panic becomes a Runa route error and goes through unified error rendering.

Install

go get github.com/duxweb/runa/middleware

Basic usage

import "github.com/duxweb/runa/middleware/recover"

route.Default().Use(recover.New())

Put recover near the beginning of the global middleware chain so it wraps later middleware and handlers.

Complete example

package main

import (
    "context"

    "github.com/duxweb/runa"
    "github.com/duxweb/runa/middleware/recover"
    "github.com/duxweb/runa/route"
)

func main() {
    app := runa.New()
    app.Install(route.Provider(route.Addr(":8080")))

    route.Default().Use(recover.New())
    route.Default().Get("/panic", func(ctx *route.Context) error {
        panic("something broken")
    })

    if err := app.Run(context.Background()); err != nil {
        panic(err)
    }
}

Custom error response

route.Default().Use(recover.New(recover.Config{
    Stack: false,
    OnRecover: func(ctx *route.Context, value any, stack []byte) error {
        return ctx.Status(500).JSON(map[string]any{
            "message": "server error",
        })
    },
}))

OnRecover is a good place for custom logging, alerts, or unified error output. If it returns a normal error, the error still enters Runa error rendering.

Config fields

Field Type Default Description
Next func(*route.Context) bool nil Skip when true
Stack bool true Include stack in panic error
OnRecover func(*route.Context, any, []byte) error nil Custom panic handler

Passing recover.Config{} sets Stack to false because false is the Go zero value. Use recover.Config{Stack: true} or plain recover.New() when you want stack output.

Common usage

Production usually disables stack output so internal paths are not exposed:

route.Default().Use(recover.New(recover.Config{Stack: false}))

Development can keep stack output for debugging:

route.Default().Use(recover.New())

Common problems

  • recover only catches panic in the current request goroutine. If a handler starts another goroutine, recover inside that goroutine too.
  • recover does not swallow normal errors. Handler-returned errors still go through Runa error handling.
  • security.New(...) already includes recover, so do not mount it twice unless you disabled it there.
Edit this page