### Hertz HTTP Client Initialization and Usage Source: https://context7.com/cloudwego/hertz/llms.txt Demonstrates the initialization of the Hertz HTTP client with various configurations such as timeouts, connection pooling, and keep-alive. It also shows basic GET, GET with timeout, POST, and a low-level `Do` method usage. ```APIDOC ## HTTP Client Operations ### Description Provides functionalities for making HTTP requests with advanced features like connection pooling, keep-alive, TLS, retries, and per-request timeouts. ### Initialization `client.NewClient` initializes a new HTTP client with optional configurations. **Options:** - `client.WithDialTimeout(duration)`: Sets the dial timeout for establishing connections. - `client.WithMaxConnsPerHost(n)`: Sets the maximum number of idle connections per host. - `client.WithMaxIdleConnDuration(duration)`: Sets the maximum duration for idle connections. - `client.WithClientReadTimeout(duration)`: Sets the read timeout for client requests. - `client.WithKeepAlive(enable)`: Enables or disables keep-alive connections. ### Methods #### `client.Get(ctx context.Context, req *protocol.Request, url string) (statusCode int, body []byte, err error)` Performs a simple GET request. #### `client.GetTimeout(ctx context.Context, req *protocol.Request, url string, timeout time.Duration) (statusCode int, body []byte, err error)` Performs a GET request with a specified timeout. #### `client.Post(ctx context.Context, req *protocol.Request, url string, args *protocol.Args) (statusCode int, body []byte, err error)` Performs a POST request with form arguments. #### `client.Do(ctx context.Context, req *protocol.Request, resp *protocol.Response) error` Performs a request using a custom `protocol.Request` and populates a `protocol.Response`. ### Request Example ```go package main import ( "context" "fmt" "time" "github.com/cloudwego/hertz/pkg/app/client" "github.com/cloudwego/hertz/pkg/protocol" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { c, err := client.NewClient( client.WithDialTimeout(5*time.Second), client.WithMaxConnsPerHost(100), client.WithMaxIdleConnDuration(30*time.Second), client.WithClientReadTimeout(10*time.Second), client.WithKeepAlive(true), ) if err != nil { panic(err) } ctx := context.Background() // Simple GET statusCode, body, err := c.Get(ctx, nil, "https://httpbin.org/get") fmt.Printf("GET status=%d body_len=%d err=%v\n", statusCode, len(body), err) // GET with timeout statusCode, body, err = c.GetTimeout(ctx, nil, "https://httpbin.org/delay/1", 2*time.Second) fmt.Printf("GetTimeout status=%d err=%v\n", statusCode, err) // POST with form args args := &protocol.Args{} args.Set("username", "alice") args.Set("password", "secret") statusCode, body, err = c.Post(ctx, nil, "https://httpbin.org/post", args) fmt.Printf("POST status=%d body=%s err=%v\n", statusCode, body, err) // Low-level Do with custom request/response req := protocol.AcquireRequest() resp := protocol.AcquireResponse() defer protocol.ReleaseRequest(req) defer protocol.ReleaseResponse(resp) req.SetMethod(consts.MethodGet) req.SetRequestURI("https://httpbin.org/headers") req.Header.Set("X-Custom", "hertz-client") if err := c.Do(ctx, req, resp); err != nil { panic(err) } fmt.Printf("Do status=%d\n", resp.StatusCode()) } ``` ``` -------------------------------- ### Mounting net/http Handler with adaptor.HertzHandler Source: https://context7.com/cloudwego/hertz/llms.txt This example demonstrates how to wrap a standard `http.Handler` using `adaptor.HertzHandler` to mount it as a Hertz route. It supports `http.Flusher` and `http.Hijacker` interfaces. ```APIDOC ## GET /legacy/*any ### Description Mounts a standard net/http handler on a Hertz route. This allows existing `http.Handler` implementations to be used within a Hertz application. ### Method GET ### Endpoint /legacy/*any ### Parameters #### Path Parameters - **any** (string) - Required - Catch-all path parameter for routing. ### Request Example ```go package main import ( "net/http" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/common/adaptor" ) var stdMux = http.NewServeMux() func init() { stdMux.HandleFunc("/legacy/hello", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte("hello from net/http")) }) } func main() { h := server.Default() h.GET("/legacy/*any", adaptor.HertzHandler(stdMux)) h.Spin() } ``` ### Response #### Success Response (200) - The response will be the output of the mounted `http.Handler`. ``` -------------------------------- ### Commit Range Example Source: https://github.com/cloudwego/hertz/blob/main/changelog/README.md Shows the format for listing all commits within a specific version range, including their type, scope, and a brief description. ```markdown ## Commits (v0.1.0..v0.2.0) - abcd123 feat(client): add streaming support (#198) - ef01234 fix(retry): data race in container init (#205) - ... ``` -------------------------------- ### Changelog Sections Example Source: https://github.com/cloudwego/hertz/blob/main/changelog/README.md Illustrates the standard sections and entry format for a Hertz changelog. Follows a specific order and uses a defined prefix for package/area. ```markdown ## Breaking Changes - http: Change `Server.Listen(addr string)` -> `Server.Listen(addr string, opts ...Option)` (#201) Migration: pass no opts for old behavior. ## Deprecations - log: Deprecate `Print`, use `Logger.Info` instead (#199) ## Features - http: Add `Client.Send` for async request dispatch (#198) ## Fixes - auth: Fix token refresh race on concurrent requests (#205) ## Improvements - cache: Reduce memory usage via LRU eviction (#210) ## Deps - Bump golang.org/x/net v0.20 -> v0.25 (#212) - Add github.com/redis/go-redis v9.0 (#214) - Remove github.com/pkg/errors (#215) ``` -------------------------------- ### Handle File Uploads with ctx.FormFile and ctx.SaveUploadedFile Source: https://context7.com/cloudwego/hertz/llms.txt Use ctx.FormFile to get uploaded file information and ctx.SaveUploadedFile to save it to a destination. Ensure proper error handling for both operations. ```go package main import ( "context" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.Default() h.POST("/upload", func(c context.Context, ctx *app.RequestContext) { file, err := ctx.FormFile("file") if err != nil { ctx.AbortWithStatusJSON(consts.StatusBadRequest, map[string]string{"error": err.Error()}) return } dst := "./uploads/" + file.Filename if err := ctx.SaveUploadedFile(file, dst); err != nil { ctx.AbortWithStatusJSON(consts.StatusInternalServerError, map[string]string{"error": err.Error()}) return } ctx.JSON(consts.StatusOK, map[string]interface{}{ "filename": file.Filename, "size": file.Size, "saved_to": dst, }) }) h.Spin() } ``` -------------------------------- ### Fine-tuning Binder with `server.WithBindConfig` Source: https://context7.com/cloudwego/hertz/llms.txt Adjust the default binder's behavior for options like loose zero mode, JSON strictness, and custom type decoders. This example configures JSON number handling and enables strict decoding. ```go package main import ( "reflect" "time" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/app/server/binding" "github.com/cloudwego/hertz/pkg/app/server/binding/internal/decoder" ) func main() { bc := binding.NewBindConfig() bc.LooseZeroMode = true // empty string → zero value bc.EnableDecoderUseNumber = true // JSON numbers → json.Number bc.EnableDecoderDisallowUnknownFields = true // strict JSON decoding // Register a custom decoder for time.Time in query/form params bc.TypeUnmarshalFuncs = map[reflect.Type]decoder.CustomizeDecodeFunc{ reflect.TypeOf(time.Time{}): func(req interface{}, params interface{}, key string, setter func(v interface{}, loosezero bool)) error { // custom time parsing logic return nil }, } h := server.Default(server.WithBindConfig(bc)) h.Spin() } ``` -------------------------------- ### Custom Binder Implementation with `server.WithCustomBinder` Source: https://context7.com/cloudwego/hertz/llms.txt Replace the default binding and validation pipeline with a custom implementation. This example shows a basic binder that only handles JSON unmarshalling. ```go package main import ( "encoding/json" "fmt" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/app/server/binding" "github.com/cloudwego/hertz/pkg/protocol" "github.com/cloudwego/hertz/pkg/route/param" ) type myBinder struct{} func (b *myBinder) Name() string { return "my-binder" } func (b *myBinder) Bind(req *protocol.Request, v interface{}, params param.Params) error { return json.Unmarshal(req.Body(), v) } func (b *myBinder) BindQuery(req *protocol.Request, v interface{}) error { return fmt.Errorf("BindQuery not implemented") } func (b *myBinder) BindHeader(req *protocol.Request, v interface{}) error { return fmt.Errorf("BindHeader not implemented") } func (b *myBinder) BindPath(req *protocol.Request, v interface{}, params param.Params) error { return fmt.Errorf("BindPath not implemented") } func (b *myBinder) BindForm(req *protocol.Request, v interface{}) error { return fmt.Errorf("BindForm not implemented") } func (b *myBinder) BindJSON(req *protocol.Request, v interface{}) error { return json.Unmarshal(req.Body(), v) } func (b *myBinder) BindProtobuf(req *protocol.Request, v interface{}) error { return fmt.Errorf("BindProtobuf not implemented") } func (b *myBinder) Validate(req *protocol.Request, v interface{}) error { return nil // implement validation logic here } // Ensure interface compliance var _ binding.Binder = (*myBinder)(nil) func main() { h := server.Default(server.WithCustomBinder(&myBinder{})) h.Spin() } ``` -------------------------------- ### Hertz Code Generation Commands Source: https://github.com/cloudwego/hertz/blob/main/cmd/hz/README.md Examples of running the Hertz code generator script. Shows how to generate for all IDL types, specific targets, and use CI mode for verification and cleanup. ```bash cd cmd/hz # Generate examples for all IDL types (output in generate_out/) ./generate.sh # Generate specific targets only ./generate.sh thrift proto3 # CI mode: generate, verify the output compiles, then clean up ./generate.sh --verify --clean ``` -------------------------------- ### Create TLS HTTPS Server Source: https://context7.com/cloudwego/hertz/llms.txt Configure Hertz to start an HTTPS server using `server.WithTLS`. This automatically switches the transporter to `standard.NewTransporter` if Netpoll is not explicitly set. Ensure your certificate and key files are correctly specified. ```go package main import ( "context" "crypto/tls" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/common/utils" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { cert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { panic(err) } tlsCfg := &tls.Config{Certificates: []tls.Certificate{cert}} h := server.New( server.WithHostPorts(":443"), server.WithTLS(tlsCfg), ) h.GET("/secure", func(c context.Context, ctx *app.RequestContext) { ctx.JSON(consts.StatusOK, utils.H{"tls": true}) }) h.Spin() } ``` -------------------------------- ### Retrieve Registered Routes at Runtime with engine.Routes Source: https://context7.com/cloudwego/hertz/llms.txt Use h.Routes() to get a list of all registered routes. This is useful for generating documentation or implementing health-check endpoints. The output can be marshaled into JSON for easy consumption. ```go package main import ( "context" "encoding/json" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.Default() h.GET("/users", func(c context.Context, ctx *app.RequestContext) { ctx.String(consts.StatusOK, "users") }) h.POST("/users", func(c context.Context, ctx *app.RequestContext) { ctx.String(consts.StatusCreated, "created") }) h.GET("/routes", func(c context.Context, ctx *app.RequestContext) { routes := h.Routes() type routeInfo struct { Method string `json:"method"` Path string `json:"path"` Handler string `json:"handler"` } var out []routeInfo for _, r := range routes { out = append(out, routeInfo{r.Method, r.Path, r.Handler}) } b, _ := json.Marshal(out) ctx.Data(consts.StatusOK, "application/json", b) }) h.Spin() } ``` -------------------------------- ### Register Routes with Path Parameters in Hertz Source: https://context7.com/cloudwego/hertz/llms.txt Register routes using HTTP method shortcuts like GET and POST. Use ':name' for named path parameters and '*name' for wildcard parameters. The handler can access parameters using ctx.Param(). ```go package main import ( "context" "fmt" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.Default() // Named path parameter h.GET("/users/:id", func(c context.Context, ctx *app.RequestContext) { id := ctx.Param("id") // "42" ctx.String(consts.StatusOK, "user %s", id) }) // Wildcard path parameter h.GET("/static/*filepath", func(c context.Context, ctx *app.RequestContext) { fp := ctx.Param("filepath") // "/css/main.css" ctx.String(consts.StatusOK, "file: %s", fp) }) // POST with JSON body h.POST("/users", func(c context.Context, ctx *app.RequestContext) { var body map[string]interface{} if err := ctx.BindJSON(&body); err != nil { ctx.AbortWithStatusJSON(consts.StatusBadRequest, map[string]string{"error": err.Error()}) return } ctx.JSON(consts.StatusCreated, body) }) // Register the same handler for all methods h.Any("/catchall", func(c context.Context, ctx *app.RequestContext) { ctx.String(consts.StatusOK, "method: %s", ctx.Method()) }) // Custom HTTP method h.Handle("PURGE", "/cache/:key", func(c context.Context, ctx *app.RequestContext) { fmt.Fprintf(ctx, "Purged key: %s\n", ctx.Param("key")) }) h.Spin() } ``` -------------------------------- ### Implement Server Lifecycle Hooks Source: https://context7.com/cloudwego/hertz/llms.txt Use OnRun hooks for startup tasks and OnShutdown hooks for graceful shutdown procedures. OnRun errors can abort startup, while OnShutdown hooks run concurrently. ```go package main import ( "context" "fmt" "github.com/cloudwego/hertz/pkg/app/server" ) func main() { h := server.Default() h.OnRun = append(h.OnRun, func(ctx context.Context) error { fmt.Println("server starting — connecting to database...") // return error to abort startup return nil }) h.OnShutdown = append(h.OnShutdown, func(ctx context.Context) { fmt.Println("server stopping — flushing caches...") // ctx carries the shutdown deadline timeout }) h.Spin() } ``` -------------------------------- ### Serve Static Files and Directories in Hertz Source: https://context7.com/cloudwego/hertz/llms.txt Use `Static`, `StaticFile`, and `StaticFS` to serve files from the local filesystem. `StaticFS` offers advanced options for compression, byte-range requests, and index page generation. ```go package main import ( "context" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.Default() // Serve ./public/ at /static/ h.Static("/static", "./public") // Serve a single file h.StaticFile("/favicon.ico", "./assets/favicon.ico") // Advanced: serve with compression and byte-range support h.StaticFS("/files", &app.FS{ Root: "./uploads", GenerateIndexPages: true, Compress: true, AcceptByteRange: true, IndexNames: []string{"index.html"}, }) // Serve file attachment (forces browser download) h.GET("/download/:name", func(c context.Context, ctx *app.RequestContext) { name := ctx.Param("name") ctx.FileAttachment("./downloads/"+name, name) }) h.Spin() } ``` -------------------------------- ### Static File Serving Source: https://context7.com/cloudwego/hertz/llms.txt Demonstrates how to serve static files and directories using Hertz's `Static`, `StaticFile`, and `StaticFS` methods. `StaticFS` offers advanced options like compression and byte-range support. ```APIDOC ## Static Files — `router.Static`, `router.StaticFile`, `router.StaticFS` Serve a directory or a single file from the local filesystem. `StaticFS` allows full control via `app.FS` (compression, byte range, index generation). ### Serve a directory ```go h.Static("/static", "./public") ``` ### Serve a single file ```go h.StaticFile("/favicon.ico", "./assets/favicon.ico") ``` ### Advanced static file serving with `StaticFS` ```go h.StaticFS("/files", &app.FS{ Root: "./uploads", GenerateIndexPages: true, Compress: true, AcceptByteRange: true, IndexNames: []string{"index.html"}, }) ``` ### Serve file attachment (forces browser download) ```go h.GET("/download/:name", func(c context.Context, ctx *app.RequestContext) { name := ctx.Param("name") ctx.FileAttachment("./downloads/"+name, name) }) ``` ``` -------------------------------- ### Create Default Hertz Server with Options Source: https://context7.com/cloudwego/hertz/llms.txt Use `server.Default` to create a Hertz instance with the Recovery middleware pre-registered. Configure timeouts, host ports, body size limits, keep-alive, network protocol, and exit wait time using functional options. ```go package main import ( "context" "crypto/tls" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/common/utils" "github.com/cloudwego/hertz/pkg/network/standard" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.Default( server.WithHostPorts("0.0.0.0:8080"), server.WithReadTimeout(10*time.Second), server.WithWriteTimeout(10*time.Second), server.WithIdleTimeout(30*time.Second), server.WithMaxRequestBodySize(4*1024*1024), // 4 MB server.WithKeepAlive(true), server.WithNetwork("tcp"), server.WithExitWaitTime(5*time.Second), ) h.GET("/ping", func(c context.Context, ctx *app.RequestContext) { ctx.JSON(consts.StatusOK, utils.H{"message": "pong"}) }) h.Spin() // blocks until OS signal, then gracefully shuts down } ``` -------------------------------- ### Build hz Tool Source: https://github.com/cloudwego/hertz/blob/main/cmd/hz/README.md Build the hz command-line tool from source. This command should be run from the cmd/hz directory. ```bash cd cmd/hz && go build -o hz . ``` -------------------------------- ### Integrate Service Discovery Client Middleware Source: https://context7.com/cloudwego/hertz/llms.txt Use the sd.Discovery middleware to resolve logical service names to real host:port addresses. Requires a discovery.Resolver implementation. ```go package main import ( "context" "net" "github.com/cloudwego/hertz/pkg/app/client" "github.com/cloudwego/hertz/pkg/app/client/discovery" "github.com/cloudwego/hertz/pkg/app/middlewares/client/sd" "github.com/cloudwego/hertz/pkg/common/config" ) // Static resolver for demonstration purposes (in production use nacos, consul, etcd, etc.) type staticResolver struct{} func (r *staticResolver) Target(ctx context.Context, target *discovery.TargetInfo) string { return target.Host } func (r *staticResolver) Resolve(ctx context.Context, desc string) (discovery.Result, error) { return discovery.Result{ CacheKey: desc, Instances: []discovery.Instance{ discovery.NewInstance("tcp", "10.0.0.1:8080", 10, nil), discovery.NewInstance("tcp", "10.0.0.2:8080", 10, nil), }, }, nil } func (r *staticResolver) Name() string { return "static" } // Ensure staticResolver implements net.Addr var _ net.Addr = (*discovery.Instance)(nil) func main() { c, _ := client.NewClient() c.Use(sd.Discovery(&staticResolver{})) // The host "my-service" is resolved by the resolver to a real instance statusCode, body, err := c.Get( context.Background(), nil, "http://my-service/api/v1/ping", config.WithSD(true), ) _ = statusCode _ = body _ = err } ``` -------------------------------- ### HTTP Method Route Registration Source: https://context7.com/cloudwego/hertz/llms.txt Register routes using shortcut functions for common HTTP methods like GET, POST, PUT, DELETE, etc. Supports named path parameters and wildcard parameters. ```APIDOC ## GET /users/:id ### Description Handles GET requests to retrieve a specific user by their ID. ### Method GET ### Endpoint /users/:id ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user. ### Response #### Success Response (200) Returns the user information. ## GET /static/*filepath ### Description Handles GET requests for static files, allowing wildcard matching for file paths. ### Method GET ### Endpoint /static/*filepath ### Parameters #### Path Parameters - **filepath** (string) - Required - The path to the requested static file. ### Response #### Success Response (200) Returns the content of the static file. ## POST /users ### Description Handles POST requests to create a new user, accepting JSON data in the request body. ### Method POST ### Endpoint /users ### Parameters #### Request Body - **(object)** - Required - User data in JSON format. ### Request Example { "name": "John Doe", "email": "john.doe@example.com" } ### Response #### Success Response (201) Returns the created user data. ## Any /catchall ### Description Handles requests for any HTTP method on the specified path. ### Method Any ### Endpoint /catchall ### Response #### Success Response (200) Returns the HTTP method used for the request. ## PURGE /cache/:key ### Description Handles custom HTTP methods, demonstrated here with PURGE to invalidate cache entries. ### Method PURGE ### Endpoint /cache/:key ### Parameters #### Path Parameters - **key** (string) - Required - The cache key to purge. ### Response #### Success Response (200) Confirmation of cache purge. ``` -------------------------------- ### Hertz HTTP Client Usage Source: https://context7.com/cloudwego/hertz/llms.txt Demonstrates the usage of Hertz's HTTP client for various request types including GET, POST, and low-level Do requests. Supports connection pooling, keep-alive, TLS, retries, and per-request timeouts. ```go package main import ( "context" "fmt" "time" "github.com/cloudwego/hertz/pkg/app/client" "github.com/cloudwego/hertz/pkg/protocol" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { c, err := client.NewClient( client.WithDialTimeout(5*time.Second), client.WithMaxConnsPerHost(100), client.WithMaxIdleConnDuration(30*time.Second), client.WithClientReadTimeout(10*time.Second), client.WithKeepAlive(true), ) if err != nil { panic(err) } ctx := context.Background() // Simple GET statusCode, body, err := c.Get(ctx, nil, "https://httpbin.org/get") fmt.Printf("GET status=%d body_len=%d err=%v\n", statusCode, len(body), err) // GET with timeout statusCode, body, err = c.GetTimeout(ctx, nil, "https://httpbin.org/delay/1", 2*time.Second) fmt.Printf("GetTimeout status=%d err=%v\n", statusCode, err) // POST with form args args := &protocol.Args{} args.Set("username", "alice") args.Set("password", "secret") statusCode, body, err = c.Post(ctx, nil, "https://httpbin.org/post", args) fmt.Printf("POST status=%d body=%s err=%v\n", statusCode, body, err) // Low-level Do with custom request/response req := protocol.AcquireRequest() resp := protocol.AcquireResponse() defer protocol.ReleaseRequest(req) defer protocol.ReleaseResponse(resp) req.SetMethod(consts.MethodGet) req.SetRequestURI("https://httpbin.org/headers") req.Header.Set("X-Custom", "hertz-client") if err := c.Do(ctx, req, resp); err != nil { panic(err) } fmt.Printf("Do status=%d\n", resp.StatusCode()) } ``` -------------------------------- ### Read Request Parameters, Headers, Cookies, and Body Source: https://context7.com/cloudwego/hertz/llms.txt Demonstrates common RequestContext methods for accessing request details like path and query parameters, headers, cookies, raw body, client IP, and full path. ```go // Handler demonstrating all common request-reading methods func requestInfoHandler(c context.Context, ctx *app.RequestContext) { // Path parameter: GET /users/:id id := ctx.Param("id") // "42" // Query parameter: GET /users/42?sort=asc&page=2 sort := ctx.Query("sort") // "asc" page, ok := ctx.GetQuery("page") // "2", true limit := ctx.DefaultQuery("limit", "10") // "10" (default) // Headers authHeader := ctx.GetHeader("Authorization") // []byte contentType := ctx.ContentType() // []byte // Cookies sessionID := ctx.Cookie("session_id") // []byte // Raw body body := ctx.GetRawData() // []byte // Client IP (checks X-Forwarded-For, X-Real-IP) clientIP := ctx.ClientIP() // "1.2.3.4" // Full path template fullPath := ctx.FullPath() // "/users/:id" ctx.JSON(consts.StatusOK, map[string]interface{}{ "id": id, "sort": sort, "page": page, "ok": ok, "limit": limit, "auth": string(authHeader), "content_type": string(contentType), "session": string(sessionID), "body_len": len(body), "client_ip": clientIP, "full_path": fullPath, }) } ``` -------------------------------- ### Create Hertz Server with Custom Listener Source: https://context7.com/cloudwego/hertz/llms.txt Use `server.WithListener` to provide a pre-created `net.Listener`. This is useful for socket activation or custom listener wrappers. The `server.WithTransport(standard.NewTransporter)` option is required when using a custom `net.Listener`. ```go package main import ( "context" "net" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/network/standard" "github.com/cloudwego/hertz/pkg/common/utils" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { ln, err := net.Listen("tcp", ":9090") if err != nil { panic(err) } h := server.New( server.WithListener(ln), server.WithTransport(standard.NewTransporter), // required for custom net.Listener ) h.GET("/hello", func(c context.Context, ctx *app.RequestContext) { ctx.JSON(consts.StatusOK, utils.H{"hello": "world"}) }) h.Spin() } ``` -------------------------------- ### Hertz Client Middleware Source: https://context7.com/cloudwego/hertz/llms.txt Demonstrates how to implement and use client-side middleware for intercepting outbound requests and responses. Middleware can be used for logging, retries, circuit-breaking, and authentication. ```go package main import ( "context" "fmt" "time" "github.com/cloudwego/hertz/pkg/app/client" "github.com/cloudwego/hertz/pkg/protocol" ) // LoggingMiddleware logs every outbound request func LoggingMiddleware(next client.Endpoint) client.Endpoint { return func(ctx context.Context, req *protocol.Request, resp *protocol.Response) error { start := time.Now() err := next(ctx, req, resp) fmt.Printf("[client] method=%s url=%s status=%d elapsed=%v err=%v\n", req.Method(), req.URI(), resp.StatusCode(), time.Since(start), err) return err } } // AuthMiddleware injects a bearer token func AuthMiddleware(token string) client.Middleware { return func(next client.Endpoint) client.Endpoint { return func(ctx context.Context, req *protocol.Request, resp *protocol.Response) error { req.Header.Set("Authorization", "Bearer "+token) return next(ctx, req, resp) } } } func main() { c, _ := client.NewClient() c.Use(LoggingMiddleware, AuthMiddleware("my-secret-token")) statusCode, body, err := c.Get(context.Background(), nil, "https://httpbin.org/bearer") fmt.Printf("status=%d body=%s err=%v\n", statusCode, body, err) } ``` -------------------------------- ### Generate New Project from Protobuf IDL Source: https://github.com/cloudwego/hertz/blob/main/cmd/hz/README.md Scaffold a new Hertz project using a Protobuf IDL file. Specify the IDL path and the Go module name. ```bash hz new --idl api.proto --module github.com/example/myservice ``` -------------------------------- ### Generate New Project from Thrift IDL Source: https://github.com/cloudwego/hertz/blob/main/cmd/hz/README.md Scaffold a new Hertz project using a Thrift IDL file. Specify the IDL path and the Go module name. ```bash hz new --idl api.thrift --module github.com/example/myservice ``` -------------------------------- ### Hertz Response Helper Functions Source: https://context7.com/cloudwego/hertz/llms.txt Utilize `ctx.Redirect`, `ctx.Header`, `ctx.SetCookie`, and `ctx.Abort*` for managing responses. These functions allow setting headers, cookies, performing redirects, and terminating request processing. ```go func utilityHandler(c context.Context, ctx *app.RequestContext) { // Set a response header ctx.Header("X-Custom-Header", "my-value") ctx.Header("X-Remove-Me", "") // removes the header // Set a cookie ctx.SetCookie( "session", // name "abc123", // value 3600, // maxAge (seconds) "/", // path "example.com", // domain protocol.CookieSameSiteLaxMode, true, // secure true, // httpOnly ) // Temporary redirect if ctx.Query("old") != "" { ctx.Redirect(consts.StatusFound, []byte("/new-path")) ctx.Abort() return } // Permanent redirect ctx.Redirect(consts.StatusMovedPermanently, []byte("https://example.com/")) } func authCheck(c context.Context, ctx *app.RequestContext) { if ctx.GetHeader("X-Token") == nil { // Abort chain + write JSON error ctx.AbortWithStatusJSON(consts.StatusUnauthorized, map[string]string{"error": "unauthorized"}) return } ctx.Next(c) } ``` -------------------------------- ### HTML Templates Source: https://context7.com/cloudwego/hertz/llms.txt Hertz supports Go's html/template system, allowing for dynamic HTML rendering with features like auto-reloading and custom function maps. ```APIDOC ## GET /page ### Description Renders an HTML page using a pre-loaded template. ### Method GET ### Endpoint /page ### Parameters None ### Response #### Success Response (200 OK) - **Content-Type**: text/html; charset=utf-8 - Renders the content of the 'index.tmpl' file with provided data. #### Response Example (HTML Output) ```html Hertz Demo

Welcome!

Current date: [formatted date]

``` ``` -------------------------------- ### Implement Basic Authentication Middleware Source: https://context7.com/cloudwego/hertz/llms.txt Use the BasicAuth middleware to enforce HTTP Basic Authentication. It stores the authenticated username in the context. BasicAuthForRealm allows custom realm and user-key configuration. ```go package main import ( "context" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/middlewares/server/basic_auth" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.Default() authorized := h.Group("/admin") authorized.Use(basic_auth.BasicAuth(basic_auth.Accounts{ "alice": "s3cr3t", "bob": "p4ssw0rd", })) authorized.GET("/dashboard", func(c context.Context, ctx *app.RequestContext) { user := ctx.GetString("user") // set by BasicAuth middleware ctx.JSON(consts.StatusOK, map[string]string{"welcome": user}) }) // Custom realm and user-key h.GET("/private", basic_auth.BasicAuthForRealm( basic_auth.Accounts{"admin": "admin123"}, "Restricted Area", "authenticated_user", ), func(c context.Context, ctx *app.RequestContext) { ctx.String(consts.StatusOK, "hello %s", ctx.GetString("authenticated_user")) }) h.Spin() } ``` -------------------------------- ### Configure Recovery Middleware with Custom Handler Source: https://context7.com/cloudwego/hertz/llms.txt Use the Recovery middleware to automatically recover from panics. Configure a custom handler to log the stack trace and return a 500 error response. ```go package main import ( "context" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/middlewares/server/recovery" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/common/hlog" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.New() h.Use(recovery.Recovery( recovery.WithRecoveryHandler(func(c context.Context, ctx *app.RequestContext, err interface{}, stack []byte) { hlog.Errorf("panic recovered: err=%v\nstack:\n%s", err, stack) ctx.JSON(consts.StatusInternalServerError, map[string]string{ "error": "internal server error", }) }), )) h.GET("/panic", func(c context.Context, ctx *app.RequestContext) { panic("intentional panic for demo") }) h.Spin() } ``` -------------------------------- ### Configure Built-in Logging with hlog Source: https://context7.com/cloudwego/hertz/llms.txt Configure the default hlog logger's level and output. Replace the default logger with other implementations like zap or logrus for advanced use cases. ```go package main import ( "context" "os" "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/protocol/consts" ) func main() { // Configure the default logger hlog.SetLevel(hlog.LevelInfo) hlog.SetOutput(os.Stdout) h := server.Default() h.GET("/log-demo", func(c context.Context, ctx *app.RequestContext) { hlog.Trace("trace level message") hlog.Debug("debug message") hlog.Info("info message") hlog.Warnf("warn: request from %s", ctx.ClientIP()) hlog.Errorf("error: %v", "demo error") // Context-aware logging (useful for tracing) hlog.CtxInfof(c, "request_id=%s processed", ctx.GetHeader("X-Request-ID")) ctx.String(consts.StatusOK, "logged") }) h.Spin() } ``` -------------------------------- ### Hertz Package Structure Source: https://github.com/cloudwego/hertz/blob/main/cmd/hz/DESIGN.md Outlines the directory structure of the Hertz command-line tool, detailing the purpose of each main directory. ```text cmd/hz/ ├── app/ # CLI commands (new/update/model/client) and plugin triggering ├── config/ # Argument parsing, validation, and compiler command construction ├── generator/ # Code generation engine (handlers, routers, models, clients, templates) │ └── model/ # IDL-to-Go type system and Go code backend ├── thrift/ # Thrift IDL plugin: AST conversion, type resolution, annotation extraction ├── protobuf/ # Protobuf IDL plugin (parallel structure to thrift/) ├── meta/ # Constants, version info, and `.hz` manifest management └── util/ # Shared utilities (string ops, file helpers, env detection, logging) ``` -------------------------------- ### Response Helpers Source: https://context7.com/cloudwego/hertz/llms.txt Illustrates the use of response helper methods such as `ctx.Redirect`, `ctx.Header`, `ctx.SetCookie`, and `ctx.Abort*` for manipulating responses and controlling request processing. ```APIDOC ## Response Helpers — `ctx.Redirect`, `ctx.Header`, `ctx.SetCookie`, `ctx.Abort*` ### Set response header ```go ctx.Header("X-Custom-Header", "my-value") ctx.Header("X-Remove-Me", "") // removes the header ``` ### Set a cookie ```go ctx.SetCookie( "session", // name "abc123", // value 3600, // maxAge (seconds) "/", // path "example.com", // domain protocol.CookieSameSiteLaxMode, true, // secure true, // httpOnly ) ``` ### Temporary redirect ```go if ctx.Query("old") != "" { ctx.Redirect(consts.StatusFound, []byte("/new-path")) ctx.Abort() return } ``` ### Permanent redirect ```go ctx.Redirect(consts.StatusMovedPermanently, []byte("https://example.com/")) ``` ### Abort with JSON error ```go ctx.AbortWithStatusJSON(consts.StatusUnauthorized, map[string]string{"error": "unauthorized"}) ``` ``` -------------------------------- ### Streaming Request Body with `server.WithStreamBody` Source: https://context7.com/cloudwego/hertz/llms.txt Enable processing of large request bodies without buffering them entirely in memory. This is achieved by enabling streaming and using `ctx.RequestBodyStream()`. ```go package main import ( "context" "io" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/protocol/consts" ) func main() { h := server.Default( server.WithStreamBody(true), server.WithDisablePreParseMultipartForm(true), // also stream multipart ) h.POST("/upload", func(c context.Context, ctx *app.RequestContext) { stream := ctx.RequestBodyStream() data, err := io.ReadAll(stream) if err != nil { ctx.AbortWithMsg(err.Error(), consts.StatusInternalServerError) return } ctx.JSON(consts.StatusOK, map[string]interface{}{ "bytes_received": len(data), }) }) h.Spin() } ```