diff --git a/.golangci.yml b/.golangci.yml index e853e72..a800bb5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -84,3 +84,7 @@ issues: - path: params.go linters: - goconst # allow string literals for WKT names + - path: protocol.go + linters: + - gochecknoglobals # allow Protocol global helpers + text: "(allProtocols|protocolToString) is a global variable" diff --git a/protocol.go b/protocol.go index 5cf497f..9ad131b 100644 --- a/protocol.go +++ b/protocol.go @@ -16,10 +16,10 @@ package vanguard import ( "bytes" - "fmt" "io" "net/http" "net/textproto" + "strconv" "strings" "time" @@ -33,13 +33,6 @@ const envelopeLen = 5 type Protocol int const ( - // The ordinal value of the protocol (other than the zero value) reflects - // the preference order. So Connect is the highest preferred protocol, - // then gRPC, etc. - - // protocolUnknown is not a valid value. Since it is the zero value, this - // requires that all Protocol values must be explicitly initialized. - protocolUnknown = Protocol(0) // ProtocolConnect indicates the Connect protocol. This protocol supports // unary and streaming endpoints. However, bidirectional streams are only // supported when combined with HTTP/2. @@ -65,31 +58,31 @@ const ( // // This protocol only supports unary and server-stream endpoints. ProtocolREST +) - // protocolMin is the minimum valid value for a Protocol. - protocolMin = ProtocolConnect - // protocolMax is the maximum valid value for a Protocol. - protocolMax = ProtocolREST - - protocolNameConnect = "Connect" - protocolNameGRPC = "gRPC" - protocolNameGRPCWeb = "gRPC-Web" - protocolNameREST = "REST" +var ( + // allProtocols are all supported protocols in descending order of + // preference. The first protocol is the default protocol. + allProtocols = [...]Protocol{ + ProtocolConnect, + ProtocolGRPC, + ProtocolGRPCWeb, + ProtocolREST, + } + protocolToString = map[Protocol]string{ + ProtocolConnect: "Connect", + ProtocolGRPC: "gRPC", + ProtocolGRPCWeb: "gRPC-Web", + ProtocolREST: "REST", + } ) func (p Protocol) String() string { - switch p { - case ProtocolConnect: - return protocolNameConnect - case ProtocolGRPC: - return protocolNameGRPC - case ProtocolGRPCWeb: - return protocolNameGRPCWeb - case ProtocolREST: - return protocolNameREST - default: - return fmt.Sprintf("unknown protocol (%d)", p) + s, ok := protocolToString[p] + if !ok { + return strconv.Itoa(int(p)) } + return s } func (p Protocol) serverHandler(op *operation) serverProtocolHandler { diff --git a/protocol_connect.go b/protocol_connect.go index 894aa59..d673bef 100644 --- a/protocol_connect.go +++ b/protocol_connect.go @@ -37,11 +37,6 @@ import ( ) const ( - protocolNameConnectUnary = protocolNameConnect + " unary" - protocolNameConnectUnaryGet = protocolNameConnectUnary + " (GET)" - protocolNameConnectUnaryPost = protocolNameConnectUnary + " (POST)" - protocolNameConnectStream = protocolNameConnect + " stream" - // TODO: Extract more constants for header names and values. contentTypeJSON = "application/json" ) @@ -154,7 +149,7 @@ func (c connectUnaryGetClientProtocol) prepareMarshalledResponse(_ *operation, _ } func (c connectUnaryGetClientProtocol) String() string { - return protocolNameConnectUnaryGet + return c.protocol().String() + " unary (GET)" } // connectUnaryPostClientProtocol implements the Connect protocol for @@ -239,7 +234,7 @@ func (c connectUnaryPostClientProtocol) encodeEnd(op *operation, end *responseEn } func (c connectUnaryPostClientProtocol) String() string { - return protocolNameConnectUnaryPost + return c.protocol().String() + " unary (POST)" } // connectUnaryServerProtocol implements the Connect protocol for @@ -402,7 +397,7 @@ func (c connectUnaryServerProtocol) requestLine(op *operation, msg proto.Message } func (c connectUnaryServerProtocol) String() string { - return protocolNameConnectUnary + return c.protocol().String() + " unary" } // connectStreamClientProtocol implements the Connect protocol for @@ -488,7 +483,7 @@ func (c connectStreamClientProtocol) encodeEnvelope(env envelope) envelopeBytes } func (c connectStreamClientProtocol) String() string { - return protocolNameConnectStream + return c.protocol().String() + " stream" } // connectStreamServerProtocol implements the Connect protocol for @@ -585,7 +580,7 @@ func (c connectStreamServerProtocol) decodeEndFromMessage(_ *operation, buffer * } func (c connectStreamServerProtocol) String() string { - return protocolNameConnectStream + return c.protocol().String() + " stream" } func connectExtractUnaryTrailers(headers http.Header) http.Header { diff --git a/protocol_grpc.go b/protocol_grpc.go index 60bad54..2c97f25 100644 --- a/protocol_grpc.go +++ b/protocol_grpc.go @@ -93,7 +93,7 @@ func (g grpcClientProtocol) encodeEnvelope(env envelope) envelopeBytes { } func (g grpcClientProtocol) String() string { - return protocolNameGRPC + return g.protocol().String() } // grpcServerProtocol implements the gRPC protocol for @@ -148,7 +148,7 @@ func (g grpcServerProtocol) decodeEndFromMessage(_ *operation, _ *bytes.Buffer) } func (g grpcServerProtocol) String() string { - return protocolNameGRPC + return g.protocol().String() } // grpcClientProtocol implements the gRPC protocol for @@ -209,7 +209,7 @@ func (g grpcWebClientProtocol) encodeEnvelope(env envelope) envelopeBytes { } func (g grpcWebClientProtocol) String() string { - return protocolNameGRPCWeb + return g.protocol().String() } // grpcServerProtocol implements the gRPC-Web protocol for @@ -275,7 +275,7 @@ func (g grpcWebServerProtocol) decodeEndFromMessage(_ *operation, buffer *bytes. } func (g grpcWebServerProtocol) String() string { - return protocolNameGRPCWeb + return g.protocol().String() } func grpcExtractRequestMeta(contentTypeShort, contentTypePrefix string, headers http.Header) (requestMeta, error) { diff --git a/protocol_rest.go b/protocol_rest.go index f968e65..a101481 100644 --- a/protocol_rest.go +++ b/protocol_rest.go @@ -244,7 +244,7 @@ func (r restClientProtocol) prepareMarshalledResponse(op *operation, base []byte } func (r restClientProtocol) String() string { - return protocolNameREST + return r.protocol().String() } // restServerProtocol implements the REST protocol for @@ -392,7 +392,7 @@ func (r restServerProtocol) requestLine(op *operation, req proto.Message) (urlPa } func (r restServerProtocol) String() string { - return protocolNameREST + return r.protocol().String() } // Decode timeout as a float in seconds from X-Server-Timeout header. diff --git a/transcoder.go b/transcoder.go index 6080577..0acc481 100644 --- a/transcoder.go +++ b/transcoder.go @@ -86,7 +86,8 @@ func (t *Transcoder) registerService(svc *Service, svcOpts serviceOptions) error return fmt.Errorf("service %s was configured with no target protocols", svc.schema.FullName()) } for protocol := range svcOpts.protocols { - if protocol <= protocolUnknown || protocol > protocolMax { + _, isKnown := protocolToString[protocol] + if !isKnown { return fmt.Errorf("protocol %d is not a valid value", protocol) } } @@ -422,7 +423,7 @@ func (o *operation) validate(transcoder *Transcoder) error { if _, supportsProtocol := o.methodConf.protocols[clientProtoHandler.protocol()]; supportsProtocol { o.server.protocol = clientProtoHandler.protocol().serverHandler(o) } else { - for protocol := protocolMin; protocol <= protocolMax; protocol++ { + for _, protocol := range allProtocols { if _, supportsProtocol := o.methodConf.protocols[protocol]; supportsProtocol { o.server.protocol = protocol.serverHandler(o) break