Documentation
¶
Overview ¶
Package jrpc provides a JSON-RPC over HTTP and WebSocket implementation with Protocol Buffer support. It enables automatic method dispatch, streaming capabilities, and context enrichment for service implementations.
This package requires server definitions to be generated from Protocol Buffer service definitions using the protoc-gen-jrpc plugin: https://github.com/valentin-kaiser/protoc-gen-jrpc
The plugin generates the correct struct implementations that satisfy the Server interface, ensuring proper integration with the jRPC service framework.
Features:
- HTTP and WebSocket endpoint support
- Automatic method resolution and dispatch with cached lookups
- Protocol Buffer JSON marshaling/unmarshaling
- Multiple streaming patterns (unary, server, client, bidirectional)
- Context enrichment with HTTP and WebSocket components
- Comprehensive error handling and connection management
Usage:
- Define your service in a .proto file
- Generate Go code using protoc with the protoc-gen-jrpc plugin
- Implement the generated Server interface
- Create a new jRPC service with jrpc.Register(yourServer)
- Register the HandlerFunc with the web package function WithJRPC
Example:
```go
package main
import (
"context"
"log"
"net/http"
"github.com/valentin-kaiser/go-core/web"
"github.com/valentin-kaiser/go-core/web/jrpc"
)
type MyService struct {
jrpc.UnimplementedMyServiceServer
}
func (s *MyService) MyMethod(ctx context.Context, req *MyRequest) (*MyResponse, error) {
// Implement your method logic here
return &MyResponse{}, nil
}
func main() {
err := web.Instance().
WithHost("localhost").
WithPort(8080).
WithJRPC(jrpc.Register(&MyService{})).
Start().Error
if err != nil {
log.Fatal().Err(err).Msg("server exited")
}
}
```
Index ¶
- func BidirectionalStream[TReq proto.Message, TResp proto.Message](c *Client, ctx context.Context, u *url.URL, in chan TReq, out chan TResp, ...) error
- func ClientStream[T proto.Message](c *Client, ctx context.Context, u *url.URL, in chan T, resp proto.Message) error
- func GetRequest(ctx context.Context) (*http.Request, bool)
- func GetResponseWriter(ctx context.Context) (http.ResponseWriter, bool)
- func GetWebSocketConn(ctx context.Context) (*websocket.Conn, bool)
- func ServerStream[T proto.Message](c *Client, ctx context.Context, u *url.URL, req proto.Message, out chan T, ...) error
- func SetUpgrader(u websocket.Upgrader)
- func WithHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) context.Context
- func WithWebSocketContext(ctx context.Context, w http.ResponseWriter, r *http.Request, ...) context.Context
- type Client
- type ClientOption
- type ContextKey
- type Server
- type Service
- type StreamingType
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BidirectionalStream ¶ added in v1.8.2
func BidirectionalStream[TReq proto.Message, TResp proto.Message](c *Client, ctx context.Context, u *url.URL, in chan TReq, out chan TResp, respFactory func() TResp) error
BidirectionalStream makes a bidirectional streaming RPC call with typed channels where both client and server send streams of messages over WebSocket.
Parameters:
- c: The client instance
- ctx: Context for the request (for cancellation)
- u: The full URL for the request
- in: Typed channel to send request messages (should be closed by caller when done)
- out: Typed channel to receive response messages (will be closed when stream ends)
- respFactory: Factory function to create new response message instances
Returns an error if the connection fails or an error occurs during streaming.
func ClientStream ¶ added in v1.8.2
func ClientStream[T proto.Message](c *Client, ctx context.Context, u *url.URL, in chan T, resp proto.Message) error
ClientStream makes a client streaming RPC call with typed channels where the client sends a stream of requests and receives one response over WebSocket.
Parameters:
- c: The client instance
- ctx: Context for the request (for cancellation)
- u: The full URL for the request
- in: Typed channel to send request messages (should be closed by caller when done)
- resp: The response message (will be populated when stream completes)
Returns an error if the connection fails or an error occurs during streaming.
func GetRequest ¶
GetRequest extracts the HTTP Request from the context. This provides access to request metadata such as headers, URL parameters, authentication information, and other request-specific data for logging, authorization, and business logic purposes.
Parameters:
- ctx: The context containing the HTTP Request
Returns:
- *http.Request: The HTTP request if found
- bool: True if the Request was found in the context
func GetResponseWriter ¶
func GetResponseWriter(ctx context.Context) (http.ResponseWriter, bool)
GetResponseWriter extracts the HTTP ResponseWriter from the context. This allows service methods to access the original response writer for setting custom headers, status codes, or other HTTP-specific operations.
Parameters:
- ctx: The context containing the ResponseWriter
Returns:
- http.ResponseWriter: The response writer if found
- bool: True if the ResponseWriter was found in the context
func GetWebSocketConn ¶
GetWebSocketConn extracts the WebSocket connection from the context. This enables streaming service methods to access connection properties, configure timeouts, handle connection-specific operations, and manage the WebSocket lifecycle.
Parameters:
- ctx: The context containing the WebSocket connection
Returns:
- *websocket.Conn: The WebSocket connection if found
- bool: True if the connection was found in the context
func ServerStream ¶ added in v1.8.2
func ServerStream[T proto.Message](c *Client, ctx context.Context, u *url.URL, req proto.Message, out chan T, factory func() T) error
ServerStream makes a server streaming RPC call with typed channels where the client sends one request and receives a stream of responses over WebSocket.
Parameters:
- c: The client instance
- ctx: Context for the request (for cancellation)
- u: The full URL for the request
- req: The request message
- out: Typed channel to receive response messages (will be closed when stream ends)
- factory: Factory function to create new response message instances
Returns an error if the connection fails or an error occurs during streaming.
func SetUpgrader ¶
SetUpgrader allows setting a custom WebSocket upgrader with specific options.
func WithHTTPContext ¶
WithHTTPContext enriches the provided context with HTTP request components. It adds the ResponseWriter and Request to the context, making them available throughout the request processing pipeline for logging, middleware, and other cross-cutting concerns.
Parameters:
- ctx: The base context to enrich
- w: The HTTP ResponseWriter for the current request
- r: The HTTP Request being processed
Returns the enriched context containing the HTTP components.
func WithWebSocketContext ¶
func WithWebSocketContext(ctx context.Context, w http.ResponseWriter, r *http.Request, conn *websocket.Conn) context.Context
WithWebSocketContext adds a WebSocket connection to the context. This enables WebSocket-specific operations and connection management from within streaming service methods.
Parameters:
- ctx: The base context to enrich
- conn: The WebSocket connection for the current session
Returns the enriched context containing the WebSocket connection.
Types ¶
type Client ¶ added in v1.8.1
type Client struct {
// contains filtered or unexported fields
}
Client provides a client implementation for making JSON-RPC calls over HTTP and WebSocket. It handles request serialization, HTTP/WebSocket communication, and response deserialization using Protocol Buffer JSON format.
The client supports:
- Unary RPC calls (HTTP POST)
- Server streaming RPC calls (WebSocket)
- Client streaming RPC calls (WebSocket)
- Bidirectional streaming RPC calls (WebSocket)
- Automatic request/response marshaling
- Custom HTTP client configuration
- Request timeout management
- Custom TLS configuration for secure WebSocket connections
Example unary call:
client := jrpc.NewClient()
req := &MyRequest{Field: "value"}
resp := &MyResponse{}
err := client.Call(ctx, url.URL{Scheme: "http", Host: "localhost:8080", Path: "/MyService/MyMethod"}, req, resp, nil)
Example server streaming call:
out := make(chan proto.Message, 10)
factory := func() proto.Message { return &MyResponse{} }
go client.ServerStream(ctx, url.URL{Scheme: "http", Host: "localhost:8080", Path: "/MyService/MyMethod"}, req, factory, out)
for msg := range out {
// Process each response message
}
func NewClient ¶ added in v1.8.1
func NewClient(opts ...ClientOption) *Client
NewClient creates a new JSON-RPC client with default settings. Optional ClientOptions can be provided to customize the client's behavior.
func (*Client) Call ¶ added in v1.8.1
func (c *Client) Call(ctx context.Context, u *url.URL, req, resp proto.Message, header http.Header) error
Call makes a unary RPC call to the specified service and method. It marshals the request message to Protocol Buffer JSON format, sends it via HTTP POST, and unmarshals the response.
URL format: {baseURL}/{service}/{method} Content-Type: application/json (Protocol Buffer JSON format)
Parameters:
- ctx: Context for the request (for cancellation and timeouts)
- u: The full URL for the request
- req: The request message (must be a proto.Message)
- resp: The response message (must be a proto.Message pointer)
- headers: Optional HTTP headers to include in the request
Returns an error if the request fails, marshaling/unmarshaling fails, or the server returns an error response.
type ClientOption ¶ added in v1.8.1
type ClientOption func(*Client)
ClientOption defines a function type for configuring the Client.
func WithClient ¶ added in v1.8.1
func WithClient(client *http.Client) ClientOption
WithClient sets a custom HTTP client.
func WithTLSConfig ¶ added in v1.8.1
func WithTLSConfig(config *tls.Config) ClientOption
WithTLSConfig sets a custom TLS configuration for WebSocket connections. This is useful for connecting to servers with self-signed certificates or specific TLS requirements.
Example for skipping certificate verification (use with caution):
tlsConfig := &tls.Config{InsecureSkipVerify: true}
client := jrpc.NewClient("https://localhost:8080", jrpc.WithTLSConfig(tlsConfig))
func WithUserAgent ¶ added in v1.8.1
func WithUserAgent(agent string) ClientOption
WithUserAgent sets a custom User-Agent header for HTTP and WebSocket requests.
type ContextKey ¶
type ContextKey string
ContextKey represents keys for context values
const ( // ContextKeyResponseWriter key for http.ResponseWriter ContextKeyResponseWriter ContextKey = "response" // ContextKeyRequest key for *http.Request ContextKeyRequest ContextKey = "request" // ContextKeyWebSocketConn key for *websocket.Conn ContextKeyWebSocketConn ContextKey = "websocket" )
type Server ¶
type Server interface {
// Descriptor returns the protocol buffer file descriptor for the service.
Descriptor() protoreflect.FileDescriptor
}
Server represents a jRPC service implementation.
type Service ¶
type Service struct {
Server
// contains filtered or unexported fields
}
Service implements the RTLS-Suite API server with support for both HTTP and WebSocket endpoints. It provides automatic method dispatch, protocol buffer message handling, and context enrichment.
func Register ¶ added in v1.5.2
Register creates a new jrpc service instance and registers the provided service implementation. The service implementation has to implement the Descriptor method. This function builds a method cache for improved lookup performance.
func (*Service) HandlerFunc ¶
func (s *Service) HandlerFunc(w http.ResponseWriter, r *http.Request)
HandlerFunc processes both HTTP and WebSocket requests to API endpoints. It automatically detects whether the request is a WebSocket upgrade request and routes to the appropriate handler (unary or websocket).
URL format: /{service}/{method} Content-Type: application/json (Protocol Buffer JSON format)
For WebSocket requests, the Connection header must contain "Upgrade" and the Upgrade header must contain "websocket".
Parameters:
- w: HTTP ResponseWriter for sending the response
- r: HTTP Request containing the API call
type StreamingType ¶
type StreamingType int
StreamingType represents the type of streaming for a method
const ( // StreamingTypeUnary represents a unary (non-streaming) method StreamingTypeUnary StreamingType = iota // StreamingTypeBidirectional represents a bidirectional streaming method StreamingTypeBidirectional // StreamingTypeServerStream represents a server streaming method StreamingTypeServerStream // StreamingTypeClientStream represents a client streaming method StreamingTypeClientStream // StreamingTypeInvalid represents an invalid method signature StreamingTypeInvalid )