Engine
The important methods of registering routes, middleware, starting and stopping services for Hertz are all included in the core type server.Hertz
. It is composed of route.Engine
and a signalWaiter
. Here’s the definition:
// Hertz is the core struct of hertz.
type Hertz struct {
*route.Engine
// Used to receive signals for graceful shutdown
signalWaiter func(err chan error) error
}
server.Hertz
Initializing the Server
Hertz provides two functions in the server
package to initialize servers: New
and Default
.
The default function Default
uses the middleware called Recovery
to prevent service crashes caused by panicking
during runtime.
// New creates a hertz instance without any default config.
func New(opts ...config.Option) *Hertz {
options := config.NewOptions(opts)
h := &Hertz{Engine: route.NewEngine(options)}
return h
}
// Default creates a hertz instance with default middlewares.
func Default(opts ...config.Option) *Hertz {
h := New(opts...)
// Uses built-in Recovery middleware based on New method
h.Use(recovery.Recovery())
return h
}
For more information on optional configurations, refer to Configuration Options.
Example Code
package main
import (
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.New()
// Use Default
// h := server.Default()
h.Spin()
}
Run Service
Hertz
provides the Spin
function to start the server.
Unlike the Run
provided in route.Engine
, it is generally recommended to use Spin
unless you have special needs when running services.
When using Service Registration and Discovery, Spin
will register the service into a registry center when starting up, and use signalWaiter
to monitor service exceptions. Only by using Spin
can we support graceful shutdown.
package main
import (
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.New()
// We usually recommend using Spin
h.Spin()
}
package main
import (
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.New()
// Start with Run function
if err:= h.Run (); err != Nil {
//...
panic(err)
}
}
route.Engine
route.Engine
is an important part of server.Hertz
, which contains a large number of commonly used methods in development, and is particularly important.
type Engine struct {
noCopy nocopy.NoCopy //lint:ignore U1000 until noCopy is used
// engine name
Name string
serverName atomic.Value
// Options for route and protocol server
options *config.Options
// route
RouterGroup
trees MethodTrees
maxParams uint16
allNoMethod app.HandlersChain
allNoRoute app.HandlersChain
noRoute app.HandlersChain
noMethod app.HandlersChain
// For render HTML
delims render.Delims
funcMap template.FuncMap
htmlRender render.HTMLRender
// NoHijackConnPool will control whether invite pool to acquire/release the hijackConn or not.
// If it is difficult to guarantee that hijackConn will not be closed repeatedly, set it to true.
NoHijackConnPool bool
hijackConnPool sync.Pool
// KeepHijackedConns is an opt-in disable of connection
// close by hertz after connections' HijackHandler returns.
// This allows to save goroutines, e.g. when hertz used to upgrade
// http connections to WS and connection goes to another handler,
// which will close it when needed.
KeepHijackedConns bool
// underlying transport
transport network.Transporter
// trace
tracerCtl tracer.Controller
enableTrace bool
// protocol layer management
protocolSuite *suite.Config
protocolServers map[string]protocol.Server
protocolStreamServers map[string]protocol.StreamServer
// RequestContext pool
ctxPool sync.Pool
// Function to handle panics recovered from http handlers.
// It should be used to generate an error page and return the http error code
// 500 (Internal Server Error).
// The handler can be used to keep your server from crashing because of
// unrecovered panics.
PanicHandler app.HandlerFunc
// ContinueHandler is called after receiving the Expect 100 Continue Header
//
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.1.1
// Using ContinueHandler a server can make decisioning on whether or not
// to read a potentially large request body based on the headers
//
// The default is to automatically read request bodies of Expect 100 Continue requests
// like they are normal requests
ContinueHandler func(header *protocol.RequestHeader) bool
// Indicates the engine status (Init/Running/Shutdown/Closed).
status uint32
// Hook functions get triggered sequentially when engine start
OnRun []CtxErrCallback
// Hook functions get triggered simultaneously when engine shutdown
OnShutdown []CtxCallback
// Custom Functions
clientIPFunc app.ClientIP
formValueFunc app.FormValueFunc
}
Set ServiceName
Sample code:
package main
func main() {
h := server.New()
// Used to set the Server field in response header, default is Hertz.
h.Name = ""
}
Rendering template
The engine provides methods such as Delims
, SetFuncMap
, LoadHTMLGlob
, LoadHTMLFiles
, SetHTMLTemplate
, and SetAutoReloadHTMLTemplate
for rendering HTML or template files.
Delims
Used to set the delimiter of the templates.
Function signature:
func (engine *Engine) Delims(left, right string) *Engine
SetFuncMap
Used to set data sources for templates.
Function signature:
type FuncMap map[string]interface{}
func (engine *Engine) SetFuncMap(funcMap template.FuncMap)
Example usage:
package main
func main() {
h := server.New()
h.SetFuncMap(template.FuncMap{
"time": time.Now.String(),
})
}
LoadHTMLGlob
Used for global loading of template files. The *
wildcard can be used to specify the template folder.
Function signature:
// LoadHTMLGlob loads HTML files identified by glob pattern
// and associates the result with HTML renderer.
func (engine *Engine) LoadHTMLGlob(pattern string)
Example code:
// Loads all html template files in render/html directory
h.LoadHTMLGlob("render/html/*")
// Loads index.tmpl template file
h.LoadHTMLGlob("index.tmpl")
LoadHTMLFiles
Used to load specified template files as a string slice.
Function signature:
// LoadHTMLFiles loads a slice of HTML files
// and associates the result with HTML renderer.
func (engine *Engine) LoadHTMLFiles(files ...string)
SetHTMLTemplate/SetAutoReloadHTMLTemplate
These two methods are used internally in rendering logic and are not recommended for direct use.
Register Middleware
Hertz provides Use
function for registering middleware into routes.
We support user-defined middleware, and at the same time we also provide some commonly used middleware implementations, See details hertz-contrib.
“At the same time, although the common usage of middleware is to register it globally, we also support registration at the routing level. For more details, please see
The parameter type of middleware
in the Use
function must be a http processing function of app.HandlerFunc
.
type HandlerFunc func (ctx context.Context, c *app.RequestContext)
Function signature:
func (engine *Engine) Use(middleware ...app.HandlerFunc) IRoutes
Sample code:
package main
// ...
func main() {
h := server.New()
// Register built-in Recovery middleware into routes.
h.Use(recovery.Recovery())
// Use custom middleware.
h.Use(exampleMiddleware())
}
func exampleMiddleware() app.handlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
// Print logs before executing functions in Next.
hlog.Info("print before...")
// Use Next to execute the matching function in route.
c.Next(ctx)
// Print logs after executing functions in Next.
hlog.Ingo("print after...")
}
}
For more examples, see repository.
Service Shutdown
hertz provides the Shutdown
function for graceful shutdown.
If you are using service registration and discovery, the corresponding data will also be deregistered from the registry when the service exits.
Function signature:
func (engine *Engine) Shutdown(ctx context.Context) (err error)
Example code:
package main
import (
//...
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.New()
// When accessing this path, it triggers the shutdown function to go offline
h.GET("/shutdown", func(ctx context.Context, c *app.RequestContext) {
h.ShutDown(ctx)
})
h.Spin()
}
For more information on graceful shutdown see documentation
Set Hook Function
The corresponding hook functions will be triggered when Engine starts up and shuts down.
OnRun
and OnShutdown
are two slices of hook functions used to store hook functions. To avoid affecting existing hook functions,
you need to use the append
function to add new hooks into slices.
For detailed configuration methods, see Hooks.
Function signature:
type CtxCallback func (ctx context.Context)
type CtxErrCallback func (ctx context.Context) error
// Hook Functions triggered during engine startup.
OnRun []CtxErrCallback
// Hook Functions triggered during engine shutdown.
OnShutdown []CtxCallback
Example code:
package main
import (
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.New()
h.OnRun = append(h.OnRun, func(ctx context.Context) error {
return nil
})
h.OnShutdown = append(h.OnShutdown, func(ctx context.Context) {
//...
})
}
Error Handlers
PanicHandler
Used to set the handling function when a program panics, default is nil
.
Note: If both PanicHandler
and Recovery
middleware are set at the same time, then the logic in Recovery
middleware will override that of PanicHandler
.
Example code:
package main
func main() {
h := server.New()
// When panic occurs, the function in PanicHandler will be triggered,
// returning a 500 status code with error message.
h.PanicHandler = func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(500, utils.H{
"message": "panic",
})
}
h.GET("/hello", func(c context.Context, ctx *app.RequestContext) {
panic("panic")
})
h.Spin()
}
Hijack
NoHijackConnPool
The hijacked connection used during Hertz connection hijacking is managed by pool management. Therefore, when the hijacked connection is used for websockets it does not support asynchronous operations.
The hijacked connection can only be closed once; closing it a second time will result in a null pointer exception.
NoHijackConnPool controls whether to use cache pools to obtain/release hijacked connections. Using pools improves performance of memory resource allocation but cannot prevent exceptions caused by closing connections twice.
If it is difficult to ensure that hijackConn won’t be closed repeatedly, it can be set as true.
Example code:
package main
func main() {
// https://github.com/cloudwego/hertz/issues/121
h.NoHijackConnPool = true
}
Get route info
Hertz provides Routes
to get the registered route information.
Route information struct:
// RouteInfo represents a request route's specification which contains method and path and its handler.
type RouteInfo struct {
Method string // http method
Path string // url path
Handler string // handler name
HandlerFunc app.HandlerFunc
}
// RoutesInfo defines a RouteInfo array.
type RoutesInfo []RouteInfo
Sample Code:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/hlog"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
h := server.Default()
h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
})
routeInfo := h.Routes()
hlog.Info(routeInfo)
h.Spin()
}
Configuration
Here is a collection of configuration options that can be used for the engine.
Use
Please see here.
NoHijackConnPool
Please see here.
OnRun/OnShutdown
Please see here.
PanicHandler
Please see here.
GetTransporterName
Get the name of the current network library being used. There are currently two options: Go’s native net
and netpoll
. Linux uses netpoll
by default, while Windows can only use Go’s native net
.
If you’re unsure about how to use one of these network libraries, please refer to this page
Function signature:
func (engine *Engine) GetTransporterName() (tName string)
// Deprecated: This only get the global default transporter - may not be the real one used by the engine.
// Use engine.GetTransporterName for the real transporter used.
func GetTransporterName() (tName string)
SetTransporter
SetTransporter
sets only Engine’s global defaults. When initializing Engine, use WithTransporter to set your network library instead.
Function signature:
func SetTransporter(transporter func(options *config.Options) network.Transporter)
IsRunning
Check whether or not Engine has been started.
Function signature:
func (engine *Engine) IsRunning() bool
Code example:
package main
func main() {
h := server.New()
// Check if service is running via /live interface
h.GET("/live", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(200, utils.H{
"isLive": h.IsRunning(),
})
})
h.Spin()
}
IsTraceEnable
Check if tracing is enabled.
Function signature:
func (engine *Engine) IsTraceEnable() bool
GetCtxPool
Get the current Engine’s ctxPool.
Function signature:
func (engine *Engine) GetCtxPool() *sync.Pool
Code example:
h := server.New()
// Retrieve a ctx from the ctxPool
h.GetCtxPool().Get().(*app.RequestContext)
// Return a ctx to the pool
h.GetCtxPool().Put(ctx)
Delims
Please see here
SetFuncMap
Please see here
LoadHTMLGlob
Please see here
LoadHTMLFiles
Please see here