hz client code generation

hz client code generation.

Introduction

Based on IDL, it generates RPC-like http requests code with a single click, which can block the tedious operation of creating and initializing hertz client and interoperate directly with the server code generated by hz.

This command needs to specify idl, otherwise no content will be generated.

The hz client command can be summarized by referring to hz client

The code structure generated by the hz client can refer to hz client

Generating code examples can refer to code

Example

This example is based on thrift, and protoc is similar to it.

Define IDL

The definition and semantics of the IDL are exactly the same as the current definition, so it is basically possible to generate client code without modifying the original IDL.

But for the client scenario, one annotation has been added, api.base_domain: specifies the default request domain to access.

Warn: When the api.any annotation is used, the client automatically generates client code for the post method to replace any.

namespace go toutiao.middleware.hertz_client

struct FormReq {
    1: string FormValue (api.form="form1"); // form annotation is used to declare the form parameter ("multipart/form-data")
}

struct QueryReq {
    1: string QueryValue (api.query="query1"); // query annotation is used to declare the query parameters of the request
}

struct PathReq {
    1: string PathValue (api.path="path1"); // path annotation is used to declare the routing parameters in the url
}

struct BodyReq {
    1: string BodyValue (api.body="body"); //  body annotation sets the entire structure to the body as a json, regardless of whether it is declared or not.
    2: string QueryValue (api.query="query2");
}

struct Resp {
    1: string Resp;
}

service HelloService {
    // api.post is used to declare the route of the request
    Resp FormMethod(1: FormReq request) (api.post="/form", api.handler_path="post");
    Resp QueryMethod(1: QueryReq request) (api.get="/query", api.handler_path="get");
    Resp PathMethod(1: PathReq request) (api.post="/path:path1", api.handler_path="post");
    Resp BodyMethod(1: BodyReq request) (api.post="/body", api.handler_path="post");
}(
    // api.base_domain is used to specify the default domain for client requests
    api.base_domain="http://127.0.0.1:8888";
)

Generate client code

hz client --mod=a/b/c --idl=../idl/psm.thrift --model_dir=model --client_dir=hertz_client -t=template=slim

Advanced Settings

Client Option

Take the code generated by thrift IDL as an example

func main() {
   generatedClient, err := hello_service.NewHelloServiceClient("https://www.example.com"), 
   hello_service.WithHertzClientOption() // Specify client configuration
}

Request-level configuration

Take the code generated by thrift IDL as an example

func main() {
	generatedClient, err := hello_service.NewHelloServiceClient(
		"http://toutiao.hertz.testa",
		)
    // The request level configuration can be specified when the call is initiated
    resp, rawResp, err := generatedClient.QueryMethod(
        context.Background(),
        QueryReq,
        config.WithSD(true), // Specify the request level setting to enable service discovery
        config.WithReadTimeout(), // Specify the request read timeout
        )
    if err != nil {
       fmt.Println(err)
       return
    }
}

Set client middleware

Take the code generated by thrift IDL as an example

func main() {
	generatedClient, err := hello_service.NewHelloServiceClient(
		"http://toutiao.hertz.testa", 
		hello_service.WithHertzClientMiddleware(), // Specify the client's middleware
		)
}

Set global header

Take the code generated by thrift IDL as an example

There are some generic header that may need to be carried in every request, or some header that cannot be defined in IDL, then we can inject these header with “WithHeader” so that every request sent will carry these header.

func main() {
	generatedClient, err := hello_service.NewHelloServiceClient(
		"http://toutiao.hertz.testa",
		hello_service.WithHeader(), // Specify the header that needs to be carried for each request sent 
	)
}

Configure TLS

Take the code generated by thrift IDL as an example

Hertz client’s TLS goes through the standard network library, so you need to configure it for the standard network library when using the generated one-click calls.

func main() {
	generatedClient, err := hello_service.NewHelloServiceClient("https://www.example.com"), 
	hello_service.WithHertzClientOption(
		client.WithDialer(standard.NewDialer()), // Use of standard libraries
		client.WithTLSConfig(clientCfg), // TLS Configuration
	)
}

Custom hertz client

Take the code generated by thrift IDL as an example

func main() {
   generatedClient, err := hello_service.NewHelloServiceClient("https://www.example.com"), 
   hello_service.WithHertzClient() // Specify custom hertz client
}