Skip to main content

Generated Go protobuf and Connect-RPC client for Flaggr

Go SDK

Generated Go protobuf types and Connect-RPC client stubs for Flaggr. Supports both Connect-RPC (HTTP) and gRPC transports.

Installation

go get github.com/flaggr/flaggr/proto/v1

Connect-RPC Client

Connect-RPC is the recommended transport — it works over HTTP/1.1 and HTTP/2 without a gRPC proxy.

package main
 
import (
	"context"
	"log"
	"net/http"
 
	"connectrpc.com/connect"
	flaggrv1 "github.com/flaggr/flaggr/proto/v1"
	"github.com/flaggr/flaggr/proto/v1/flaggrv1connect"
)
 
func main() {
	client := flaggrv1connect.NewEvaluationServiceClient(
		http.DefaultClient,
		"https://flaggr.dev",
	)
 
	resp, err := client.ResolveBoolean(context.Background(),
		connect.NewRequest(&flaggrv1.ResolveBooleanRequest{
			FlagKey:      "checkout-v2",
			DefaultValue: false,
			Context: &flaggrv1.EvaluationContext{
				TargetingKey: "user-456",
				StringAttributes: map[string]string{
					"plan":    "enterprise",
					"country": "AU",
				},
			},
			ServiceId: "web-app",
		}),
	)
	if err != nil {
		log.Fatal(err)
	}
 
	log.Printf("checkout-v2 = %v (reason: %s)", resp.Msg.Value, resp.Msg.Reason)
}

gRPC Client

If you prefer standard gRPC:

package main
 
import (
	"context"
	"log"
 
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
 
	flaggrv1 "github.com/flaggr/flaggr/proto/v1"
)
 
func main() {
	conn, err := grpc.NewClient("flaggr.dev:443",
		grpc.WithTransportCredentials(insecure.NewCredentials()),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
 
	client := flaggrv1.NewEvaluationServiceClient(conn)
 
	resp, err := client.ResolveBoolean(context.Background(),
		&flaggrv1.ResolveBooleanRequest{
			FlagKey:      "checkout-v2",
			DefaultValue: false,
			Context: &flaggrv1.EvaluationContext{
				TargetingKey: "user-456",
			},
			ServiceId: "web-app",
		},
	)
	if err != nil {
		log.Fatal(err)
	}
 
	log.Printf("checkout-v2 = %v (reason: %s)", resp.Value, resp.Reason)
}

Flag Evaluation

Boolean

resp, err := client.ResolveBoolean(ctx, connect.NewRequest(&flaggrv1.ResolveBooleanRequest{
	FlagKey:      "dark-mode",
	DefaultValue: false,
	Context:      evalCtx,
	ServiceId:    "web-app",
}))

String

resp, err := client.ResolveString(ctx, connect.NewRequest(&flaggrv1.ResolveStringRequest{
	FlagKey:      "button-color",
	DefaultValue: "blue",
	Context:      evalCtx,
	ServiceId:    "web-app",
}))

Number

resp, err := client.ResolveNumber(ctx, connect.NewRequest(&flaggrv1.ResolveNumberRequest{
	FlagKey:      "rate-limit",
	DefaultValue: 100,
	Context:      evalCtx,
	ServiceId:    "web-app",
}))

Object (JSON)

resp, err := client.ResolveObject(ctx, connect.NewRequest(&flaggrv1.ResolveObjectRequest{
	FlagKey:      "banner-config",
	DefaultValue: `{"text":"","color":"blue","dismissible":true}`,
	Context:      evalCtx,
	ServiceId:    "web-app",
}))

Bulk Evaluation

resp, err := client.BulkEvaluateFlags(ctx, connect.NewRequest(&flaggrv1.BulkEvaluateFlagsRequest{
	FlagKeys:  []string{"checkout-v2", "dark-mode", "rate-limit"},
	Context:   evalCtx,
	ServiceId: "web-app",
}))
 
for key, result := range resp.Msg.Flags {
	log.Printf("%s = %v (reason: %s)", key, result.Value, result.Reason)
}

Streaming

Subscribe to real-time flag updates with server-side streaming:

stream := flaggrv1connect.NewFlagStreamServiceClient(
	http.DefaultClient,
	"https://flaggr.dev",
)
 
resp, err := stream.StreamFlags(ctx, connect.NewRequest(&flaggrv1.StreamFlagsRequest{
	ServiceId:   "web-app",
	Environment: flaggrv1.Environment_ENVIRONMENT_PRODUCTION,
	ClientId:    "go-service-01",
	ApiToken:    "flg_your_token",
}))
if err != nil {
	log.Fatal(err)
}
 
for resp.Receive() {
	update := resp.Msg()
	switch update.EventType {
	case flaggrv1.FlagEventType_FLAG_EVENT_TYPE_UPDATED:
		log.Printf("flag %s updated", update.FlagKey)
	case flaggrv1.FlagEventType_FLAG_EVENT_TYPE_TOGGLED:
		log.Printf("flag %s toggled", update.FlagKey)
	case flaggrv1.FlagEventType_FLAG_EVENT_TYPE_HEARTBEAT:
		// connection alive
	}
}
if err := resp.Err(); err != nil {
	log.Fatal(err)
}

OpenFeature Integration

Use with the OpenFeature Go SDK:

package main
 
import (
	"context"
	"log"
 
	"github.com/open-feature/go-sdk/openfeature"
)
 
func main() {
	// Register the Flaggr provider
	openfeature.SetProvider(NewFlaggrProvider("https://flaggr.dev", "web-app", "flg_your_token"))
 
	client := openfeature.NewClient("my-service")
 
	value, err := client.BooleanValue(context.Background(), "checkout-v2", false,
		openfeature.NewEvaluationContext("user-456", map[string]interface{}{
			"plan":    "enterprise",
			"country": "AU",
		}),
	)
	if err != nil {
		log.Fatal(err)
	}
 
	log.Printf("checkout-v2 = %v", value)
}

The FlaggrProvider wraps the Connect-RPC client and implements the openfeature.FeatureProvider interface. See the OpenFeature Go SDK docs for more on evaluation context, hooks, and event handling.