### Basic Setup with Server Reflection Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/configuration.md Configure gRPC UI with server reflection to automatically discover services and methods. This is a common starting point for gRPC UI setup. ```go ctx := context.Background() cc, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatal(err) } deferr cc.Close() handler, err := standalone.HandlerViaReflection(ctx, cc, "localhost:50051") if err != nil { log.Fatal(err) } http.ListenAndServe(":8080", handler) ``` -------------------------------- ### Add Examples to UI with WithExamples Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/standalone-api.md Use WithExamples to add pre-configured example RPC requests to the UI. These examples are displayed for quick reference. ```go example := standalone.Example{ Name: "Say Hello", Description: "Basic greeting", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Data: map[string]interface{}{"name": "World"}, }, } opt, err := standalone.WithExamples(example) if err != nil { log.Fatal(err) } handler := standalone.Handler(cc, target, methods, files, opt) ``` -------------------------------- ### Minimal gRPC UI Setup in Go Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md This example demonstrates the most basic setup for serving a gRPC UI. It connects to a gRPC server and serves the UI on localhost:8080 using auto-discovery via reflection. ```go package main import ( "context" "log" "net/http" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" ) func main() { ctx := context.Background() // Connect to gRPC server cc, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer cc.Close() // Create handler with auto-discovery handler, err := standalone.HandlerViaReflection(ctx, cc, "localhost:50051") if err != nil { log.Fatal(err) } // Serve on localhost:8080 log.Println("gRPC UI at http://localhost:8080") log.Fatal(http.ListenAndServe(":8080", handler)) } ``` -------------------------------- ### Add Pre-configured Examples Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/quickstart-reference.md Include predefined examples for specific RPC methods to simplify user interaction. Each example can specify the service, method, and request data. ```go examples := []standalone.Example{ { Name: "Say Hello", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Data: map[string]interface{}{"name": "World"}, }, }, } opt, _ := standalone.WithExamples(examples...) handler := standalone.Handler(cc, "localhost:50051", methods, files, opt) ``` -------------------------------- ### gRPC UI with Pre-configured Examples in Go Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md This example demonstrates how to create and serve pre-defined gRPC requests as examples within the UI. It uses reflection to discover methods and files, then defines example requests with metadata and data payloads. ```go package main import ( "context" "log" "net/http" "github.com/fullstorydev/grpcui" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" ) func main() { ctx := context.Background() cc, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer cc.Close() // Get methods and files methods, err := grpcui.AllMethodsViaReflection(ctx, cc) if err != nil { log.Fatal(err) } files, err := grpcui.AllFilesViaReflection(ctx, cc) if err != nil { log.Fatal(err) } // Create examples examples := []standalone.Example{ { Name: "Simple Greeting", Description: "Say hello to Alice", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Metadata: []standalone.ExampleMetadataPair{ {Name: "user-id", Value: "user123"}, }, Data: map[string]interface{}{ "name": "Alice", }, }, }, { Name: "Greeting with Token", Description: "Say hello with authentication", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Metadata: []standalone.ExampleMetadataPair{ {Name: "authorization", Value: "Bearer eyJhbGc..."}, }, Data: map[string]interface{}{ "name": "Bob", }, }, }, } // Create handler with examples examplesOpt, err := standalone.WithExamples(examples...) if err != nil { log.Fatal(err) } handler := standalone.Handler(cc, "localhost:50051", methods, files, examplesOpt, ) log.Println("gRPC UI at http://localhost:8080") log.Fatal(http.ListenAndServe(":8080", handler)) } ``` -------------------------------- ### gRPC UI Setup with Options in Go Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md This example shows how to configure the gRPC UI handler with additional options. It enables client-side debugging and sets default metadata for all requests. ```go package main import ( "context" "log" "net/http" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" ) func main() { ctx := context.Background() cc, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer cc.Close() // Create handler with options handler, err := standalone.HandlerViaReflection(ctx, cc, "localhost:50051", standalone.WithClientDebug(true), standalone.WithDefaultMetadata([]string{ "user-id: user123", "environment: dev", }), ) if err != nil { log.Fatal(err) } log.Println("gRPC UI at http://localhost:8080 (debug enabled)") log.Fatal(http.ListenAndServe(":8080", handler)) } ``` -------------------------------- ### WithExamples Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/standalone-api.md Adds pre-configured example RPC requests to the UI. The examples are displayed in the web UI for quick reference. ```APIDOC ## WithExamples ### Description Adds pre-configured example RPC requests to the UI. The examples are displayed in the web UI for quick reference. ### Function Signature ```go func WithExamples(examples ...Example) (HandlerOption, error) ``` ### Parameters #### Variadic Parameters - **examples** (`...Example`) - Required - Variable list of example requests ### Returns - `HandlerOption` - Option to pass to `Handler` - `error` - Error if unable to encode examples to JSON ### Example ```go example := standalone.Example{ Name: "Say Hello", Description: "Basic greeting", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Data: map[string]interface{}{"name": "World"}, }, } opt, err := standalone.WithExamples(example) if err != nil { log.Fatal(err) } handler := standalone.Handler(cc, target, methods, files, opt) ``` ``` -------------------------------- ### Retrieve Pre-configured Example RPC Requests Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/http-endpoints.md This endpoint returns a list of pre-configured example RPC requests. It returns an empty array if no examples have been set up. ```bash curl http://localhost:8080/examples ``` -------------------------------- ### GET /examples Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/http-endpoints.md Retrieves pre-configured example RPC requests. This endpoint is useful for quickly testing or understanding how to format requests for specific gRPC methods. ```APIDOC ## GET /examples ### Description Retrieves pre-configured example RPC requests. ### Method GET ### Endpoint /examples ### Response #### Success Response (200) - **name** (string) - Display name for the example - **description** (string) - Human-readable description of the example - **service** (string) - Fully-qualified service name (e.g., `helloworld.Greeter`) - **method** (string) - Method name (e.g., `SayHello`) - **request** (object) - Pre-configured request with timeout, metadata, and data ### Response Example ```json [ { "name": "Say Hello", "description": "A simple greeting request", "service": "helloworld.Greeter", "method": "SayHello", "request": { "timeout_secs": 10, "metadata": [ { "name": "authorization", "value": "Bearer token123" } ], "data": { "name": "World" } } } ] ``` ### Example ```bash curl http://localhost:8080/examples ``` ``` -------------------------------- ### Create an Example RPC Instance Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/types.md Illustrates how to instantiate and populate an Example struct for a specific RPC call, including timeout and metadata. ```go example := Example{ Name: "Say Hello", Description: "A simple greeting request", Service: "helloworld.Greeter", Method: "SayHello", Request: ExampleRequest{ TimeoutSeconds: 10, Metadata: []ExampleMetadataPair{ {Name: "authorization", Value: "Bearer token123"}, }, Data: map[string]interface{}{"name": "World"}, }, } ``` -------------------------------- ### Add Examples from JSON Data with WithExampleData Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/standalone-api.md Use WithExampleData to add examples to the UI from raw JSON data. The data must be valid JSON that unmarshals to []Example. ```go examplesJSON := []byte(`[ { "name": "Say Hello", "description": "Basic greeting", "service": "helloworld.Greeter", "method": "SayHello", "request": { "timeout_secs": 10, "metadata": [], "data": {"name": "World"} } } ]`) opt, err := standalone.WithExampleData(examplesJSON) if err != nil { log.Fatal(err) } handler := standalone.Handler(cc, target, methods, files, opt) ``` -------------------------------- ### Install grpcui from Source with Go Source: https://github.com/fullstorydev/grpcui/blob/master/README.md Install the grpcui command-line tool using the Go toolchain. Ensure your $GOPATH/bin is in your $PATH. ```shell go install github.com/fullstorydev/grpcui/cmd/grpcui@latest ``` -------------------------------- ### WithExampleData Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/standalone-api.md Adds examples to the UI from raw JSON data. The data must be valid JSON that unmarshals to `[]Example`. ```APIDOC ## WithExampleData ### Description Adds examples to the UI from raw JSON data. The data must be valid JSON that unmarshals to `[]Example`. ### Function Signature ```go func WithExampleData(data []byte) (HandlerOption, error) ``` ### Parameters #### Path Parameters - **data** (`[]byte`) - Required - JSON-encoded slice of examples ### Returns - `HandlerOption` - Option to pass to `Handler` - `error` - Error if JSON is invalid ### Example ```go examplesJSON := []byte(`[ { "name": "Say Hello", "description": "Basic greeting", "service": "helloworld.Greeter", "method": "SayHello", "request": { "timeout_secs": 10, "metadata": [], "data": {"name": "World"} } } ]`) opt, err := standalone.WithExampleData(examplesJSON) if err != nil { log.Fatal(err) } handler := standalone.Handler(cc, target, methods, files, opt) ``` ``` -------------------------------- ### Build and Install grpcui from Source Source: https://github.com/fullstorydev/grpcui/blob/master/README.md Build and install the grpcui command-line tool from the repository sources using make. This is useful if you have cloned the repo outside your $GOPATH. ```shell make install ``` -------------------------------- ### Adding Examples and Custom Assets Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/configuration.md Enhance gRPC UI with predefined examples for services and methods, and serve custom JavaScript and static assets like images. This improves usability and interactivity. ```go examples := []standalone.Example{ { Name: "Simple Greeting", Description: "Say hello to someone", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Metadata: []standalone.ExampleMetadataPair{ {Name: "user-id", Value: "user123"}, }, Data: map[string]interface{}{"name": "Alice"}, }, }, { Name: "Greeting with Token", Description: "Say hello with authentication", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Metadata: []standalone.ExampleMetadataPair{ {Name: "authorization", Value: "Bearer token123"}, }, Data: map[string]interface{}{"name": "Bob"}, }, }, } examplesOpt, err := standalone.WithExamples(examples...) if err != nil { log.Fatal(err) } customJS := []byte( `window.addEventListener('load', function() { console.log('gRPC UI loaded'); }); `) logoData, err := os.ReadFile("/path/to/logo.png") if err != nil { log.Fatal(err) } handler := standalone.Handler(conn, "localhost:50051", methods, files, examplesOpt, standalone.AddJS("app.js", customJS), standalone.ServeAsset("logo.png", logoData), ) http.ListenAndServe(":8080", handler) ``` -------------------------------- ### Example RPC Request Configuration Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/standalone-api.md Configures a simple 'Hello' RPC request with metadata and data. ```go example := standalone.Example{ Name: "Simple Hello", Description: "Basic greeting request", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Metadata: []standalone.ExampleMetadataPair{ {Name: "authorization", Value: "Bearer token123"}, }, Data: map[string]interface{}{ "name": "World", }, }, } ``` -------------------------------- ### gRPC UI with Custom HTML Template and CSS in Go Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md This example illustrates how to customize the appearance of the gRPC UI by providing a custom HTML template and CSS. Note: This is a conceptual example and requires obtaining methods and files separately, as shown in Example 4. ```go package main import ( "context" "html/template" "log" "net/http" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" ) func main() { ctx := context.Background() cc, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer cc.Close() // Custom HTML template customTmpl := template.Must(template.New("index.html").Parse(` {{ .Target }} - gRPC UI {{ range .AddlResources }}{{ . }}{{ end }}

gRPC UI for {{ .Target }}

Interactive interface for testing gRPC services

{{ .WebFormContents }}
`)) // Custom CSS customCSS := []byte(` body { font-family: 'Segoe UI', sans-serif; line-height: 1.6; color: #333; } .grpc-web-form { background: white; border: 1px solid #ddd; border-radius: 4px; padding: 20px; } `) // Get methods and files methods, err := standalone.Handler(cc, "localhost:50051", []/*methods*/, []/*files*/, standalone.WithIndexTemplate(customTmpl), standalone.WithCSS(customCSS), ) // Actually need to get methods/files first: // This is a conceptual example - see Example 4 for complete code } ``` -------------------------------- ### Load Examples from File Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md Loads a slice of standalone.Example from a JSON file. Handles file reading and JSON unmarshalling. ```go import ( "encoding/json" "io/ioutil" ) func loadExamplesFromFile(path string) ([]standalone.Example, error) { data, err := ioutil.ReadFile(path) if err != nil { return nil, err } var examples []standalone.Example err = json.Unmarshal(data, &examples) return examples, err } // Usage examples, _ := loadExamplesFromFile("./examples.json") opt, _ := standalone.WithExamples(examples...) ``` -------------------------------- ### Configure Standalone Handler with Examples and Debugging Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/configuration.md Set up the standalone gRPC UI handler with pre-defined examples, enable client-side JavaScript console logging, and configure RPC handler verbosity. ```go example := standalone.Example{ Name: "Say Hello", Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Data: map[string]interface{}{"name": "World"}, }, } opt, err := standalone.WithExamples(example) if err != nil { log.Fatal(err) } handler := standalone.Handler(conn, "localhost:50051", methods, files, opt, standalone.WithClientDebug(true), ) ``` -------------------------------- ### Install grpcui with Homebrew Source: https://github.com/fullstorydev/grpcui/blob/master/README.md Use Homebrew to install the grpcui command-line tool on macOS or Linux. ```shell brew install grpcui ``` -------------------------------- ### Create Example from Proto Message Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md Helper function to construct a standalone.Example from a proto message and a name. It specifies the service, method, and request data. ```go import pb "github.com/example/helloworld" func makeExample(name string, req *pb.HelloRequest) standalone.Example { return standalone.Example{ Name: name, Service: "helloworld.Greeter", Method: "SayHello", Request: standalone.ExampleRequest{ TimeoutSeconds: 10, Data: req, }, } } // Usage example := makeExample("Simple", &pb.HelloRequest{Name: "World"}) ``` -------------------------------- ### Define Example RPC Structure Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/types.md Defines the structure for a pre-configured example RPC request, including service, method, and request details. ```go type Example struct { Name string Description string Service string Method string Request ExampleRequest } ``` -------------------------------- ### Fastest Setup with grpcui Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/README.md This is the quickest way to set up a gRPC UI handler using reflection. It requires gRPC dial context and establishes a connection to the server. Ensure the server address and port are correct. ```go ctx := context.Background() cc, _ := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) h, _ := standalone.HandlerViaReflection(ctx, cc, "localhost:50051") http.ListenAndServe(":8080", h) ``` -------------------------------- ### Define Example Request Structure Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/types.md Defines the structure for the request portion of an example RPC call, specifying timeout, metadata, and data. ```go type ExampleRequest struct { TimeoutSeconds float64 Metadata []ExampleMetadataPair Data interface{} } ``` -------------------------------- ### Production Server Configuration Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/quickstart-reference.md Example configuration for a production server using `HandlerViaReflection`. It includes authorization headers and disables default value emission. ```go handler, _ := standalone.HandlerViaReflection(ctx, cc, target, standalone.WithMetadata([]string{ "authorization: Bearer " + os.Getenv("API_TOKEN"), }), standalone.EmitDefaults(false), ) ``` -------------------------------- ### Shared Service Configuration Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/quickstart-reference.md Example configuration for a shared service using `HandlerViaReflection`. It sets default metadata, preserves specific headers, and includes example data. ```go handler, _ := standalone.HandlerViaReflection(ctx, cc, target, standalone.WithDefaultMetadata([]string{ "user-id: user123", }), standalone.PreserveHeaders([]string{"authorization"}), standalone.WithExampleData(examplesJSON), ) ``` -------------------------------- ### Define Example Metadata Pair Structure Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/types.md Defines the structure for a single metadata (header) pair used in example RPC requests. ```go type ExampleMetadataPair struct { Name string Value string } ``` -------------------------------- ### Setup with Custom HTML Template Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/README.md Customize the appearance of the gRPC UI by providing your own HTML template. This allows for branding and a tailored user experience. The template must be parsed before being passed to the handler. ```go tmpl := template.Must(template.New("index").Parse("...")) handler, _ := standalone.HandlerViaReflection(ctx, cc, "localhost:50051", standalone.WithIndexTemplate(tmpl), ) ``` -------------------------------- ### Run grpcui without Installation Source: https://github.com/fullstorydev/grpcui/blob/master/README.md Execute the grpcui command-line tool directly using 'go run' without a formal installation. This is useful for testing or quick usage. ```shell go run ./cmd/grpcui/grpcui.go -plaintext localhost:9019 ``` -------------------------------- ### gRPC UI with In-Process Server Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md This example demonstrates serving gRPC UI directly from an in-process gRPC server without needing a separate client connection. This is efficient for development and testing environments where the UI and server run in the same process. ```go package main import ( "context" "log" "net" "net/http" pb "github.com/example/helloworld" "github.com/fullstorydev/grpcui" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" ) // Implement your gRPC service type GreeterServer struct { pb.UnimplementedGreeterServer } func (s *GreeterServer) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { return &pb.HelloReply{ Message: "Hello " + req.Name, }, nil } func main() { // Create and start gRPC server grpcServer := grpc.NewServer() pb.RegisterGreeterServer(grpcServer, &GreeterServer{}) // Start in background lis, _ := net.Listen("tcp", "localhost:50051") go func() { log.Println("gRPC server at localhost:50051") grpcServer.Serve(lis) }() // Create UI handler using in-process server methods, _ := grpcui.AllMethodsViaInProcess(grpcServer) files, _ := grpcui.AllFilesViaInProcess() handler := standalone.Handler(grpcServer, "localhost:50051", methods, files) // Serve UI on different port log.Println("gRPC UI at http://localhost:8080") http.ListenAndServe(":8080", handler) } ``` -------------------------------- ### Get All Methods for Server Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/grpcui-main-api.md Retrieves all method descriptors exposed by a given gRPC server instance. Ensure the server is properly initialized before calling this function. ```go grpcServer := grpc.NewServer() // Register services... methods, err := grpcui.AllMethodsForServer(grpcServer) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Metadata Header Format Examples Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/configuration.md Examples of how to format metadata headers for gRPC-Web UI. Headers follow the 'name: value' format and are case-insensitive. Special handling applies to binary headers. ```text authorization: Bearer token123 x-request-id: req-abc-123 Content-Type: application/grpc user-agent: grpcui/1.0 ``` -------------------------------- ### Serve File-Based Assets with gRPC-Web UI Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/configuration.md Configure gRPC-Web UI to serve custom CSS, JavaScript, and static asset directories. This example shows how to add a CSS file, a JS file, and a directory of images, with path validation for security. ```go handler := standalone.Handler(conn, "localhost:50051", methods, files, standalone.AddCSSFile("theme.css", func() (io.ReadCloser, error) { return os.Open("/etc/grpcui/theme.css") }), standalone.AddJSFile("analytics.js", func() (io.ReadCloser, error) { return os.Open("/etc/grpcui/analytics.js") }), standalone.ServeAssetDirectory("images", func(filename string) (io.ReadCloser, error) { fullPath := filepath.Join("/var/www/images", filename) // Validate path is within /var/www/images if !strings.HasPrefix(fullPath, "/var/www/images") { return nil, os.ErrNotExist } return os.Open(fullPath) }), ) http.ListenAndServe(":8080", handler) ``` -------------------------------- ### Setup with Custom Metadata Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/README.md Configure the gRPC UI handler to include custom metadata, such as authorization tokens, during requests. This is useful for authenticating or passing additional information to your gRPC services. ```go handler, _ := standalone.HandlerViaReflection(ctx, cc, "localhost:50051", standalone.WithMetadata([]string{"authorization: Bearer token123"}), ) ``` -------------------------------- ### gRPC UI with Multiple Services and Sub-routing Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md This example demonstrates how to serve multiple gRPC services through a single gRPC UI instance by mounting handlers for each service on different URL paths. This is useful for managing and accessing distinct services from a unified dashboard. ```go package main import ( "context" "log" "net/http" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" ) func main() { ctx := context.Background() // Connect to multiple services accountsSvc, _ := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) paymentSvc, _ := grpc.DialContext(ctx, "localhost:50052", grpc.WithInsecure()) defers accountsSvc.Close() defers paymentSvc.Close() // Create handlers for each service accountsHandler, _ := standalone.HandlerViaReflection(ctx, accountsSvc, "accounts-service:50051") paymentHandler, _ := standalone.HandlerViaReflection(ctx, paymentSvc, "payment-service:50052") // Mount on different paths mux := http.NewServeMux() mux.Handle("/accounts/", http.StripPrefix("/accounts", accountsHandler)) mux.Handle("/payments/", http.StripPrefix("/payments", paymentHandler)) // Add index page mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") w.Write([]byte(` gRPC UI Dashboard

gRPC UI Dashboard

`)) }) log.Println("gRPC UI dashboard at http://localhost:8080") log.Fatal(http.ListenAndServe(":8080", mux)) } ``` -------------------------------- ### Modular Assembly for Custom gRPC UI Page Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md This example shows how to build a custom HTML page for gRPC UI by programmatically generating its components like the web form, JavaScript, and CSS. It's useful when you need a highly customized UI or want to embed gRPC UI within a larger application. ```go package main import ( "context" "html/template" "log" "net/http" "github.com/fullstorydev/grpcui" "google.golang.org/grpc" ) func main() { ctx := context.Background() cc, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer cc.Close() // Get methods and files methods, err := grpcui.AllMethodsViaReflection(ctx, cc) if err != nil { log.Fatal(err) } files, err := grpcui.AllFilesViaReflection(ctx, cc) if err != nil { log.Fatal(err) } // Create handlers invokeOpts := grpcui.InvokeOptions{ EmitDefaults: true, Verbosity: 1, } rpcInvokeHandler := http.StripPrefix("/rpc/invoke", grpcui.RPCInvokeHandlerWithOptions(cc, methods, invokeOpts)) rpcMetadataHandler := grpcui.RPCMetadataHandler(methods, files) // Generate web form webFormOpts := grpcui.WebFormOptions{ DefaultMetadata: []string{"user-id: user123"}, Debug: boolPtr(true), } webFormHTML := grpcui.WebFormContentsWithOptions( "/rpc/invoke/", "/rpc/metadata", "localhost:50051", methods, webFormOpts) webFormJS := grpcui.WebFormScript() webFormCSS := grpcui.WebFormSampleCSS() // Create custom HTML page customPageTmpl := template.Must(template.New("page").Parse(` gRPC UI
{{ .WebForm }}
`)) // Register handlers mux := http.NewServeMux() mux.Handle("/rpc/invoke/", rpcInvokeHandler) mux.Handle("/rpc/metadata", rpcMetadataHandler) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } customPageTmpl.Execute(w, map[string]interface{}{ "CSS": string(webFormCSS), "WebForm": string(webFormHTML), "JS": string(webFormJS), }) }) log.Println("gRPC UI at http://localhost:8080") log.Fatal(http.ListenAndServe(":8080", mux)) } func boolPtr(b bool) *bool { return &b } ``` -------------------------------- ### GET / Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/http-endpoints.md Serves the main web UI page with an interactive form for selecting and invoking RPC methods. It includes embedded CSS, JavaScript, and a dynamically generated form. ```APIDOC ## GET / ### Description Returns the main HTML page containing the web form for selecting and invoking RPC methods. The page includes embedded CSS, JavaScript, and the dynamically-generated form based on available methods. ### Method GET ### Endpoint / ### Parameters #### Path Parameters None #### Query Parameters None ### Response #### Success Response (200 OK) - **Content-Type**: `text/html; charset=utf-8` - **Body**: Complete HTML page with embedded web form #### Headers - `Cache-Control: private, must-revalidate` (when served by Handler) - `ETag: ` (when served by Handler) ### Request Example ```bash curl -v http://localhost:8080/ ``` ``` -------------------------------- ### Get All File Descriptors In-Process Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/grpcui-main-api.md Retrieves all file descriptors known to the current server process from the in-process registry. This includes descriptors for all compiled proto files linked into the program. ```go files, err := grpcui.AllFilesViaInProcess() if err != nil { log.Fatal(err) } for _, fd := range files { fmt.Printf("File: %s\n", fd.GetName()) for _, md := range fd.GetMessageTypes() { fmt.Printf(" Message: %s\n", md.GetName()) } } ``` -------------------------------- ### Secure Configuration with Extra Metadata Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/configuration.md Apply security measures by adding authorization and tracking metadata to all requests, and preserve specific request headers. Includes an example of wrapping the handler with authentication middleware. ```go // Add authorization and tracking metadata to all requests handler := standalone.Handler(conn, "localhost:50051", methods, files, standalone.WithMetadata([]string{ "authorization: Bearer " + os.Getenv("GRPC_TOKEN"), "x-trace-id: " + generateTraceID(), "x-user-id: user123", }), standalone.PreserveHeaders([]string{ "x-request-id", "x-correlation-id", }), standalone.WithInvokeVerbosity(1), ) // Wrap with authentication middleware authenticatedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !isAuthenticated(r) { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } handler.ServeHTTP(w, r) }) http.ListenAndServe(":8080", authenticatedHandler) ``` -------------------------------- ### Assemble Modular grpcui Components Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/quickstart-reference.md For custom layouts, use the modular grpcui package functions to assemble the UI components. This involves getting methods and files, creating individual handlers, and then combining them with custom HTML. ```go // Get methods and files methods, _ := grpcui.AllMethodsViaReflection(ctx, cc) files, _ := grpcui.AllFilesViaReflection(ctx, cc) // Create handlers invokeHandler := grpcui.RPCInvokeHandler(cc, methods) metadataHandler := grpcui.RPCMetadataHandler(methods, files) webForm := grpcui.WebFormContents("/invoke", "/metadata", "localhost:50051", methods) webFormJS := grpcui.WebFormScript() webFormCSS := grpcui.WebFormSampleCSS() // Assemble custom HTML page and register handlers mux := http.NewServeMux() mux.Handle("/rpc/invoke/", http.StripPrefix("/rpc/invoke", invokeHandler)) mux.Handle("/rpc/metadata", metadataHandler) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // Render HTML with webForm, webFormJS, webFormCSS }) ``` -------------------------------- ### Example rpcError JSON Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/types.md An example of the JSON structure for an rpcError, illustrating a common error scenario. ```json { "code": 3, "name": "INVALID_ARGUMENT", "message": "invalid field: name must be non-empty", "details": [] } ``` -------------------------------- ### Example Field Definition JSON Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/types.md An example JSON representation of a field definition, illustrating its structure and properties. ```json { "name": "userName", "protoName": "user_name", "type": "string", "oneOfFields": [], "isMessage": false, "isEnum": false, "isArray": false, "isMap": false, "isRequired": false, "defaultVal": "", "description": "optional string user_name = 1;" } ``` -------------------------------- ### Example Enum Value Definition JSON Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/types.md An example JSON representation of an enum value definition, showing its numeric value and name. ```json { "num": 0, "name": "UNKNOWN" } ``` -------------------------------- ### GET /metadata Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/http-endpoints.md Retrieves schema metadata for a specified RPC method or all message types. It can be used to get details about request and response structures for gRPC services. ```APIDOC ## GET /metadata ### Description Retrieves schema metadata for a specified RPC method or all message types. ### Method GET ### Endpoint /metadata ### Parameters #### Query Parameters - **method** (string) - Required - Fully-qualified method name (e.g., `helloworld.Greeter/SayHello`) or `*` for all message types ### Response #### Success Response (200) - **requestType** (string) - Fully-qualified name of the request message type - **requestStream** (boolean) - Whether the RPC method accepts a stream of request messages - **messageTypes** (object) - Map of fully-qualified message type names to field definitions - **enumTypes** (object) - Map of fully-qualified enum type names to enum value definitions ### Response Example ```json { "requestType": "helloworld.HelloRequest", "requestStream": false, "messageTypes": { "helloworld.HelloRequest": [ { "name": "name", "protoName": "name", "type": "string", "oneOfFields": [], "isMessage": false, "isEnum": false, "isArray": false, "isMap": false, "isRequired": false, "defaultVal": "", "description": "optional string name = 1;" } ], "helloworld.HelloReply": [ { "name": "message", "protoName": "message", "type": "string", "oneOfFields": [], "isMessage": false, "isEnum": false, "isArray": false, "isMap": false, "isRequired": false, "defaultVal": "", "description": "optional string message = 1;" } ] }, "enumTypes": { "example.Status": [ { "num": 0, "name": "UNKNOWN" }, { "num": 1, "name": "ACTIVE" } ] } } ``` ### Example ```bash # Get metadata for a specific method curl 'http://localhost:8080/metadata?method=helloworld.Greeter/SayHello' # Get metadata for all message types (for google.protobuf.Any support) curl 'http://localhost:8080/metadata?method=*' ``` ``` -------------------------------- ### Mock gRPC Server for Testing Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md Sets up a mock gRPC server and a gRPC UI handler for testing purposes. It uses in-memory connections and mocks the server implementation. ```go package main import ( "context" "fmt" "net/http/httptest" "testing" pb "github.com/example/helloworld" "github.com/fullstorydev/grpcui" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) type mockGreeter struct { pb.UnimplementedGreeterServer } func (m *mockGreeter) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { return &pb.HelloReply{Message: "Hello " + req.Name}, nil } func TestUI(t *testing.T) { // Create test gRPC server server := grpc.NewServer() pb.RegisterGreeterServer(server, &mockGreeter{}) // Create test listener lis := bufconn.Listen(1024 * 1024) go server.Serve(lis) // Create client ctx := context.Background() conn, _ := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return lis.Dial() }), grpc.WithTransportCredentials(insecure.NewCredentials()), ) // Get methods methods, _ := grpcui.AllMethodsViaInProcess(server) files, _ := grpcui.AllFilesViaInProcess() // Create handler handler := standalone.Handler(conn, "test-server", methods, files) // Test it req := httptest.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Errorf("Expected 200, got %d", rr.Code) } server.GracefulStop() } ``` -------------------------------- ### Handler Options (GoF Strategy Pattern) Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/architecture.md Demonstrates the Strategy pattern implementation for handler options, where `HandlerOption` interface methods apply configurations to `handlerOptions`. ```go HandlerOption interface ├── apply(opts *handlerOptions) void Implementations: ├── WithIndexTemplate() → optFunc ├── WithCSS() → optFunc ├── AddJS() → optFunc ├── AddCSS() → optFunc ├── WithMetadata() → optFunc ├── WithExamples() → optFunc ├── EmitDefaults() → optFunc ├── WithClientDebug() → optFunc └── ... (15+ options) Handler() function └── for _, opt := range opts { opt.apply(&handlerOptions) } ``` -------------------------------- ### Load gRPC Methods and Files via Server Reflection Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/quickstart-reference.md This strategy is recommended for dynamic schema discovery without extra files. It requires the server to support reflection. ```go methods, _ := grpcui.AllMethodsViaReflection(ctx, cc) files, _ := grpcui.AllFilesViaReflection(ctx, cc) ``` -------------------------------- ### ServeAssetDirectory Handler Option Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/standalone-api.md Serves a directory of assets at /s//. The open function is called with the remaining relative path to retrieve files. The open function should handle file not found errors using os.IsNotExist() for 404 responses. ```go func ServeAssetDirectory(dirname string, open func(filename string) (io.ReadCloser, error)) HandlerOption ``` ```go handler := standalone.Handler(cc, target, methods, files, standalone.ServeAssetDirectory("static", func(filename string) (io.ReadCloser, error) { return os.Open(filepath.Join("/var/www/static", filename)) }), ) ``` -------------------------------- ### Get All Methods for Services Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/grpcui-main-api.md Extracts all method descriptors from a given slice of service descriptors. This function automatically handles deduplication of services. ```go // Assuming you have service descriptors services := []*desc.ServiceDescriptor{ /* ... */ } methods := grpcui.AllMethodsForServices(services) for _, method := range methods { fmt.Printf("Method: %s\n", method.GetFullyQualifiedName()) } ``` -------------------------------- ### Load gRPC Services via Proto Files using grpcurl Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/quickstart-reference.md This approach works with any server but requires proto files. It uses the grpcurl package to load descriptors from proto files. ```go // Using grpcurl package (not direct grpcui API) source, _ := grpcurl.DescriptorSourceFromProtoFiles( []string{"path/to/protos"}, // import paths "service.proto", // proto files ) methods, _ := grpcurl.ListServices(source) ``` -------------------------------- ### Display grpcui Help Information Source: https://github.com/fullstorydev/grpcui/blob/master/README.md Use the -help flag to display all available command-line options for the grpcui tool. This is useful for understanding the tool's configuration and capabilities. ```shell grpcui -help ``` -------------------------------- ### Graceful Degradation of gRPC UI Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/code-examples.md Demonstrates serving gRPC directly if gRPC UI creation fails. It attempts to create the UI via reflection and falls back to direct gRPC serving. ```go package main import ( "context" "log" "net/http" "github.com/fullstorydev/grpcui/standalone" "google.golang.org/grpc" ) func main() { ctx := context.Background() cc, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure()) if err != nil { // Fall back to direct gRPC if UI creation fails log.Printf("Warning: Failed to create gRPC UI: %v", err) log.Printf("Serving gRPC only on :50051") return } defer cc.Close() // Try with reflection first handler, err := standalone.HandlerViaReflection(ctx, cc, "localhost:50051") if err != nil { log.Printf("Warning: Reflection failed: %v", err) log.Printf("Cannot create UI without descriptors") return } log.Println("gRPC UI at http://localhost:8080") if err := http.ListenAndServe(":8080", handler); err != nil { log.Fatal(err) } } ``` -------------------------------- ### GET /grpc-web-form.css Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/http-endpoints.md Retrieves the CSS stylesheet used to style the gRPC-Web UI's web form. This endpoint provides the default styling for the UI elements. ```APIDOC ## GET /grpc-web-form.css ### Description Returns the CSS stylesheet for styling the web form. ### Method GET ### Endpoint /grpc-web-form.css ### Response #### Success Response (200 OK) - **Content-Type**: `text/css; charset=UTF-8` - **Body**: CSS stylesheet ### Headers - `Cache-Control`: `public, max-age=3600` (or private, depending on configuration) - `ETag`: `` ### Description Default CSS styling for the web form. Can be replaced or supplemented using `WithCSS`, `AddCSS`, or `AddCSSFile` options. ``` -------------------------------- ### Get Schema Metadata for Specific Method Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/http-endpoints.md Use this endpoint to retrieve schema metadata for a particular RPC method. Ensure the method name is correctly formatted. ```bash curl 'http://localhost:8080/metadata?method=helloworld.Greeter/SayHello' ``` -------------------------------- ### Generate Protoset File with protoc Source: https://github.com/fullstorydev/grpcui/blob/master/README.md Use this command to generate a protoset file from your proto source files. Ensure to include all necessary imports. ```shell protoc --proto_path=. \ --descriptor_set_out=myservice.protoset \ --include_imports \ my/custom/server/service.proto ``` -------------------------------- ### gRPC UI with Custom Routing Source: https://github.com/fullstorydev/grpcui/blob/master/_autodocs/quickstart-reference.md Configure custom routing for your gRPC UI. This example sets up a health check endpoint and routes API requests to the gRPC UI handler. ```go handler, _ := standalone.HandlerViaReflection(ctx, cc, target) mux := http.NewServeMux() mux.Handle("/api/", http.StripPrefix("/api", handler)) mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) http.ListenAndServe(":8080", mux) ```