github.com/livekit/protocol@v1.16.1-0.20240517185851-47e4c6bba773/utils/interceptors/curl.go (about)

     1  package interceptors
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"io"
     7  	"net/http"
     8  	"sort"
     9  
    10  	"github.com/twitchtv/twirp"
    11  	"google.golang.org/protobuf/encoding/protojson"
    12  	"google.golang.org/protobuf/proto"
    13  )
    14  
    15  // NewCurlPrinter creates a Twirp interceptor that prints a curl commands for each request made.
    16  func NewCurlPrinter(w io.Writer, url string) twirp.Interceptor {
    17  	return func(next twirp.Method) twirp.Method {
    18  		return func(ctx context.Context, req any) (any, error) {
    19  			pkg, ok1 := twirp.PackageName(ctx)
    20  			svc, ok2 := twirp.ServiceName(ctx)
    21  			meth, ok3 := twirp.MethodName(ctx)
    22  			if !ok1 || !ok2 || !ok3 {
    23  				return next(ctx, req)
    24  			}
    25  			m, ok := req.(proto.Message)
    26  			if !ok {
    27  				return next(ctx, req)
    28  			}
    29  			hdr, _ := twirp.HTTPRequestHeaders(ctx)
    30  			if err := printCurl(w, url, pkg, svc, meth, hdr, m); err != nil {
    31  				return nil, err
    32  			}
    33  			return next(ctx, req)
    34  		}
    35  	}
    36  }
    37  
    38  func printCurl(w io.Writer, url, pkg, svc, meth string, hdr http.Header, req proto.Message) error {
    39  	data, err := protojson.Marshal(req)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	buf, isBuf := w.(*bytes.Buffer)
    44  	if !isBuf {
    45  		buf = new(bytes.Buffer)
    46  	}
    47  	buf.WriteString("curl ")
    48  	buf.WriteString(`-X POST `)
    49  	buf.WriteString("\\\n\t")
    50  	hkeys := make([]string, 0, len(hdr))
    51  	for k := range hdr {
    52  		hkeys = append(hkeys, k)
    53  	}
    54  	sort.Strings(hkeys)
    55  	for _, h := range hkeys {
    56  		switch h {
    57  		case "Content-Type":
    58  			continue
    59  		}
    60  		for _, v := range hdr[h] {
    61  			buf.WriteString(`-H '`)
    62  			buf.WriteString(h)
    63  			buf.WriteString(`: `)
    64  			buf.WriteString(v)
    65  			buf.WriteString(`' `)
    66  			buf.WriteString("\\\n\t")
    67  		}
    68  	}
    69  	buf.WriteString(`-H 'Content-Type: application/json' `)
    70  	buf.WriteString("\\\n\t")
    71  	buf.WriteString(`--data '`)
    72  	buf.Write(data)
    73  	buf.WriteString(`' `)
    74  	buf.WriteString("\\\n\t")
    75  	buf.WriteString(url)
    76  	buf.WriteString("/twirp/")
    77  	buf.WriteString(pkg)
    78  	buf.WriteString(".")
    79  	buf.WriteString(svc)
    80  	buf.WriteString("/")
    81  	buf.WriteString(meth)
    82  	buf.WriteString("\n")
    83  	if isBuf {
    84  		return nil
    85  	}
    86  	_, err = buf.WriteTo(w)
    87  	return err
    88  }