snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
test / Lint (push) Failing after 3s
test / Test with Go 1.26.8 (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:17:21 +05:00
commit b352a9a30d
472 changed files with 108375 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
package proxyproto
import "github.com/centrifugal/centrifuge"
func DisconnectFromProto(s *Disconnect) *centrifuge.Disconnect {
return &centrifuge.Disconnect{
Code: s.Code,
Reason: s.Reason,
}
}
func ErrorFromProto(s *Error) *centrifuge.Error {
return &centrifuge.Error{
Code: s.Code,
Message: s.Message,
Temporary: s.Temporary,
}
}

View File

@@ -0,0 +1,110 @@
package proxyproto
import "encoding/json"
type ResponseDecoder interface {
DecodeConnectResponse(data []byte) (*ConnectResponse, error)
DecodeRefreshResponse(data []byte) (*RefreshResponse, error)
DecodeRPCResponse(data []byte) (*RPCResponse, error)
DecodeSubscribeResponse(data []byte) (*SubscribeResponse, error)
DecodePublishResponse(data []byte) (*PublishResponse, error)
DecodeSubRefreshResponse(data []byte) (*SubRefreshResponse, error)
DecodeNotifyCacheEmptyResponse(data []byte) (*NotifyCacheEmptyResponse, error)
DecodeMapPublishResponse(data []byte) (*MapPublishResponse, error)
DecodeMapRemoveResponse(data []byte) (*MapRemoveResponse, error)
DecodeSharedPollRefreshResponse(data []byte) (*SharedPollRefreshResponse, error)
}
var _ ResponseDecoder = (*JSONDecoder)(nil)
type JSONDecoder struct{}
func (e *JSONDecoder) DecodeConnectResponse(data []byte) (*ConnectResponse, error) {
var resp ConnectResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeRefreshResponse(data []byte) (*RefreshResponse, error) {
var resp RefreshResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeRPCResponse(data []byte) (*RPCResponse, error) {
var resp RPCResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeSubscribeResponse(data []byte) (*SubscribeResponse, error) {
var resp SubscribeResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodePublishResponse(data []byte) (*PublishResponse, error) {
var resp PublishResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeSubRefreshResponse(data []byte) (*SubRefreshResponse, error) {
var resp SubRefreshResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeNotifyCacheEmptyResponse(data []byte) (*NotifyCacheEmptyResponse, error) {
var resp NotifyCacheEmptyResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeMapPublishResponse(data []byte) (*MapPublishResponse, error) {
var resp MapPublishResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeMapRemoveResponse(data []byte) (*MapRemoveResponse, error) {
var resp MapRemoveResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (e *JSONDecoder) DecodeSharedPollRefreshResponse(data []byte) (*SharedPollRefreshResponse, error) {
var resp SharedPollRefreshResponse
err := json.Unmarshal(data, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}

View File

@@ -0,0 +1,60 @@
package proxyproto
import "encoding/json"
type RequestEncoder interface {
EncodeConnectRequest(req *ConnectRequest) ([]byte, error)
EncodeRefreshRequest(req *RefreshRequest) ([]byte, error)
EncodeRPCRequest(req *RPCRequest) ([]byte, error)
EncodeSubscribeRequest(req *SubscribeRequest) ([]byte, error)
EncodePublishRequest(req *PublishRequest) ([]byte, error)
EncodeSubRefreshRequest(req *SubRefreshRequest) ([]byte, error)
EncodeNotifyCacheEmptyRequest(req *NotifyCacheEmptyRequest) ([]byte, error)
EncodeMapPublishRequest(req *MapPublishRequest) ([]byte, error)
EncodeMapRemoveRequest(req *MapRemoveRequest) ([]byte, error)
EncodeSharedPollRefreshRequest(req *SharedPollRefreshRequest) ([]byte, error)
}
var _ RequestEncoder = (*JSONEncoder)(nil)
type JSONEncoder struct{}
func (e *JSONEncoder) EncodeConnectRequest(req *ConnectRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeRefreshRequest(req *RefreshRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeRPCRequest(req *RPCRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeSubscribeRequest(req *SubscribeRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodePublishRequest(req *PublishRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeSubRefreshRequest(req *SubRefreshRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeNotifyCacheEmptyRequest(req *NotifyCacheEmptyRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeMapPublishRequest(req *MapPublishRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeMapRemoveRequest(req *MapRemoveRequest) ([]byte, error) {
return json.Marshal(req)
}
func (e *JSONEncoder) EncodeSharedPollRefreshRequest(req *SharedPollRefreshRequest) ([]byte, error) {
return json.Marshal(req)
}

View File

@@ -0,0 +1,25 @@
#!/bin/bash
set -e
# go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# go install github.com/fatih/gomodifytags@v1.13.0
# go install github.com/FZambia/gomodifytype@latest
which protoc
which gomodifytype
which gomodifytags
protoc-gen-go --version
protoc-gen-go-grpc --version
protoc -I ./ \
proxy.proto \
--go_out=. \
--go-grpc_out=.
gomodifytype -file proxy.pb.go -all -w -from "[]byte" -to "Raw"
bash generate_tags.sh
echo "Done! Make sure JSON tags properly replaced for new messages"

View File

@@ -0,0 +1,11 @@
#!/bin/bash
set -e
echo "replacing tags of structs..."
gomodifytags -file proxy.pb.go -field User -struct RefreshRequest -all -w -remove-options json=omitempty >/dev/null
gomodifytags -file proxy.pb.go -field User -struct SubscribeRequest -all -w -remove-options json=omitempty >/dev/null
gomodifytags -file proxy.pb.go -field User -struct PublishRequest -all -w -remove-options json=omitempty >/dev/null
gomodifytags -file proxy.pb.go -field User -struct RPCRequest -all -w -remove-options json=omitempty >/dev/null
gomodifytags -file proxy.pb.go -field User -struct SubRefreshRequest -all -w -remove-options json=omitempty >/dev/null

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,433 @@
syntax = "proto3";
package centrifugal.centrifugo.proxy;
option go_package = "./;proxyproto";
service CentrifugoProxy {
// Connect to proxy connection authentication and communicate initial state.
rpc Connect(ConnectRequest) returns (ConnectResponse);
// Refresh to proxy decision about connection expiration to the app backend.
rpc Refresh(RefreshRequest) returns (RefreshResponse);
// Subscribe to proxy subscription attempts to channels.
rpc Subscribe(SubscribeRequest) returns (SubscribeResponse);
// Publish to proxy publication attempts to channels.
rpc Publish(PublishRequest) returns (PublishResponse);
// RPC to execute custom logic on the backend over request through the real-time connection.
rpc RPC(RPCRequest) returns (RPCResponse);
// SubRefresh to proxy decision about subscription expiration to the app backend.
rpc SubRefresh(SubRefreshRequest) returns (SubRefreshResponse);
// SubscribeUnidirectional is an EXPERIMENTAL method which allows handling unidirectional
// subscription streams. Stream starts with SubscribeRequest similar to Subscribe rpc,
// then expects StreamSubscribeResponse with SubscribeResponse as first message, and
// StreamSubscribeResponse with Publication afterwards.
rpc SubscribeUnidirectional(SubscribeRequest) returns (stream StreamSubscribeResponse);
// SubscribeBidirectional is an EXPERIMENTAL method which allows handling bidirectional
// subscription streams. Stream receives StreamSubscribeRequest. First StreamSubscribeRequest
// always contains SubscribeRequest, then StreamSubscribeRequest will contain data published
// by client. Reverse direction works the same way as in SubscribeUnidirectional.
rpc SubscribeBidirectional(stream StreamSubscribeRequest) returns (stream StreamSubscribeResponse);
// NotifyCacheEmpty is an EXPERIMENTAL method which allows to load documents from the backend.
rpc NotifyCacheEmpty(NotifyCacheEmptyRequest) returns (NotifyCacheEmptyResponse);
// NotifyChannelState can be used to receive channel events such as channel "occupied" and "vacated".
// This is a feature in a preview state and is only available in Centrifugo PRO.
rpc NotifyChannelState(NotifyChannelStateRequest) returns (NotifyChannelStateResponse);
// MapPublish to proxy map publish attempts to channels.
rpc MapPublish(MapPublishRequest) returns (MapPublishResponse);
// MapRemove to proxy map remove attempts from channels.
rpc MapRemove(MapRemoveRequest) returns (MapRemoveResponse);
// SharedPollRefresh to proxy shared poll refresh requests to the app backend.
rpc SharedPollRefresh(SharedPollRefreshRequest) returns (SharedPollRefreshResponse);
}
message FilterNode {
string op = 1;
string key = 2;
string cmp = 3;
string val = 4;
repeated string vals = 5;
repeated FilterNode nodes = 6;
}
message Disconnect {
reserved 3;
uint32 code = 1;
string reason = 2;
}
message Error {
uint32 code = 1;
string message = 2;
bool temporary = 3;
}
message ConnectRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
bytes data = 10;
string b64data = 11;
string name = 12;
string version = 13;
repeated string channels = 14;
}
message SubscribeOptions {
int64 expire_at = 1;
bytes info = 2;
string b64info = 3;
bytes data = 4;
string b64data = 5;
SubscribeOptionOverride override = 6;
FilterNode server_tags_filter = 7;
// cache_recover, when set, makes Centrifugo initiate cache recovery for the
// server-side subscription without requiring the client to provide a recover
// flag/position itself. This is the server-side equivalent of subscribing with an
// empty `since` on the client. Mostly useful for unidirectional clients which do
// not know channel names. Requires recovery to be enabled for the channel and only
// applies in cache recovery mode, where it delivers the latest publication on
// (re)subscribe.
bool cache_recover = 8;
}
message ConnectResult {
string user = 1;
int64 expire_at = 2;
bytes info = 3;
string b64info = 4;
bytes data = 5;
string b64data = 6;
repeated string channels = 7;
map<string, SubscribeOptions> subs = 8;
bytes meta = 9;
repeated ChannelsCapability caps = 10;
// PRO only — client labels attached to the centrifuge.Client by Centrifugo PRO.
// Parsed by OSS but not used (OSS does not populate centrifuge.ConnectReply.Labels).
map<string, string> labels = 11;
}
message ChannelsCapability {
repeated string channels = 1;
repeated string allow = 2;
string match = 3;
}
message ConnectResponse {
ConnectResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
message RefreshRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
string user = 10;
bytes meta = 11;
// PRO only — connection labels attached to the originating centrifuge.Client.
// Centrifugo PRO always populates this from Client.Labels() (no opt-in toggle).
map<string, string> labels = 12;
}
message RefreshResult {
bool expired = 1;
int64 expire_at = 2;
bytes info = 3;
string b64info = 4;
bytes meta = 5;
repeated ChannelsCapability caps = 6;
}
message RefreshResponse {
RefreshResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
message SubscribeRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
string user = 10;
string channel = 11;
string token = 12;
bytes meta = 13;
bytes data = 14;
string b64data = 15;
// PRO only — connection labels attached to the originating centrifuge.Client.
// Centrifugo PRO always populates this from Client.Labels() (no opt-in toggle).
map<string, string> labels = 16;
}
message BoolValue {
bool value = 1;
}
message Int32Value {
int32 value = 1;
}
message SubscribeOptionOverride {
BoolValue presence = 1;
BoolValue join_leave = 2;
BoolValue force_recovery = 3;
BoolValue force_positioning = 4;
BoolValue force_push_join_leave = 5;
}
message SubscribeResult {
int64 expire_at = 1;
bytes info = 2;
string b64info = 3;
bytes data = 4;
string b64data = 5;
SubscribeOptionOverride override = 6;
repeated string allow = 7;
FilterNode server_tags_filter = 8;
}
message SubscribeResponse {
SubscribeResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
message PublishRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
string user = 10;
string channel = 11;
bytes data = 12;
string b64data = 13;
bytes meta = 14;
// PRO only — connection labels attached to the originating centrifuge.Client.
// Centrifugo PRO always populates this from Client.Labels() (no opt-in toggle).
map<string, string> labels = 15;
}
message PublishResult {
bytes data = 1;
string b64data = 2;
bool skip_history = 3;
map<string, string> tags = 4;
string idempotency_key = 5;
bool delta = 6;
uint64 version = 7;
string version_epoch = 8;
}
message PublishResponse {
PublishResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
message MapPublishRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
string user = 10;
string channel = 11;
string key = 12;
bytes data = 13;
string b64data = 14;
bytes meta = 15;
// PRO only — connection labels attached to the originating centrifuge.Client.
// Centrifugo PRO always populates this from Client.Labels() (no opt-in toggle).
map<string, string> labels = 16;
}
message MapPublishResult {
string key = 1;
bytes data = 2;
string b64data = 3;
map<string, string> tags = 4;
int64 score = 5;
string key_mode = 6;
bytes stream_data = 7;
string b64stream_data = 8;
string idempotency_key = 9;
bool delta = 10;
uint64 version = 11;
string version_epoch = 12;
}
message MapPublishResponse {
MapPublishResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
message MapRemoveRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
string user = 10;
string channel = 11;
string key = 12;
bytes meta = 13;
// PRO only — connection labels attached to the originating centrifuge.Client.
// Centrifugo PRO always populates this from Client.Labels() (no opt-in toggle).
map<string, string> labels = 14;
}
message MapRemoveResult {
string key = 1;
map<string, string> tags = 2;
string idempotency_key = 3;
}
message MapRemoveResponse {
MapRemoveResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
message RPCRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
string user = 10;
string method = 11;
bytes data = 12;
string b64data = 13;
bytes meta = 14;
// PRO only — connection labels attached to the originating centrifuge.Client.
// Centrifugo PRO always populates this from Client.Labels() (no opt-in toggle).
map<string, string> labels = 15;
}
message RPCResult {
bytes data = 1;
string b64data = 2;
}
message RPCResponse {
RPCResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
message SubRefreshRequest {
string client = 1;
string transport = 2;
string protocol = 3;
string encoding = 4;
string user = 10;
string channel = 11;
bytes meta = 12;
// PRO only — connection labels attached to the originating centrifuge.Client.
// Centrifugo PRO always populates this from Client.Labels() (no opt-in toggle).
map<string, string> labels = 13;
}
message SubRefreshResult {
bool expired = 1;
int64 expire_at = 2;
bytes info = 3;
string b64info = 4;
}
message SubRefreshResponse {
SubRefreshResult result = 1;
Error error = 2;
Disconnect disconnect = 3;
}
// Publication is an event to be sent to a client.
// We intentionally make it use the same Protobuf numbers for fields as our client protocol
// Publication - for now only for consistency.
message Publication {
reserved 1, 2, 3, 5, 6;
bytes data = 4;
map<string, string> tags = 7;
}
message StreamSubscribeRequest {
// Centrifugo always sends this within the first message upon user subscription request.
// It's always not set in the following StreamRequest messages from Centrifugo.
SubscribeRequest subscribe_request = 1;
// Publication may be set when client publishes to the on-demand stream. If you are using
// bidirectional stream then Centrifugo assumes publications from client-side are allowed.
Publication publication = 2;
}
message StreamSubscribeResponse {
// SubscribeResponse may optionally be set in the first message from backend to Centrifugo.
SubscribeResponse subscribe_response = 1;
// Publication goes to client. Can't be set in the first message from backend to Centrifugo.
Publication publication = 2;
}
message NotifyCacheEmptyRequest {
string channel = 1;
}
message NotifyCacheEmptyResponse {
NotifyCacheEmptyResult result = 1;
}
message NotifyCacheEmptyResult {
bool populated = 1;
}
message NotifyChannelStateRequest {
repeated ChannelEvent events = 1;
}
message ChannelEvent {
int64 time_ms = 1;
string channel = 2;
string type = 3; // "occupied" | "vacated" | could be more in the future. Not using enums for better JSON interop.
}
message NotifyChannelStateResponse {
NotifyChannelStateResult result = 1;
Error error = 2;
}
message NotifyChannelStateResult {}
message SharedPollRefreshRequest {
string channel = 1;
repeated SharedPollRefreshItem items = 2;
}
message SharedPollRefreshItem {
string key = 1;
uint64 version = 2;
}
message SharedPollRefreshResult {
repeated SharedPollRefreshResultItem items = 1;
string epoch = 2;
}
message SharedPollRefreshResultItem {
string key = 1;
bytes data = 2;
uint64 version = 3;
bool removed = 4;
bytes prev_data = 5;
}
message SharedPollRefreshResponse {
SharedPollRefreshResult result = 1;
Error error = 2;
}

View File

@@ -0,0 +1,615 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v7.34.0
// source: proxy.proto
package proxyproto
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
CentrifugoProxy_Connect_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/Connect"
CentrifugoProxy_Refresh_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/Refresh"
CentrifugoProxy_Subscribe_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/Subscribe"
CentrifugoProxy_Publish_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/Publish"
CentrifugoProxy_RPC_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/RPC"
CentrifugoProxy_SubRefresh_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/SubRefresh"
CentrifugoProxy_SubscribeUnidirectional_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/SubscribeUnidirectional"
CentrifugoProxy_SubscribeBidirectional_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/SubscribeBidirectional"
CentrifugoProxy_NotifyCacheEmpty_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/NotifyCacheEmpty"
CentrifugoProxy_NotifyChannelState_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/NotifyChannelState"
CentrifugoProxy_MapPublish_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/MapPublish"
CentrifugoProxy_MapRemove_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/MapRemove"
CentrifugoProxy_SharedPollRefresh_FullMethodName = "/centrifugal.centrifugo.proxy.CentrifugoProxy/SharedPollRefresh"
)
// CentrifugoProxyClient is the client API for CentrifugoProxy service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type CentrifugoProxyClient interface {
// Connect to proxy connection authentication and communicate initial state.
Connect(ctx context.Context, in *ConnectRequest, opts ...grpc.CallOption) (*ConnectResponse, error)
// Refresh to proxy decision about connection expiration to the app backend.
Refresh(ctx context.Context, in *RefreshRequest, opts ...grpc.CallOption) (*RefreshResponse, error)
// Subscribe to proxy subscription attempts to channels.
Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (*SubscribeResponse, error)
// Publish to proxy publication attempts to channels.
Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*PublishResponse, error)
// RPC to execute custom logic on the backend over request through the real-time connection.
RPC(ctx context.Context, in *RPCRequest, opts ...grpc.CallOption) (*RPCResponse, error)
// SubRefresh to proxy decision about subscription expiration to the app backend.
SubRefresh(ctx context.Context, in *SubRefreshRequest, opts ...grpc.CallOption) (*SubRefreshResponse, error)
// SubscribeUnidirectional is an EXPERIMENTAL method which allows handling unidirectional
// subscription streams. Stream starts with SubscribeRequest similar to Subscribe rpc,
// then expects StreamSubscribeResponse with SubscribeResponse as first message, and
// StreamSubscribeResponse with Publication afterwards.
SubscribeUnidirectional(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StreamSubscribeResponse], error)
// SubscribeBidirectional is an EXPERIMENTAL method which allows handling bidirectional
// subscription streams. Stream receives StreamSubscribeRequest. First StreamSubscribeRequest
// always contains SubscribeRequest, then StreamSubscribeRequest will contain data published
// by client. Reverse direction works the same way as in SubscribeUnidirectional.
SubscribeBidirectional(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[StreamSubscribeRequest, StreamSubscribeResponse], error)
// NotifyCacheEmpty is an EXPERIMENTAL method which allows to load documents from the backend.
NotifyCacheEmpty(ctx context.Context, in *NotifyCacheEmptyRequest, opts ...grpc.CallOption) (*NotifyCacheEmptyResponse, error)
// NotifyChannelState can be used to receive channel events such as channel "occupied" and "vacated".
// This is a feature in a preview state and is only available in Centrifugo PRO.
NotifyChannelState(ctx context.Context, in *NotifyChannelStateRequest, opts ...grpc.CallOption) (*NotifyChannelStateResponse, error)
// MapPublish to proxy map publish attempts to channels.
MapPublish(ctx context.Context, in *MapPublishRequest, opts ...grpc.CallOption) (*MapPublishResponse, error)
// MapRemove to proxy map remove attempts from channels.
MapRemove(ctx context.Context, in *MapRemoveRequest, opts ...grpc.CallOption) (*MapRemoveResponse, error)
// SharedPollRefresh to proxy shared poll refresh requests to the app backend.
SharedPollRefresh(ctx context.Context, in *SharedPollRefreshRequest, opts ...grpc.CallOption) (*SharedPollRefreshResponse, error)
}
type centrifugoProxyClient struct {
cc grpc.ClientConnInterface
}
func NewCentrifugoProxyClient(cc grpc.ClientConnInterface) CentrifugoProxyClient {
return &centrifugoProxyClient{cc}
}
func (c *centrifugoProxyClient) Connect(ctx context.Context, in *ConnectRequest, opts ...grpc.CallOption) (*ConnectResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ConnectResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_Connect_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) Refresh(ctx context.Context, in *RefreshRequest, opts ...grpc.CallOption) (*RefreshResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RefreshResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_Refresh_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (*SubscribeResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SubscribeResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_Subscribe_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*PublishResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PublishResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_Publish_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) RPC(ctx context.Context, in *RPCRequest, opts ...grpc.CallOption) (*RPCResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RPCResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_RPC_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) SubRefresh(ctx context.Context, in *SubRefreshRequest, opts ...grpc.CallOption) (*SubRefreshResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SubRefreshResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_SubRefresh_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) SubscribeUnidirectional(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StreamSubscribeResponse], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &CentrifugoProxy_ServiceDesc.Streams[0], CentrifugoProxy_SubscribeUnidirectional_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[SubscribeRequest, StreamSubscribeResponse]{ClientStream: stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type CentrifugoProxy_SubscribeUnidirectionalClient = grpc.ServerStreamingClient[StreamSubscribeResponse]
func (c *centrifugoProxyClient) SubscribeBidirectional(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[StreamSubscribeRequest, StreamSubscribeResponse], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &CentrifugoProxy_ServiceDesc.Streams[1], CentrifugoProxy_SubscribeBidirectional_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[StreamSubscribeRequest, StreamSubscribeResponse]{ClientStream: stream}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type CentrifugoProxy_SubscribeBidirectionalClient = grpc.BidiStreamingClient[StreamSubscribeRequest, StreamSubscribeResponse]
func (c *centrifugoProxyClient) NotifyCacheEmpty(ctx context.Context, in *NotifyCacheEmptyRequest, opts ...grpc.CallOption) (*NotifyCacheEmptyResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(NotifyCacheEmptyResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_NotifyCacheEmpty_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) NotifyChannelState(ctx context.Context, in *NotifyChannelStateRequest, opts ...grpc.CallOption) (*NotifyChannelStateResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(NotifyChannelStateResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_NotifyChannelState_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) MapPublish(ctx context.Context, in *MapPublishRequest, opts ...grpc.CallOption) (*MapPublishResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MapPublishResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_MapPublish_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) MapRemove(ctx context.Context, in *MapRemoveRequest, opts ...grpc.CallOption) (*MapRemoveResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MapRemoveResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_MapRemove_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *centrifugoProxyClient) SharedPollRefresh(ctx context.Context, in *SharedPollRefreshRequest, opts ...grpc.CallOption) (*SharedPollRefreshResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SharedPollRefreshResponse)
err := c.cc.Invoke(ctx, CentrifugoProxy_SharedPollRefresh_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// CentrifugoProxyServer is the server API for CentrifugoProxy service.
// All implementations must embed UnimplementedCentrifugoProxyServer
// for forward compatibility.
type CentrifugoProxyServer interface {
// Connect to proxy connection authentication and communicate initial state.
Connect(context.Context, *ConnectRequest) (*ConnectResponse, error)
// Refresh to proxy decision about connection expiration to the app backend.
Refresh(context.Context, *RefreshRequest) (*RefreshResponse, error)
// Subscribe to proxy subscription attempts to channels.
Subscribe(context.Context, *SubscribeRequest) (*SubscribeResponse, error)
// Publish to proxy publication attempts to channels.
Publish(context.Context, *PublishRequest) (*PublishResponse, error)
// RPC to execute custom logic on the backend over request through the real-time connection.
RPC(context.Context, *RPCRequest) (*RPCResponse, error)
// SubRefresh to proxy decision about subscription expiration to the app backend.
SubRefresh(context.Context, *SubRefreshRequest) (*SubRefreshResponse, error)
// SubscribeUnidirectional is an EXPERIMENTAL method which allows handling unidirectional
// subscription streams. Stream starts with SubscribeRequest similar to Subscribe rpc,
// then expects StreamSubscribeResponse with SubscribeResponse as first message, and
// StreamSubscribeResponse with Publication afterwards.
SubscribeUnidirectional(*SubscribeRequest, grpc.ServerStreamingServer[StreamSubscribeResponse]) error
// SubscribeBidirectional is an EXPERIMENTAL method which allows handling bidirectional
// subscription streams. Stream receives StreamSubscribeRequest. First StreamSubscribeRequest
// always contains SubscribeRequest, then StreamSubscribeRequest will contain data published
// by client. Reverse direction works the same way as in SubscribeUnidirectional.
SubscribeBidirectional(grpc.BidiStreamingServer[StreamSubscribeRequest, StreamSubscribeResponse]) error
// NotifyCacheEmpty is an EXPERIMENTAL method which allows to load documents from the backend.
NotifyCacheEmpty(context.Context, *NotifyCacheEmptyRequest) (*NotifyCacheEmptyResponse, error)
// NotifyChannelState can be used to receive channel events such as channel "occupied" and "vacated".
// This is a feature in a preview state and is only available in Centrifugo PRO.
NotifyChannelState(context.Context, *NotifyChannelStateRequest) (*NotifyChannelStateResponse, error)
// MapPublish to proxy map publish attempts to channels.
MapPublish(context.Context, *MapPublishRequest) (*MapPublishResponse, error)
// MapRemove to proxy map remove attempts from channels.
MapRemove(context.Context, *MapRemoveRequest) (*MapRemoveResponse, error)
// SharedPollRefresh to proxy shared poll refresh requests to the app backend.
SharedPollRefresh(context.Context, *SharedPollRefreshRequest) (*SharedPollRefreshResponse, error)
mustEmbedUnimplementedCentrifugoProxyServer()
}
// UnimplementedCentrifugoProxyServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedCentrifugoProxyServer struct{}
func (UnimplementedCentrifugoProxyServer) Connect(context.Context, *ConnectRequest) (*ConnectResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Connect not implemented")
}
func (UnimplementedCentrifugoProxyServer) Refresh(context.Context, *RefreshRequest) (*RefreshResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Refresh not implemented")
}
func (UnimplementedCentrifugoProxyServer) Subscribe(context.Context, *SubscribeRequest) (*SubscribeResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Subscribe not implemented")
}
func (UnimplementedCentrifugoProxyServer) Publish(context.Context, *PublishRequest) (*PublishResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Publish not implemented")
}
func (UnimplementedCentrifugoProxyServer) RPC(context.Context, *RPCRequest) (*RPCResponse, error) {
return nil, status.Error(codes.Unimplemented, "method RPC not implemented")
}
func (UnimplementedCentrifugoProxyServer) SubRefresh(context.Context, *SubRefreshRequest) (*SubRefreshResponse, error) {
return nil, status.Error(codes.Unimplemented, "method SubRefresh not implemented")
}
func (UnimplementedCentrifugoProxyServer) SubscribeUnidirectional(*SubscribeRequest, grpc.ServerStreamingServer[StreamSubscribeResponse]) error {
return status.Error(codes.Unimplemented, "method SubscribeUnidirectional not implemented")
}
func (UnimplementedCentrifugoProxyServer) SubscribeBidirectional(grpc.BidiStreamingServer[StreamSubscribeRequest, StreamSubscribeResponse]) error {
return status.Error(codes.Unimplemented, "method SubscribeBidirectional not implemented")
}
func (UnimplementedCentrifugoProxyServer) NotifyCacheEmpty(context.Context, *NotifyCacheEmptyRequest) (*NotifyCacheEmptyResponse, error) {
return nil, status.Error(codes.Unimplemented, "method NotifyCacheEmpty not implemented")
}
func (UnimplementedCentrifugoProxyServer) NotifyChannelState(context.Context, *NotifyChannelStateRequest) (*NotifyChannelStateResponse, error) {
return nil, status.Error(codes.Unimplemented, "method NotifyChannelState not implemented")
}
func (UnimplementedCentrifugoProxyServer) MapPublish(context.Context, *MapPublishRequest) (*MapPublishResponse, error) {
return nil, status.Error(codes.Unimplemented, "method MapPublish not implemented")
}
func (UnimplementedCentrifugoProxyServer) MapRemove(context.Context, *MapRemoveRequest) (*MapRemoveResponse, error) {
return nil, status.Error(codes.Unimplemented, "method MapRemove not implemented")
}
func (UnimplementedCentrifugoProxyServer) SharedPollRefresh(context.Context, *SharedPollRefreshRequest) (*SharedPollRefreshResponse, error) {
return nil, status.Error(codes.Unimplemented, "method SharedPollRefresh not implemented")
}
func (UnimplementedCentrifugoProxyServer) mustEmbedUnimplementedCentrifugoProxyServer() {}
func (UnimplementedCentrifugoProxyServer) testEmbeddedByValue() {}
// UnsafeCentrifugoProxyServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to CentrifugoProxyServer will
// result in compilation errors.
type UnsafeCentrifugoProxyServer interface {
mustEmbedUnimplementedCentrifugoProxyServer()
}
func RegisterCentrifugoProxyServer(s grpc.ServiceRegistrar, srv CentrifugoProxyServer) {
// If the following call panics, it indicates UnimplementedCentrifugoProxyServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&CentrifugoProxy_ServiceDesc, srv)
}
func _CentrifugoProxy_Connect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ConnectRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).Connect(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_Connect_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).Connect(ctx, req.(*ConnectRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_Refresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RefreshRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).Refresh(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_Refresh_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).Refresh(ctx, req.(*RefreshRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_Subscribe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SubscribeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).Subscribe(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_Subscribe_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).Subscribe(ctx, req.(*SubscribeRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PublishRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).Publish(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_Publish_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).Publish(ctx, req.(*PublishRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_RPC_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RPCRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).RPC(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_RPC_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).RPC(ctx, req.(*RPCRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_SubRefresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SubRefreshRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).SubRefresh(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_SubRefresh_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).SubRefresh(ctx, req.(*SubRefreshRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_SubscribeUnidirectional_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(SubscribeRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(CentrifugoProxyServer).SubscribeUnidirectional(m, &grpc.GenericServerStream[SubscribeRequest, StreamSubscribeResponse]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type CentrifugoProxy_SubscribeUnidirectionalServer = grpc.ServerStreamingServer[StreamSubscribeResponse]
func _CentrifugoProxy_SubscribeBidirectional_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(CentrifugoProxyServer).SubscribeBidirectional(&grpc.GenericServerStream[StreamSubscribeRequest, StreamSubscribeResponse]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type CentrifugoProxy_SubscribeBidirectionalServer = grpc.BidiStreamingServer[StreamSubscribeRequest, StreamSubscribeResponse]
func _CentrifugoProxy_NotifyCacheEmpty_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(NotifyCacheEmptyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).NotifyCacheEmpty(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_NotifyCacheEmpty_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).NotifyCacheEmpty(ctx, req.(*NotifyCacheEmptyRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_NotifyChannelState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(NotifyChannelStateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).NotifyChannelState(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_NotifyChannelState_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).NotifyChannelState(ctx, req.(*NotifyChannelStateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_MapPublish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MapPublishRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).MapPublish(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_MapPublish_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).MapPublish(ctx, req.(*MapPublishRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_MapRemove_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MapRemoveRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).MapRemove(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_MapRemove_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).MapRemove(ctx, req.(*MapRemoveRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CentrifugoProxy_SharedPollRefresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SharedPollRefreshRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CentrifugoProxyServer).SharedPollRefresh(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CentrifugoProxy_SharedPollRefresh_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CentrifugoProxyServer).SharedPollRefresh(ctx, req.(*SharedPollRefreshRequest))
}
return interceptor(ctx, in, info, handler)
}
// CentrifugoProxy_ServiceDesc is the grpc.ServiceDesc for CentrifugoProxy service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var CentrifugoProxy_ServiceDesc = grpc.ServiceDesc{
ServiceName: "centrifugal.centrifugo.proxy.CentrifugoProxy",
HandlerType: (*CentrifugoProxyServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Connect",
Handler: _CentrifugoProxy_Connect_Handler,
},
{
MethodName: "Refresh",
Handler: _CentrifugoProxy_Refresh_Handler,
},
{
MethodName: "Subscribe",
Handler: _CentrifugoProxy_Subscribe_Handler,
},
{
MethodName: "Publish",
Handler: _CentrifugoProxy_Publish_Handler,
},
{
MethodName: "RPC",
Handler: _CentrifugoProxy_RPC_Handler,
},
{
MethodName: "SubRefresh",
Handler: _CentrifugoProxy_SubRefresh_Handler,
},
{
MethodName: "NotifyCacheEmpty",
Handler: _CentrifugoProxy_NotifyCacheEmpty_Handler,
},
{
MethodName: "NotifyChannelState",
Handler: _CentrifugoProxy_NotifyChannelState_Handler,
},
{
MethodName: "MapPublish",
Handler: _CentrifugoProxy_MapPublish_Handler,
},
{
MethodName: "MapRemove",
Handler: _CentrifugoProxy_MapRemove_Handler,
},
{
MethodName: "SharedPollRefresh",
Handler: _CentrifugoProxy_SharedPollRefresh_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "SubscribeUnidirectional",
Handler: _CentrifugoProxy_SubscribeUnidirectional_Handler,
ServerStreams: true,
},
{
StreamName: "SubscribeBidirectional",
Handler: _CentrifugoProxy_SubscribeBidirectional_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "proxy.proto",
}

View File

@@ -0,0 +1,25 @@
package proxyproto
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
)
func TestMarshalJSON(t *testing.T) {
msg := &RPCRequest{
Data: []byte(`{"input": "привет"}`),
}
_, err := json.Marshal(msg)
require.NoError(t, err)
}
func TestMarshalProtobuf(t *testing.T) {
msg := &RPCRequest{
Data: []byte(`{"input": "привет"}`),
}
_, err := proto.Marshal(msg)
require.NoError(t, err)
}

View File

@@ -0,0 +1,26 @@
package proxyproto
import (
"errors"
)
// Raw type used by Centrifugo as type for fields in structs which value
// we want to left untouched.
type Raw []byte
// MarshalJSON returns *r as the JSON encoding of r.
func (r Raw) MarshalJSON() ([]byte, error) {
if r == nil {
return []byte("null"), nil
}
return r, nil
}
// UnmarshalJSON sets *r to a copy of data.
func (r *Raw) UnmarshalJSON(data []byte) error {
if r == nil {
return errors.New("raw: UnmarshalJSON on nil pointer")
}
*r = append((*r)[0:0], data...)
return nil
}

View File

@@ -0,0 +1,8 @@
Proxy transform rules:
| Client protocol type | Proxy type | Headers | Meta |
| ------------- | ------------- | -------------- | -------------- |
| HTTP | HTTP | In request headers | No meta |
| GRPC | GRPC | No headers | In request meta |
| HTTP | GRPC | In request meta | No meta |
| GRPC | HTTP | No headers | In request headers |

View File

@@ -0,0 +1,199 @@
package proxyproto
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
func TestEncodeSharedPollRefreshRequest(t *testing.T) {
encoder := &JSONEncoder{}
req := &SharedPollRefreshRequest{
Channel: "test:channel",
Items: []*SharedPollRefreshItem{
{Key: "key1", Version: 0},
{Key: "key2", Version: 5},
},
}
data, err := encoder.EncodeSharedPollRefreshRequest(req)
require.NoError(t, err)
var decoded map[string]interface{}
err = json.Unmarshal(data, &decoded)
require.NoError(t, err)
require.Equal(t, "test:channel", decoded["channel"])
items := decoded["items"].([]interface{})
require.Len(t, items, 2)
item0 := items[0].(map[string]interface{})
require.Equal(t, "key1", item0["key"])
// Version 0 should be omitted (omitempty).
_, hasVersion := item0["version"]
require.False(t, hasVersion)
item1 := items[1].(map[string]interface{})
require.Equal(t, "key2", item1["key"])
require.Equal(t, float64(5), item1["version"])
}
func TestEncodeSharedPollRefreshRequest_EmptyItems(t *testing.T) {
encoder := &JSONEncoder{}
req := &SharedPollRefreshRequest{
Channel: "ch",
Items: []*SharedPollRefreshItem{},
}
data, err := encoder.EncodeSharedPollRefreshRequest(req)
require.NoError(t, err)
require.Contains(t, string(data), `"channel":"ch"`)
}
func TestDecodeSharedPollRefreshResponse(t *testing.T) {
decoder := &JSONDecoder{}
input := `{
"result": {
"items": [
{"key": "key1", "data": {"votes": 42}, "version": 5},
{"key": "key2", "data": {"votes": 10}, "version": 3, "removed": true}
]
}
}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(input))
require.NoError(t, err)
require.NotNil(t, resp.Result)
require.Len(t, resp.Result.Items, 2)
item0 := resp.Result.Items[0]
require.Equal(t, "key1", item0.Key)
require.Equal(t, uint64(5), item0.Version)
require.False(t, item0.Removed)
require.Contains(t, string(item0.Data), "42")
item1 := resp.Result.Items[1]
require.Equal(t, "key2", item1.Key)
require.Equal(t, uint64(3), item1.Version)
require.True(t, item1.Removed)
}
func TestDecodeSharedPollRefreshResponse_EmptyItems(t *testing.T) {
decoder := &JSONDecoder{}
input := `{"result": {"items": []}}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(input))
require.NoError(t, err)
require.NotNil(t, resp.Result)
require.Empty(t, resp.Result.Items)
}
func TestDecodeSharedPollRefreshResponse_MissingFields(t *testing.T) {
decoder := &JSONDecoder{}
input := `{"result": {"items": [{"key": "key1"}]}}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(input))
require.NoError(t, err)
require.Len(t, resp.Result.Items, 1)
item := resp.Result.Items[0]
require.Equal(t, "key1", item.Key)
require.Equal(t, uint64(0), item.Version)
require.False(t, item.Removed)
require.Nil(t, item.Data)
require.Nil(t, item.PrevData)
}
func TestDecodeSharedPollRefreshResponse_WithPrevData(t *testing.T) {
decoder := &JSONDecoder{}
input := `{"result": {"items": [{"key": "k1", "data": {"v": 1}, "version": 2, "prev_data": {"v": 0}}]}}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(input))
require.NoError(t, err)
require.Len(t, resp.Result.Items, 1)
require.NotNil(t, resp.Result.Items[0].PrevData)
require.Contains(t, string(resp.Result.Items[0].PrevData), "0")
}
func TestDecodeSharedPollRefreshResponse_ErrorResponse(t *testing.T) {
decoder := &JSONDecoder{}
input := `{"error": {"code": 100, "message": "internal error"}}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(input))
require.NoError(t, err)
require.NotNil(t, resp.Error)
require.Equal(t, uint32(100), resp.Error.Code)
require.Equal(t, "internal error", resp.Error.Message)
require.Nil(t, resp.Result)
}
func TestDecodeSharedPollRefreshResponse_NullResult(t *testing.T) {
decoder := &JSONDecoder{}
input := `{"result": null}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(input))
require.NoError(t, err)
require.Nil(t, resp.Result)
}
func TestDecodeSharedPollRefreshResponse_InvalidJSON(t *testing.T) {
decoder := &JSONDecoder{}
_, err := decoder.DecodeSharedPollRefreshResponse([]byte(`not json`))
require.Error(t, err)
}
func TestSharedPollRefreshRequest_RoundTrip(t *testing.T) {
encoder := &JSONEncoder{}
decoder := &JSONDecoder{}
original := &SharedPollRefreshRequest{
Channel: "test:ch",
Items: []*SharedPollRefreshItem{
{Key: "k1", Version: 10},
{Key: "k2", Version: 0},
{Key: "k3", Version: 999},
},
}
data, err := encoder.EncodeSharedPollRefreshRequest(original)
require.NoError(t, err)
// Wrap in response format to test decode.
respJSON := `{"result": {"items": [{"key": "k1", "data": {"x": 1}, "version": 11}, {"key": "k3", "data": {"x": 3}, "version": 1000}]}}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(respJSON))
require.NoError(t, err)
require.Len(t, resp.Result.Items, 2)
// Verify the request was encoded properly.
var reqDecoded SharedPollRefreshRequest
err = json.Unmarshal(data, &reqDecoded)
require.NoError(t, err)
require.Equal(t, "test:ch", reqDecoded.Channel)
require.Len(t, reqDecoded.Items, 3)
}
func TestEncodeSharedPollRefreshRequest_DiffMode(t *testing.T) {
encoder := &JSONEncoder{}
req := &SharedPollRefreshRequest{
Channel: "ch",
Items: []*SharedPollRefreshItem{
{Key: "k1", Version: 5},
{Key: "k2", Version: 10},
},
}
data, err := encoder.EncodeSharedPollRefreshRequest(req)
require.NoError(t, err)
var decoded map[string]interface{}
err = json.Unmarshal(data, &decoded)
require.NoError(t, err)
items := decoded["items"].([]interface{})
item0 := items[0].(map[string]interface{})
require.Equal(t, float64(5), item0["version"])
item1 := items[1].(map[string]interface{})
require.Equal(t, float64(10), item1["version"])
}
func TestDecodeSharedPollRefreshResponse_RemovedItem(t *testing.T) {
decoder := &JSONDecoder{}
input := `{"result": {"items": [{"key": "k1", "removed": true}]}}`
resp, err := decoder.DecodeSharedPollRefreshResponse([]byte(input))
require.NoError(t, err)
require.Len(t, resp.Result.Items, 1)
require.True(t, resp.Result.Items[0].Removed)
require.Equal(t, "k1", resp.Result.Items[0].Key)
require.Equal(t, uint64(0), resp.Result.Items[0].Version)
}