How to modify result of a database query for a client in a MySQL protocol via Golang?

Viewed 54

I have a task to modify result of a query to MySQL server. I've created a simple Golang tcp proxy-server which can bypass packets from client to server and reverse. Now it looks like this:

package proxy

import (
    "io"
    "net"

    ll "common/logger"
)

type MysqlProxy struct {
    logger    ll.Logger
    proxy     net.Listener
    mysqlAddr string
}

func NewMysqlProxy(logger ll.Logger, proxyAddr, mysqlAddr string) (*MysqlProxy, error) {
    tcpServer, err := net.Listen("tcp", proxyAddr)
    if err != nil {
        return nil, err
    }

    return &MysqlProxy{
        logger:    logger,
        proxy:     tcpServer,
        mysqlAddr: mysqlAddr,
    }, nil
}

func (p *MysqlProxy) Close() error {
    return p.proxy.Close()
}

func (p *MysqlProxy) AcceptConnection() {
    tlsConn, err := p.proxy.Accept()
    if err != nil {
        p.logger.Error(
            "[MysqlProxy] error on accepting a new tls-connection",
        )
        return
    }

    p.logger.Info(
        "[MysqlProxy] accepted a connection on a proxy server",
        ll.LogField("proxy_server_remote_addr", ll.FieldTypeString, tlsConn.RemoteAddr().String()),
        ll.LogField("proxy_server_local_addr", ll.FieldTypeString, tlsConn.LocalAddr().String()),
        ll.LogField("target_db_server", ll.FieldTypeString, p.mysqlAddr),
    )

    go p.handleConnection(tlsConn)
}

func (p *MysqlProxy) handleConnection(proxyConn net.Conn) {
    defer func(proxyConn net.Conn) {
        if err := proxyConn.Close(); err != nil {
            p.logger.Error(
                "[MysqlProxy] error on closing connection from proxy",
            )
        }
    }(proxyConn)

    mysql, err := net.Dial("tcp", p.mysqlAddr)
    if err != nil {
        return
    }

    go func() {
        _, err := io.Copy(proxyConn, mysql)
        if err != nil {
            p.logger.Error(
                "[MysqlProxy] error on coping bytes from mysql to proxy",
            )
        }
    }()

    if _, err := io.Copy(mysql, proxyConn); err != nil {
        p.logger.Error(
            "[MysqlProxy] error on coping bytes from proxy to mysql",
        )
    }
}

However, now it just bypass bytes and I need to analyze the packets from the server to the client:

if _, err := io.Copy(mysql, proxyConn); err != nil {

There are several libs in Go which provide a client, proxy or protocol itself:

but I've not found examples of working with raw bytes from the server there. I need to get a string representation from the result (ex. rows from the "SELECT..." query), work with them, then pack back to the raw-bytes response and send it to the client.

0 Answers
Related