gateway

package
v2.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: Apache-2.0 Imports: 49 Imported by: 0

README

Gateway

Gateway 是一个 gRPC Gateway 实现,提供 HTTP/JSON 到 gRPC 的协议转换功能。它支持服务注册、中间件、HTTP Rule 解析等特性,让开发者可以轻松地将 gRPC 服务暴露为 RESTful API。

核心特性

  • 分层架构:前端协议层(Frontend)/ 统一调度层(Dispatcher)/ 后端 gRPC 层(Backend)三层解耦,底层 gRPC handler 注册一次,多种协议前端复用
  • 统一调度Dispatcher 统一处理 Unary / Server-Stream / Client-Stream / Bidi 四种流模式
  • 多协议前端:HTTP/REST、gRPC-Web、WebSocket、Native gRPC 共享同一套后端 handler
  • HTTP Rule 解析:支持 google.api.http 注解,自动解析 RESTful 路径模板
  • 协议转换:自动处理 HTTP/JSON 与 gRPC/Protobuf 之间的双向转换
  • gRPC Web 支持:允许浏览器直接调用 gRPC 服务
  • 服务注册:支持本地服务和代理服务的注册
  • 中间件支持:提供 Unary 和 Stream 拦截器
  • 自定义编解码:支持 JSON、Protobuf 等多种编码格式
  • 错误映射:自动将 gRPC 错误码映射为 HTTP 状态码

分层架构概览

[ 前端协议层 Frontend ]      [ 核心调度层 Dispatcher ]      [ 后端 gRPC 层 Backend ]
  HTTP/REST                                                   inprocgrpc.Channel
  gRPC-Web          ──►   归一化为 grpc.ServerStream    ──►   (本地 handler)
  WebSocket                统一泵:unary/server/             remoteProxyCli
  Native gRPC              client/bidi 四种流模式             (远程代理)

对外监听由 servers/gatewayserver 装配。NATS/zrpc 见 pkg/zrpcbridge

设计灵感来自 connectrpc/vanguard-go:所有前端协议最终归一化为 gRPC 语义的 ServerStream,由统一的 Dispatcher 对接后端,从而让「底层注册一次的 gRPC handler」服务于多种上层协议。详见 架构设计

快速开始

1. 定义 Proto 文件
syntax = "proto3";

package example.v1;

import "google/api/annotations.proto";

service UserService {
  rpc GetUser(GetUserRequest) returns (User) {
    option (google.api.http) = {
      get: "/v1/users/{user_id}"
    };
  }
  
  rpc CreateUser(CreateUserRequest) returns (User) {
    option (google.api.http) = {
      post: "/v1/users"
      body: "*"
    };
  }
}
2. 实现并注册服务
package main

import (
    "github.com/gofiber/fiber/v3"
    "github.com/pubgo/lava/v2/pkg/gateway"
    pb "your/proto/package"
)

func main() {
    // 创建 Gateway
    mux := gateway.NewMux()

    // 注册服务
    mux.RegisterService(&pb.UserService_ServiceDesc, &userServiceImpl{})

    // 创建 Fiber 应用
    app := fiber.New()
    app.All("/v1/*", mux.Handler)

    app.Listen(":8080")
}
3. 调用服务
# GET 请求
curl http://localhost:8080/v1/users/123

# POST 请求
curl -X POST http://localhost:8080/v1/users \
  -H "Content-Type: application/json" \
  -d '{"name": "John", "email": "john@example.com"}'

文档

文档 说明
使用指南 服务注册、路由配置、中间件、错误处理等
gRPC Web 浏览器端 gRPC Web 集成
WebSocket 基于 coder/websocket 的 WebSocket 前端
Native gRPC 原生 gRPC 透传,RegisterService 一次多协议复用
NATS/zrpc 桥接 可选:NATS 订阅桥接到 Mux(非 gateway 前端)
架构设计 分层架构、核心组件、调度流程
实现细节 路径解析、调度器、元数据转换、流式处理
部署/TLS 边缘 TLS 终止与 Traefik 多协议路由

支持的协议

协议 Content-Type / 入口 说明
HTTP/JSON application/json RESTful API
HTTP/JSON (别名) application/grpc-web-json 前端命名兼容(按 JSON 处理)
gRPC Web application/grpc-web+proto 浏览器 gRPC (二进制)
gRPC Web Text application/grpc-web-text+proto 浏览器 gRPC (Base64)
WebSocket Mux.WebSocketHandler() net/http 监听,支持双向流
Native gRPC Mux.GRPCServerOptions() 标准 grpc.Server 透传

NATS/zrpc 不属于 gateway 前端,见 pkg/zrpcbridge

说明:HTTP/REST 与 gRPC-Web 前端运行在 Fiber/fasthttp 栈上(Mux.Handler);WebSocket 前端基于 coder/websocket,必须运行在标准 net/http 栈上(Mux.WebSocketHandler()),详见 WebSocket 文档

路径匹配

模式 示例 说明
{field} /users/{id} 路径变量
* /files/* 单段通配符
** /files/** 多段通配符
:verb /users/{id}:get 动词后缀

错误码映射

gRPC Code HTTP Status
OK 200
InvalidArgument 400
Unauthenticated 401
PermissionDenied 403
NotFound 404
Internal 500

完整映射表见 实现细节

示例

  • gRPC Web 示例 - HTTP/gRPC-Web 前后端示例
  • 多协议示例 - 同一套 handler 同时暴露 HTTP/gRPC-Web(:8080)、WebSocket(:8081)、原生 gRPC(:50051)
    • internal/examples/grpcwebsocket/verify/ 提供自动化验证(先启动 main,再运行 verify)

部署与 TLS

Gateway 不内置 HTTPS/TLS,全程明文(http / h2c),TLS 在边缘代理(如 Traefik)终止。 三类协议需分别路由,其中原生 gRPC 回源必须用 h2c

协议 默认端口 回源 scheme
HTTP/REST + gRPC-Web http_port(8080) http
WebSocket websocket_port(8081) http
原生 gRPC grpc_port(50051) h2c

开箱即用的 Traefik 配置见 deploy/traefik/,说明见 部署/TLS 文档

参考

Documentation

Index

Constants

View Source
const MetadataHeaderPrefix = "Grpc-Metadata-"

MetadataHeaderPrefix is the http prefix that represents custom metadata parameters to or from a gRPC call.

View Source
const MetadataPrefix = "grpcgateway-"

MetadataPrefix is prepended to permanent HTTP header keys (as specified by the IANA) when added to the gRPC context.

View Source
const MetadataTrailerPrefix = "Grpc-Trailer-"

MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to HTTP headers in a response handled by grpc-gateway

Variables

View Source
var DefaultContextTimeout = 0 * time.Second

DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound header isn't present. If the value is 0 the sent `context` will not have a timeout.

Functions

func FieldMaskFromRequestBody

func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*fieldmask.FieldMask, error)

FieldMaskFromRequestBody creates a FieldMask printing all complete paths from the JSON body.

func HTTPPathPattern

func HTTPPathPattern(ctx context.Context) (string, bool)

HTTPPathPattern returns the HTTP path pattern string relating to the HTTP handler, if one exists. The format of the returned string is defined by the google.api.http path template type.

func HTTPStatusFromCode

func HTTPStatusFromCode(code codes.Code) int

HTTPStatusFromCode converts a gRPC error code into the corresponding HTTP response status. See: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto

func NewContextWithServerTransportStream

func NewContextWithServerTransportStream(ctx context.Context, s grpc.ServerStream, method string) context.Context

func NewServerMetadataContext

func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context

NewServerMetadataContext creates a new context with ServerMetadata

func RPCMethod

func RPCMethod(ctx context.Context) (string, bool)

RPCMethod returns the method string for the server context. The returned string is in the format of "/package.service/method".

func TransparentHandler

func TransparentHandler(cli grpc.ClientConnInterface, inType, outType protoreflect.MessageType, opts ...grpc.CallOption) grpc.StreamHandler

Types

type AnnotateContextOption

type AnnotateContextOption func(ctx context.Context) context.Context

func WithHTTPPathPattern

func WithHTTPPathPattern(pattern string) AnnotateContextOption

type Backend added in v2.2.0

type Backend = grpc.ClientConnInterface

Backend is the unified gRPC dispatch target. Mux implements this via in-process handlers and optional remote proxy clients.

type Codec

type Codec interface {
	encoding.Codec
	// MarshalAppend appends the marshaled form of v to b and returns the result.
	MarshalAppend([]byte, any) ([]byte, error)
}

Codec defines the interface used to encode and decode messages.

type CodecJSON

CodecJSON is a Codec implementation with protobuf json format.

func (CodecJSON) Marshal

func (c CodecJSON) Marshal(v any) ([]byte, error)

func (CodecJSON) MarshalAppend

func (c CodecJSON) MarshalAppend(b []byte, v any) ([]byte, error)

func (CodecJSON) Name

func (CodecJSON) Name() string

func (CodecJSON) ReadNext

func (c CodecJSON) ReadNext(b []byte, r io.Reader, limit int) ([]byte, int, error)

ReadNext reads the length of the message around the json object. It reads until it finds a matching number of braces. It does not validate the JSON.

func (CodecJSON) Unmarshal

func (c CodecJSON) Unmarshal(data []byte, v any) error

func (CodecJSON) WriteNext

func (c CodecJSON) WriteNext(w io.Writer, b []byte) (int, error)

WriteNext writes the raw JSON message to w without any size prefix.

type CodecProto

type CodecProto struct {
	proto.MarshalOptions
}

CodecProto is a Codec implementation with protobuf binary format.

func (CodecProto) Marshal

func (c CodecProto) Marshal(v any) ([]byte, error)

func (CodecProto) MarshalAppend

func (c CodecProto) MarshalAppend(b []byte, v any) ([]byte, error)

func (CodecProto) Name

func (CodecProto) Name() string

Name == "proto" overwritting internal proto codec

func (CodecProto) ReadNext

func (c CodecProto) ReadNext(b []byte, r io.Reader, limit int) ([]byte, int, error)

ReadNext reads a varint size-delimited wire-format message from r.

func (CodecProto) Unmarshal

func (CodecProto) Unmarshal(data []byte, v any) error

func (CodecProto) WriteNext

func (c CodecProto) WriteNext(w io.Writer, b []byte) (int, error)

WriteNext writes the length of the message encoded as 4 byte unsigned integer and then writes the message to w.

type Compressor

type Compressor interface {
	encoding.Compressor
}

Compressor is used to compress and decompress messages. Based on grpc/encoding.

type Dispatcher added in v2.2.0

type Dispatcher struct{}

Dispatcher routes frontend streams to a Backend, handling unary, server-streaming, client-streaming, and bidi modes.

func NewDispatcher added in v2.2.0

func NewDispatcher() *Dispatcher

func (*Dispatcher) Dispatch added in v2.2.0

func (d *Dispatcher) Dispatch(
	ctx context.Context,
	backend Backend,
	frontend FrontendStream,
	op *Operation,
	in any,
) (header, trailer metadata.MD, err error)

Dispatch connects a frontend stream to the backend for the given operation. For unary and server-streaming RPCs, in must already be populated by the frontend (RecvMsg on the request message).

func (*Dispatcher) DispatchFrontend added in v2.2.0

func (d *Dispatcher) DispatchFrontend(
	ctx context.Context,
	backend Backend,
	frontend FrontendStream,
	op *Operation,
) (header, trailer metadata.MD, err error)

DispatchFrontend drives a frontend grpc.ServerStream end-to-end. For unary and server-streaming RPCs it pre-reads the request message via RecvMsg before dispatching; client-streaming and bidi read inside the pump. This is the shared entrypoint for frontends whose request surface is already a grpc.ServerStream (native gRPC passthrough, websocket, zrpc).

type FrontendStream added in v2.2.0

type FrontendStream = grpc.ServerStream

FrontendStream is the protocol-neutral request/response surface exposed by each gateway frontend (HTTP, gRPC-Web, WebSocket, native gRPC).

type Gateway

type Gateway interface {
	grpc.ClientConnInterface
	SetUnaryInterceptor(interceptor grpc.UnaryServerInterceptor)
	SetStreamInterceptor(interceptor grpc.StreamServerInterceptor)

	SetRequestDecoder(protoreflect.FullName, func(ctx fiber.Ctx, msg proto.Message) error)
	SetResponseEncoder(protoreflect.FullName, func(ctx fiber.Ctx, msg proto.Message) error)
	RegisterService(sd *grpc.ServiceDesc, ss any)

	GetOperation(operation string) *GrpcMethod
	Handler(fiber.Ctx) error
	ServeHTTP(http.ResponseWriter, *http.Request)
	GetRouteMethods() []RouteOperation
}

type GrpcMethod

type GrpcMethod struct {
	Srv     any
	SrvDesc *grpc.ServiceDesc

	GrpcMethodDesc *grpc.MethodDesc
	GrpcStreamDesc *grpc.StreamDesc
	MethodDesc     protoreflect.MethodDescriptor

	GrpcFullMethod string
	Meta           *lavapbv1.RpcMeta
}

type MatchOperation

type MatchOperation = routertree.MatchOperation

func GetRouterTarget

func GetRouterTarget(mux *Mux, kind, path string) (*MatchOperation, error)

type MethodHandler

type MethodHandler = func(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error)

type MethodRoute added in v2.2.0

type MethodRoute struct {
	FullMethod string
	Operation  *Operation
}

MethodRoute describes a registered gRPC method for external protocol bridges.

type Mux

type Mux struct {
	// contains filtered or unexported fields
}

func NewMux

func NewMux(opts ...MuxOption) *Mux

func (*Mux) Dispatch added in v2.2.0

func (m *Mux) Dispatch(ctx context.Context, frontend FrontendStream, op *Operation, in any) (metadata.MD, metadata.MD, error)

Dispatch routes a frontend stream to the Mux backend.

func (*Mux) DispatchFrontend added in v2.2.0

func (m *Mux) DispatchFrontend(ctx context.Context, frontend FrontendStream, op *Operation) (metadata.MD, metadata.MD, error)

DispatchFrontend drives a frontend stream end-to-end through the dispatcher.

func (*Mux) Err added in v2.2.0

func (m *Mux) Err() error

Err returns the first service registration error, if any.

func (*Mux) GRPCPassthroughStreamHandler added in v2.2.0

func (m *Mux) GRPCPassthroughStreamHandler() grpc.StreamHandler

GRPCPassthroughStreamHandler returns a stream handler suitable for grpc.UnknownServiceHandler. Native gRPC clients connect to a *grpc.Server configured with this handler; each RPC is forwarded to the Mux backend (inprocgrpc local handlers or remote proxies) through the unified Dispatcher, so unary, server-stream, client-stream, and bidi all behave correctly.

Register services only on the Mux (RegisterService / RegisterProxy); do not register the same implementations again on the outer grpc.Server.

func (*Mux) GRPCServerOptions added in v2.2.0

func (m *Mux) GRPCServerOptions(extra ...grpc.ServerOption) []grpc.ServerOption

GRPCServerOptions returns server options that enable native gRPC passthrough through this Mux. Append to grpc.NewServer or grpcbuilder.Config.Build opts.

func (*Mux) GetOperation

func (m *Mux) GetOperation(operation string) *GrpcMethod

func (*Mux) GetOperationByName

func (m *Mux) GetOperationByName(name string) *GrpcMethod

func (*Mux) GetRouteMethods

func (m *Mux) GetRouteMethods() []RouteOperation

func (*Mux) Handler

func (m *Mux) Handler(ctx fiber.Ctx) error

func (*Mux) Invoke

func (m *Mux) Invoke(ctx context.Context, method string, args, reply any, opts ...grpc.CallOption) error

func (*Mux) MatchOperation

func (m *Mux) MatchOperation(method, path string) (r result.Result[*MatchOperation])

func (*Mux) NewStream

func (m *Mux) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error)

func (*Mux) RegisterProxy

func (m *Mux) RegisterProxy(sd *grpc.ServiceDesc, proxy lava.GrpcRouter, cli grpc.ClientConnInterface)

func (*Mux) RegisterService

func (m *Mux) RegisterService(sd *grpc.ServiceDesc, ss any)

RegisterService satisfies grpc.ServiceRegistrar for generated service code hooks.

func (*Mux) Routes added in v2.2.0

func (m *Mux) Routes() []MethodRoute

Routes returns registered gRPC full methods for external bridges (e.g. zrpc).

func (*Mux) ServeHTTP

func (m *Mux) ServeHTTP(writer http.ResponseWriter, request *http.Request)

func (*Mux) SetRequestDecoder

func (m *Mux) SetRequestDecoder(name protoreflect.FullName, f func(ctx fiber.Ctx, msg proto.Message) error)

func (*Mux) SetResponseEncoder

func (m *Mux) SetResponseEncoder(name protoreflect.FullName, f func(ctx fiber.Ctx, msg proto.Message) error)

func (*Mux) SetStreamInterceptor

func (m *Mux) SetStreamInterceptor(interceptor grpc.StreamServerInterceptor)

SetStreamInterceptor configures the in-process channel to use the given server interceptor for streaming RPCs when dispatching.

func (*Mux) SetUnaryInterceptor

func (m *Mux) SetUnaryInterceptor(interceptor grpc.UnaryServerInterceptor)

func (*Mux) WebSocketHandler added in v2.2.0

func (m *Mux) WebSocketHandler(opts ...WSOption) http.Handler

WebSocketHandler returns an http.Handler that bridges websocket clients to the registered gRPC handlers. It uses coder/websocket, so it must be served by a standard net/http server (it cannot run on the fasthttp/fiber stack).

The request path is interpreted as the gRPC full method name, e.g. "/pkg.v1.Service/Method". The wire format defaults to protojson (text frames) and can be switched to protobuf (binary frames) via the "?encoding=proto" query parameter or the "grpc-ws-proto" subprotocol.

type MuxOption

type MuxOption func(*muxOptions)

MuxOption is an option for a mux.

type Operation added in v2.2.0

type Operation struct {
	FullMethod string
	InputType  protoreflect.MessageType
	OutputType protoreflect.MessageType
	StreamDesc *grpc.StreamDesc // nil for unary RPCs
	Meta       *lavapbv1.RpcMeta
}

Operation describes a registered RPC method and its schema.

type PathFieldVar

type PathFieldVar = routertree.PathFieldVar

type RouteOperation

type RouteOperation = routertree.RouteOperation

type ServerMetadata

type ServerMetadata struct {
	HeaderMD  metadata.MD
	TrailerMD metadata.MD
}

ServerMetadata consists of metadata sent from gRPC server.

func ServerMetadataFromContext

func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool)

ServerMetadataFromContext returns the ServerMetadata in ctx

type ServerTransportStream

type ServerTransportStream struct {
	// contains filtered or unexported fields
}

ServerTransportStream implements grpc.ServerTransportStream. It should only be used by the generated files to support grpc.SendHeader outside of gRPC server use.

func (*ServerTransportStream) Header

func (s *ServerTransportStream) Header() metadata.MD

Header returns the header metadata of the stream.

func (*ServerTransportStream) Method

func (s *ServerTransportStream) Method() string

Method returns the method for the stream.

func (*ServerTransportStream) SendHeader

func (s *ServerTransportStream) SendHeader(md metadata.MD) error

SendHeader sets the header metadata.

func (*ServerTransportStream) SetHeader

func (s *ServerTransportStream) SetHeader(md metadata.MD) error

SetHeader sets the header metadata.

func (*ServerTransportStream) SetTrailer

func (s *ServerTransportStream) SetTrailer(md metadata.MD) error

SetTrailer sets the trailer metadata.

func (*ServerTransportStream) Trailer

func (s *ServerTransportStream) Trailer() metadata.MD

Trailer returns the cached trailer metadata.

type StreamDirector

type StreamDirector func(ctx context.Context, fullMethodName string) (context.Context, grpc.ClientConnInterface, error)

type StreamHandler

type StreamHandler = grpc.StreamHandler

type WSConfig added in v2.2.0

type WSConfig struct {
	// OriginPatterns are passed to coder/websocket AcceptOptions.OriginPatterns.
	// When empty and InsecureSkipVerify is false, only same-origin connections are allowed.
	OriginPatterns []string
	// InsecureSkipVerify disables origin verification. Use only in development.
	InsecureSkipVerify bool
	// Subprotocols advertised during the handshake. Defaults to grpc-ws-json and grpc-ws-proto.
	Subprotocols []string
}

WSConfig holds websocket frontend settings for production wiring.

type WSOption added in v2.2.0

type WSOption func(*wsOptions)

WSOption configures the websocket frontend.

func WSOptionsFromConfig added in v2.2.0

func WSOptionsFromConfig(cfg WSConfig) []WSOption

WSOptionsFromConfig builds WSOption values from WSConfig.

func WithWSInsecureSkipVerify added in v2.2.0

func WithWSInsecureSkipVerify() WSOption

WithWSInsecureSkipVerify disables websocket origin verification.

func WithWSOriginPatterns added in v2.2.0

func WithWSOriginPatterns(patterns ...string) WSOption

WithWSOriginPatterns sets allowed origin patterns for the websocket handshake.

func WithWSSubprotocols added in v2.2.0

func WithWSSubprotocols(subprotocols ...string) WSOption

WithWSSubprotocols sets the advertised websocket subprotocols.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL