package main import ( "context" "fmt" "log" "net" "github.com/mwitkow/grpc-proxy/proxy" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" ) var director proxy.StreamDirector func main() { // director = func(ctx context.Context, fullMethodName string) (context.Context, *grpc.ClientConn, error) { // // Make sure we never forward internal services. // if strings.HasPrefix(fullMethodName, "/com.example.internal.") { // return nil, nil, status.Errorf(codes.Unimplemented, "Unknown method") // } // md, ok := metadata.FromIncomingContext(ctx) // // Copy the inbound metadata explicitly. // outCtx := metadata.NewOutgoingContext(ctx, md.Copy()) // if ok { // // Decide on which backend to dial // if val, exists := md[":authority"]; exists && val[0] == "staging.api.example.com" { // // Make sure we use DialContext so the dialing can be cancelled/time out together with the context. // conn, err := grpc.DialContext(ctx, "api-service.staging.svc.local") // return outCtx, conn, err // } else if val, exists := md[":authority"]; exists && val[0] == "api.example.com" { // conn, err := grpc.DialContext(ctx, "api-service.prod.svc.local") // return outCtx, conn, err // } // } // return nil, nil, status.Errorf(codes.Unimplemented, "Unknown method") // } // director. fmt.Println(test()) } func test() error { socketPath := "/state/home/projects/workbench/26-headscale-tailnets/headscale.sock" // // Connect to Unix socket // dst, err := grpc.Dial( // "unix://"+socketPath, // grpc.WithTransportCredentials(insecure.NewCredentials()), // ) // if err != nil { // return err // } // defer dst.Close() // Connect to TCP address instead of socket dst, err := grpc.Dial( "localhost:8081", grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { return err } defer dst.Close() // Create proxy with director director := func(ctx context.Context, fullMethodName string) (context.Context, *grpc.ClientConn, error) { log.Printf("Director called for method: %s", fullMethodName) // Extract incoming metadata/headers md, ok := metadata.FromIncomingContext(ctx) if ok { log.Printf("Forwarding headers: %v", md) // Extract the intended host from :authority header if authority := md.Get(":authority"); len(authority) > 0 { log.Printf("Intended host: %s", authority[0]) } // Also check for host header (HTTP/1.1 style) if host := md.Get("host"); len(host) > 0 { log.Printf("Host header: %s", host[0]) } // Forward headers to outgoing context ctx = metadata.NewOutgoingContext(ctx, md) } return ctx, dst, nil } // Create gRPC server with proxy handler server := grpc.NewServer( grpc.CustomCodec(proxy.Codec()), grpc.UnknownServiceHandler(proxy.TransparentHandler(director)), ) // Listen on TCP lis, err := net.Listen("tcp", ":8090") if err != nil { return err } log.Printf("gRPC proxy listening on :8090, forwarding to %s", socketPath) return server.Serve(lis) } // func test2() error { // dst, err := grpc.Dial("example.com") // if err != nil { // return err // } // proxy := proxy.NewProxy(dst) // grpc.Dia // ip, err := net.ListenIP("tcp", "127.0.0.1") // if err != nil { // return err // } // proxy.Serve(ip) // return nil // }