Skip to content

10 Zinx Interceptor

刘丹冰 edited this page May 12, 2023 · 3 revisions

Case Source Code : https://github.com/aceld/zinx-usage/tree/main/zinx_interceptor

Zinx provides interceptors for data packet interception. During the process of reading data from the raw transmission, Zinx allows developers to add custom interceptors (IIterceptor) to connections for handling data in a chain of responsibility fashion. This enables developers to process packets based on their specific characteristics using different interceptor methods. There is no limit to the number of interceptors that can be added.

Zinx's interceptor is built on top of a chain of responsibility (IChain), where interceptors (IInterceptor) are executed in sequence. image

1. IChain Interface

The IChain interface is defined as follows:

// Chain of responsibility
type IChain interface {
	Request() IcReq       // Get the request data in the current chain (current interceptor)
	Proceed(IcReq) IcResp // Enter and execute the next interceptor, passing the request data to the next interceptor
}

2. IInterceptor Interface

The interceptor interface, IInterceptor, is defined as follows:

// Interceptor
type IInterceptor interface {
	Intercept(IChain) IcResp // Interception processing method of the interceptor (defined by the developer)
}

Here, IcReq and IcResp represent the input and output data of the interceptor, respectively, and they are defined as follows:

// Interceptor input data
type IcReq interface{}

// Interceptor output data
type IcResp interface{}

Regarding the interfaces related to the chain of responsibility, developers don't need to pay too much attention to them because Zinx already has a default chain of responsibility established. What developers need to focus on is how to add their custom interceptors to the Zinx chain of responsibility for data packet interception and handling.

3. Adding an Interceptor to the Chain for Server/Client

3.1 Define an Interceptor

type MyInterceptor struct{}

func (m *MyInterceptor) Intercept(chain ziface.IChain) ziface.IcResp {
	request := chain.Request() // Get the input data of the current interceptor from the chain

	// Custom logic for the interceptor's processing, here we simply print the input
	iRequest := request.(ziface.IRequest) // Note: Due to the type of Zinx's Request, we need to do a type assertion here

	fmt.Println("Custom interceptor, received message:", iRequest.GetData())

	return chain.Proceed(chain.Request()) // Enter and execute the next interceptor
}

We can use server.AddInterceptor() / client.AddInterceptor() to add an interceptor to the connections of the server/client.

3.2 Adding Interceptor to Server/Client

package main

import (
	"fmt"
	"github.com/aceld/zinx/ziface"
	"github.com/aceld/zinx/znet"
)

type HelloRouter struct {
	znet.BaseRouter
}

func (hr *HelloRouter) Handle(request ziface.IRequest) {
	fmt.Println(string(request.GetData()))
}

func main() {
	// Create a server object
	server := znet.NewServer()
	// Add route mappings
	server.AddRouter(1, &HelloRouter{})
	// Add custom interceptor
	server.AddInterceptor(&MyInterceptor{})
	// Start the server
	server.Serve()
}

After running the client, the interceptor's output received by the server would be as follows:

Aceld@AcelddeMacBook-Pro zinx_interceptor (main) $ go run server.go 
                                        
              ██                        
              ▀▀                        
 ████████   ████     ██▄████▄  ▀██  ██▀ 
     ▄█▀      ██     ██▀   ██    ████   
   ▄█▀        ██     ██    ██    ▄██▄   
 ▄██▄▄▄▄▄  ▄▄▄██▄▄▄  ██    ██   ▄█▀▀█▄  
 ▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀  ▀▀    ▀▀  ▀▀▀  ▀▀▀ 
                                        
┌──────────────────────────────────────────────────────┐
│ [Github] https://github.com/aceld                    │
│ [tutorial] https://www.yuque.com/aceld/npyr8s/bgftov │
│ [document] https://www.yuque.com/aceld/tsgooa        │
└──────────────────────────────────────────────────────┘
[Zinx] Version: V1.0, MaxConn: 12000, MaxPacketSize: 4096
===== Zinx Global Config =====
Host: 0.0.0.0
TCPPort: 8999
Name: ZinxServerApp
Version: V1.0
MaxPacketSize: 4096
MaxConn: 12000
WorkerPoolSize: 10
MaxWorkerTaskLen: 1024
MaxMsgChanLen: 1024
IOReadBuffSize: 1024
LogDir: /Users/Aceld/go/src/zinx-usage/zinx_interceptor/log
LogFile: zinx.log
LogIsolationLevel: 0
HeartbeatMax: 10
CertFile: 
PrivateKeyFile: 
==============================
Custom interceptor, received message: %s [0 0 0 1 0 0 0 33 80 105 110 103 46 46 46 80 105 110 103 46 46 46 80 105 110 103 46 46 46 91 70 114 111 109 67 108 105 101 110 116 93]
Ping...Ping...Ping...[FromClient]
Custom interceptor, received message: %s [0 0 0 1 0 0 0 33 80 105 110 103 46 46 46 80 105 110 103 46 46 46 80 105 110 103 46 46 46 91 70 114 111 109 67 108 105 101 110 116 93]
Ping...Ping...Ping...[FromClient]
Custom interceptor, received message: %s [0 0 0 1 0 0 0 33 80 105 110 103 46 46 46 80 105 110 103 46 46 46 80 105 110 103 46 46 46 91 70 114 111 109 67 108 105 101 110 116 93]
Ping...Ping...Ping...[FromClient]
Custom interceptor, received message:%s [0 0 0 1 0 0 0 33 80 105 110 103 46 46 46 80 105 110 103 46 46 46 80 105 110 103 46 46 46 91 70 114 111 109 67 108 105 101 110 116 93]
Ping...Ping...Ping...[FromClient]