127 lines
3.3 KiB
Go
127 lines
3.3 KiB
Go
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
|
|
|
|
// }
|