### 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
`))
})
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)
```