775 lines
19 KiB
Go
775 lines
19 KiB
Go
package api
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/centrifugal/centrifugo/v6/internal/apiproto"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/codes"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
type LegacyCommand struct {
|
|
Id uint32 `json:"id,omitempty"`
|
|
Method CommandMethodType `json:"method,omitempty"`
|
|
Params apiproto.Raw `json:"params,omitempty"`
|
|
}
|
|
|
|
type LegacyReply struct {
|
|
Id uint32 `json:"id,omitempty"`
|
|
Error *apiproto.Error `json:"error,omitempty"`
|
|
Result apiproto.Raw `json:"result,omitempty"`
|
|
}
|
|
|
|
type CommandMethodType int32
|
|
|
|
// UnmarshalJSON helps to unmarshal command method when set as string.
|
|
func (m *CommandMethodType) UnmarshalJSON(data []byte) error {
|
|
if len(data) > 2 {
|
|
if v, ok := Command_MethodType_value[strings.ToUpper(string(data[1:len(data)-1]))]; ok {
|
|
*m = CommandMethodType(v)
|
|
return nil
|
|
}
|
|
}
|
|
val, err := strconv.Atoi(string(data))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*m = CommandMethodType(val)
|
|
return nil
|
|
}
|
|
|
|
// GetParamsDecoder ...
|
|
func GetParamsDecoder() apiproto.RequestDecoder {
|
|
return apiproto.NewJSONRequestDecoder()
|
|
}
|
|
|
|
// PutParamsDecoder ...
|
|
func PutParamsDecoder(_ apiproto.RequestDecoder) {}
|
|
|
|
// GetResultEncoder ...
|
|
func GetResultEncoder() apiproto.ResultEncoder {
|
|
return apiproto.NewJSONResultEncoder()
|
|
}
|
|
|
|
// PutResultEncoder ...
|
|
func PutResultEncoder(_ apiproto.ResultEncoder) {}
|
|
|
|
var (
|
|
jsonReplyEncoderPool sync.Pool
|
|
)
|
|
|
|
// ReplyEncoder ...
|
|
type ReplyEncoder interface {
|
|
Reset()
|
|
Encode(reply *LegacyReply) error
|
|
Finish() []byte
|
|
}
|
|
|
|
var _ ReplyEncoder = (*JSONReplyEncoder)(nil)
|
|
|
|
// JSONReplyEncoder ...
|
|
type JSONReplyEncoder struct {
|
|
count int
|
|
buffer bytes.Buffer
|
|
}
|
|
|
|
// NewJSONReplyEncoder ...
|
|
func NewJSONReplyEncoder() *JSONReplyEncoder {
|
|
return &JSONReplyEncoder{}
|
|
}
|
|
|
|
// Reset ...
|
|
func (e *JSONReplyEncoder) Reset() {
|
|
e.count = 0
|
|
e.buffer.Reset()
|
|
}
|
|
|
|
// Encode ...
|
|
func (e *JSONReplyEncoder) Encode(r *LegacyReply) error {
|
|
if e.count > 0 {
|
|
e.buffer.WriteString("\n")
|
|
}
|
|
data, err := json.Marshal(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
e.buffer.Write(data)
|
|
e.count++
|
|
return nil
|
|
}
|
|
|
|
// Finish ...
|
|
func (e *JSONReplyEncoder) Finish() []byte {
|
|
data := e.buffer.Bytes()
|
|
dataCopy := make([]byte, len(data))
|
|
copy(dataCopy, data)
|
|
return dataCopy
|
|
}
|
|
|
|
// GetReplyEncoder ...
|
|
func GetReplyEncoder() ReplyEncoder {
|
|
e := jsonReplyEncoderPool.Get()
|
|
if e == nil {
|
|
return NewJSONReplyEncoder()
|
|
}
|
|
return e.(ReplyEncoder)
|
|
}
|
|
|
|
// PutReplyEncoder ...
|
|
func PutReplyEncoder(e ReplyEncoder) {
|
|
e.Reset()
|
|
jsonReplyEncoderPool.Put(e)
|
|
}
|
|
|
|
// CommandDecoder ...
|
|
type CommandDecoder interface {
|
|
Reset([]byte)
|
|
Decode() (*LegacyCommand, error)
|
|
}
|
|
|
|
var jsonCommandDecoderPool sync.Pool
|
|
|
|
var _ CommandDecoder = (*JSONCommandDecoder)(nil)
|
|
|
|
// GetCommandDecoder ...
|
|
func GetCommandDecoder(data []byte) CommandDecoder {
|
|
e := jsonCommandDecoderPool.Get()
|
|
if e == nil {
|
|
return NewJSONCommandDecoder(data)
|
|
}
|
|
decoder := e.(CommandDecoder)
|
|
decoder.Reset(data)
|
|
return decoder
|
|
}
|
|
|
|
// PutCommandDecoder ...
|
|
func PutCommandDecoder(d CommandDecoder) {
|
|
jsonCommandDecoderPool.Put(d)
|
|
}
|
|
|
|
// JSONCommandDecoder ...
|
|
type JSONCommandDecoder struct {
|
|
decoder *json.Decoder
|
|
}
|
|
|
|
// NewJSONCommandDecoder ...
|
|
func NewJSONCommandDecoder(data []byte) *JSONCommandDecoder {
|
|
return &JSONCommandDecoder{
|
|
decoder: json.NewDecoder(bytes.NewReader(data)),
|
|
}
|
|
}
|
|
|
|
// Reset ...
|
|
func (d *JSONCommandDecoder) Reset(data []byte) {
|
|
d.decoder = json.NewDecoder(bytes.NewReader(data))
|
|
}
|
|
|
|
// Decode ...
|
|
func (d *JSONCommandDecoder) Decode() (*LegacyCommand, error) {
|
|
var c LegacyCommand
|
|
err := d.decoder.Decode(&c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &c, nil
|
|
}
|
|
|
|
// OldRoute handles all methods inside one /api handler.
|
|
// The plan is to remove it in Centrifugo v7.
|
|
func (s *Handler) OldRoute() http.HandlerFunc {
|
|
return s.handleAPI
|
|
}
|
|
|
|
func (s *Handler) handleAPI(w http.ResponseWriter, r *http.Request) {
|
|
select {
|
|
case <-s.node.NotifyShutdown():
|
|
w.WriteHeader(http.StatusServiceUnavailable)
|
|
return
|
|
default:
|
|
}
|
|
|
|
var data []byte
|
|
var err error
|
|
|
|
data, err = io.ReadAll(r.Body)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error reading API request body")
|
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if len(data) == 0 {
|
|
log.Error().Err(errors.New("no data in API request")).Msg("bad request")
|
|
http.Error(w, "Bad Request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
encoder := GetReplyEncoder()
|
|
defer PutReplyEncoder(encoder)
|
|
|
|
decoder := GetCommandDecoder(data)
|
|
defer PutCommandDecoder(decoder)
|
|
|
|
for {
|
|
command, decodeErr := decoder.Decode()
|
|
if decodeErr != nil && decodeErr != io.EOF {
|
|
log.Error().Err(decodeErr).Msg("error decoding API data")
|
|
http.Error(w, "Bad Request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
if command != nil {
|
|
if s.config.UseOpenTelemetry {
|
|
span := trace.SpanFromContext(r.Context())
|
|
span.SetAttributes(attribute.String("method", Command_MethodType_name[int32(command.Method)]))
|
|
}
|
|
rep, err := s.handleAPICommand(r.Context(), command)
|
|
if err != nil {
|
|
if s.config.UseOpenTelemetry {
|
|
span := trace.SpanFromContext(r.Context())
|
|
span.SetStatus(codes.Error, err.Error())
|
|
}
|
|
log.Error().Err(err).Msg("error handling API command")
|
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if s.config.UseOpenTelemetry && rep.Error != nil {
|
|
span := trace.SpanFromContext(r.Context())
|
|
span.SetStatus(codes.Error, rep.Error.Error())
|
|
}
|
|
err = encoder.Encode(rep)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error encoding API reply")
|
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
if decodeErr == io.EOF {
|
|
break
|
|
}
|
|
}
|
|
s.writeJson(w, encoder.Finish())
|
|
}
|
|
|
|
const (
|
|
Command_PUBLISH CommandMethodType = 0
|
|
Command_BROADCAST CommandMethodType = 1
|
|
Command_UNSUBSCRIBE CommandMethodType = 2
|
|
Command_DISCONNECT CommandMethodType = 3
|
|
Command_PRESENCE CommandMethodType = 4
|
|
Command_PRESENCE_STATS CommandMethodType = 5
|
|
Command_HISTORY CommandMethodType = 6
|
|
Command_HISTORY_REMOVE CommandMethodType = 7
|
|
Command_CHANNELS CommandMethodType = 8
|
|
Command_INFO CommandMethodType = 9
|
|
Command_RPC CommandMethodType = 10
|
|
Command_SUBSCRIBE CommandMethodType = 11
|
|
Command_REFRESH CommandMethodType = 12
|
|
Command_CONNECTIONS CommandMethodType = 14
|
|
Command_UPDATE_USER_STATUS CommandMethodType = 15
|
|
Command_GET_USER_STATUS CommandMethodType = 16
|
|
Command_DELETE_USER_STATUS CommandMethodType = 17
|
|
Command_BLOCK_USER CommandMethodType = 18
|
|
Command_UNBLOCK_USER CommandMethodType = 19
|
|
Command_REVOKE_TOKEN CommandMethodType = 20
|
|
Command_INVALIDATE_USER_TOKENS CommandMethodType = 21
|
|
Command_DEVICE_REGISTER CommandMethodType = 22
|
|
Command_DEVICE_UPDATE CommandMethodType = 23
|
|
Command_DEVICE_REMOVE CommandMethodType = 24
|
|
Command_DEVICE_LIST CommandMethodType = 25
|
|
Command_DEVICE_TOPIC_LIST CommandMethodType = 26
|
|
Command_DEVICE_TOPIC_UPDATE CommandMethodType = 27
|
|
Command_USER_TOPIC_LIST CommandMethodType = 28
|
|
Command_USER_TOPIC_UPDATE CommandMethodType = 29
|
|
Command_SEND_PUSH_NOTIFICATION CommandMethodType = 30
|
|
Command_UPDATE_PUSH_STATUS CommandMethodType = 31
|
|
Command_CANCEL_PUSH CommandMethodType = 32
|
|
Command_MAP_PUBLISH CommandMethodType = 33
|
|
Command_MAP_REMOVE CommandMethodType = 34
|
|
Command_MAP_READ_STATE CommandMethodType = 35
|
|
Command_MAP_READ_STREAM CommandMethodType = 36
|
|
Command_MAP_STATS CommandMethodType = 37
|
|
Command_MAP_CLEAR CommandMethodType = 38
|
|
Command_SHARED_POLL_PUBLISH CommandMethodType = 39
|
|
)
|
|
|
|
var Command_MethodType_value = map[string]int32{
|
|
"PUBLISH": 0,
|
|
"BROADCAST": 1,
|
|
"UNSUBSCRIBE": 2,
|
|
"DISCONNECT": 3,
|
|
"PRESENCE": 4,
|
|
"PRESENCE_STATS": 5,
|
|
"HISTORY": 6,
|
|
"HISTORY_REMOVE": 7,
|
|
"CHANNELS": 8,
|
|
"INFO": 9,
|
|
"RPC": 10,
|
|
"SUBSCRIBE": 11,
|
|
"REFRESH": 12,
|
|
"CONNECTIONS": 14,
|
|
"UPDATE_USER_STATUS": 15,
|
|
"GET_USER_STATUS": 16,
|
|
"DELETE_USER_STATUS": 17,
|
|
"BLOCK_USER": 18,
|
|
"UNBLOCK_USER": 19,
|
|
"REVOKE_TOKEN": 20,
|
|
"INVALIDATE_USER_TOKENS": 21,
|
|
"DEVICE_REGISTER": 22,
|
|
"DEVICE_UPDATE": 23,
|
|
"DEVICE_REMOVE": 24,
|
|
"DEVICE_LIST": 25,
|
|
"DEVICE_TOPIC_LIST": 26,
|
|
"DEVICE_TOPIC_UPDATE": 27,
|
|
"USER_TOPIC_LIST": 28,
|
|
"USER_TOPIC_UPDATE": 29,
|
|
"SEND_PUSH_NOTIFICATION": 30,
|
|
"UPDATE_PUSH_STATUS": 31,
|
|
"CANCEL_PUSH": 32,
|
|
"MAP_PUBLISH": 33,
|
|
"MAP_REMOVE": 34,
|
|
"MAP_READ_STATE": 35,
|
|
"MAP_READ_STREAM": 36,
|
|
"MAP_STATS": 37,
|
|
"MAP_CLEAR": 38,
|
|
"SHARED_POLL_PUBLISH": 39,
|
|
}
|
|
|
|
var (
|
|
Command_MethodType_name = map[int32]string{
|
|
0: "PUBLISH",
|
|
1: "BROADCAST",
|
|
2: "UNSUBSCRIBE",
|
|
3: "DISCONNECT",
|
|
4: "PRESENCE",
|
|
5: "PRESENCE_STATS",
|
|
6: "HISTORY",
|
|
7: "HISTORY_REMOVE",
|
|
8: "CHANNELS",
|
|
9: "INFO",
|
|
10: "RPC",
|
|
11: "SUBSCRIBE",
|
|
12: "REFRESH",
|
|
14: "CONNECTIONS",
|
|
15: "UPDATE_USER_STATUS",
|
|
16: "GET_USER_STATUS",
|
|
17: "DELETE_USER_STATUS",
|
|
18: "BLOCK_USER",
|
|
19: "UNBLOCK_USER",
|
|
20: "REVOKE_TOKEN",
|
|
21: "INVALIDATE_USER_TOKENS",
|
|
22: "DEVICE_REGISTER",
|
|
23: "DEVICE_UPDATE",
|
|
24: "DEVICE_REMOVE",
|
|
25: "DEVICE_LIST",
|
|
26: "DEVICE_TOPIC_LIST",
|
|
27: "DEVICE_TOPIC_UPDATE",
|
|
28: "USER_TOPIC_LIST",
|
|
29: "USER_TOPIC_UPDATE",
|
|
30: "SEND_PUSH_NOTIFICATION",
|
|
31: "UPDATE_PUSH_STATUS",
|
|
32: "CANCEL_PUSH",
|
|
33: "MAP_PUBLISH",
|
|
34: "MAP_REMOVE",
|
|
35: "MAP_READ_STATE",
|
|
36: "MAP_READ_STREAM",
|
|
37: "MAP_STATS",
|
|
38: "MAP_CLEAR",
|
|
39: "SHARED_POLL_PUBLISH",
|
|
}
|
|
)
|
|
|
|
func (s *Handler) handleAPICommand(ctx context.Context, cmd *LegacyCommand) (*LegacyReply, error) {
|
|
|
|
method := cmd.Method
|
|
params := cmd.Params
|
|
|
|
rep := &LegacyReply{
|
|
Id: cmd.Id,
|
|
}
|
|
|
|
var replyRes apiproto.Raw
|
|
|
|
decoder := GetParamsDecoder()
|
|
defer PutParamsDecoder(decoder)
|
|
|
|
encoder := GetResultEncoder()
|
|
defer PutResultEncoder(encoder)
|
|
|
|
switch method {
|
|
case Command_PUBLISH:
|
|
cmd, err := decoder.DecodePublish(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding publish params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Publish(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodePublish(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_BROADCAST:
|
|
cmd, err := decoder.DecodeBroadcast(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding broadcast params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Broadcast(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeBroadcast(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_SUBSCRIBE:
|
|
cmd, err := decoder.DecodeSubscribe(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding subscribe params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Subscribe(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeSubscribe(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_UNSUBSCRIBE:
|
|
cmd, err := decoder.DecodeUnsubscribe(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding unsubscribe params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Unsubscribe(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeUnsubscribe(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_DISCONNECT:
|
|
cmd, err := decoder.DecodeDisconnect(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding disconnect params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Disconnect(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeDisconnect(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_PRESENCE:
|
|
cmd, err := decoder.DecodePresence(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding presence params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Presence(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodePresence(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_PRESENCE_STATS:
|
|
cmd, err := decoder.DecodePresenceStats(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding presence stats params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.PresenceStats(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodePresenceStats(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_HISTORY:
|
|
cmd, err := decoder.DecodeHistory(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding history params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.History(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeHistory(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_HISTORY_REMOVE:
|
|
cmd, err := decoder.DecodeHistoryRemove(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding history remove params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.HistoryRemove(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeHistoryRemove(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_INFO:
|
|
resp := s.api.Info(ctx, &apiproto.InfoRequest{})
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
var err error
|
|
replyRes, err = encoder.EncodeInfo(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_RPC:
|
|
cmd, err := decoder.DecodeRPC(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding rpc params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.RPC(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeRPC(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_REFRESH:
|
|
cmd, err := decoder.DecodeRefresh(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding refresh params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Refresh(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeRefresh(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_CHANNELS:
|
|
cmd, err := decoder.DecodeChannels(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding channels params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.Channels(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeChannels(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_MAP_PUBLISH:
|
|
cmd, err := decoder.DecodeMapPublish(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding map publish params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.MapPublish(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeMapPublish(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_MAP_REMOVE:
|
|
cmd, err := decoder.DecodeMapRemove(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding map remove params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.MapRemove(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeMapRemove(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_MAP_READ_STATE:
|
|
cmd, err := decoder.DecodeMapReadState(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding map read state params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.MapReadState(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeMapReadState(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_MAP_READ_STREAM:
|
|
cmd, err := decoder.DecodeMapReadStream(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding map read stream params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.MapReadStream(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeMapReadStream(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_MAP_STATS:
|
|
cmd, err := decoder.DecodeMapStats(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding map stats params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.MapStats(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeMapStats(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_MAP_CLEAR:
|
|
cmd, err := decoder.DecodeMapClear(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding map clear params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.MapClear(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeMapClear(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case Command_SHARED_POLL_PUBLISH:
|
|
cmd, err := decoder.DecodeSharedPollPublish(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error decoding shared poll publish params")
|
|
rep.Error = apiproto.ErrorBadRequest
|
|
return rep, nil
|
|
}
|
|
resp := s.api.SharedPollPublish(ctx, cmd)
|
|
if resp.Error != nil {
|
|
rep.Error = resp.Error
|
|
} else {
|
|
if resp.Result != nil {
|
|
replyRes, err = encoder.EncodeSharedPollPublish(resp.Result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
rep.Error = apiproto.ErrorNotFound
|
|
}
|
|
|
|
if replyRes != nil {
|
|
rep.Result = replyRes
|
|
}
|
|
|
|
return rep, nil
|
|
}
|