Skip to content

Commit

Permalink
refactor config
Browse files Browse the repository at this point in the history
  • Loading branch information
FZambia committed Oct 21, 2024
1 parent b6b6242 commit 7647474
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 88 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/FZambia/statik v0.1.2-0.20180217151304-b9f012bb2a1b
github.com/FZambia/tarantool v0.3.1
github.com/FZambia/viper-lite v0.0.0-20220110144934-1899f66c7d0e
github.com/centrifugal/centrifuge v0.33.5-0.20241020185416-a408ea29087f
github.com/centrifugal/centrifuge v0.33.5-0.20241021182958-fcbdab609e7a
github.com/centrifugal/protocol v0.13.4
github.com/cristalhq/jwt/v5 v5.4.0
github.com/gobwas/glob v0.2.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/centrifugal/centrifuge v0.33.5-0.20241020185416-a408ea29087f h1:ildH/ynu9PV2eIRx33GIgnmbFq2KaJRNK9PhAbr+2go=
github.com/centrifugal/centrifuge v0.33.5-0.20241020185416-a408ea29087f/go.mod h1:83bjiDCVcoWrXXjFibG9vS0fJ+aUpSA3kD2RLlvl1RE=
github.com/centrifugal/centrifuge v0.33.5-0.20241021182958-fcbdab609e7a h1:qkRT9GqE2R7SyAfT4ZkU0WaYrWTFA8UnTEjqZkyHuPY=
github.com/centrifugal/centrifuge v0.33.5-0.20241021182958-fcbdab609e7a/go.mod h1:83bjiDCVcoWrXXjFibG9vS0fJ+aUpSA3kD2RLlvl1RE=
github.com/centrifugal/protocol v0.13.4 h1:I0YxXtFNfn/ndDIZp5RkkqQcSSNH7DNPUbXKYtJXDzs=
github.com/centrifugal/protocol v0.13.4/go.mod h1:7V5vI30VcoxJe4UD87xi7bOsvI0bmEhvbQuMjrFM2L4=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
Expand Down
2 changes: 1 addition & 1 deletion internal/proxy/connect_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (p *HTTPConnectProxy) ProxyConnect(ctx context.Context, req *proxyproto.Con
}
respData, err := p.httpCaller.CallHTTP(ctx, p.config.Endpoint, httpRequestHeaders(ctx, p.config), data)
if err != nil {
protocolError, protocolDisconnect := translateHTTPError(err, p.config.HttpStatusTranslate)
protocolError, protocolDisconnect := transformHTTPError(err, p.config.HttpStatusTransforms)
if protocolError != nil || protocolDisconnect != nil {
return &proxyproto.ConnectResponse{
Error: protocolError,
Expand Down
8 changes: 4 additions & 4 deletions internal/proxy/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,16 @@ func stringInSlice(a string, list []string) bool {
return false
}

func translateHTTPError(err error, translate []HttpStatusTranslate) (*proxyproto.Error, *proxyproto.Disconnect) {
if len(translate) == 0 {
func transformHTTPError(err error, transforms []HttpStatusToCodeTransform) (*proxyproto.Error, *proxyproto.Disconnect) {
if len(transforms) == 0 {
return nil, nil
}
var statusErr *statusCodeError
if !errors.As(err, &statusErr) {
return nil, nil
}
for _, t := range translate {
if t.Status == statusErr.Code {
for _, t := range transforms {
if t.StatusCode == statusErr.Code {
if t.ToError.Code > 0 {
return &proxyproto.Error{
Code: t.ToError.Code,
Expand Down
16 changes: 8 additions & 8 deletions internal/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ import (
"github.com/centrifugal/centrifugo/v5/internal/tools"
)

type TranslateError struct {
type TransformError struct {
Code uint32 `mapstructure:"code" json:"code"`
Message string `mapstructure:"message" json:"message"`
Temporary bool `mapstructure:"temporary" json:"temporary"`
}

type TranslateDisconnect struct {
type TransformDisconnect struct {
Code uint32 `mapstructure:"code" json:"code"`
Reason string `mapstructure:"reason" json:"reason"`
}

type HttpStatusTranslate struct {
Status int `mapstructure:"status" json:"status"`
ToError TranslateError `mapstructure:"to_error" json:"to_error"`
ToDisconnect TranslateDisconnect `mapstructure:"to_disconnect" json:"to_disconnect"`
type HttpStatusToCodeTransform struct {
StatusCode int `mapstructure:"status_code" json:"status_code"`
ToError TransformError `mapstructure:"to_error" json:"to_error"`
ToDisconnect TransformDisconnect `mapstructure:"to_disconnect" json:"to_disconnect"`
}

// Config for proxy.
Expand All @@ -37,8 +37,8 @@ type Config struct {

// HTTPHeaders is a list of HTTP headers to proxy. No headers used by proxy by default.
// If GRPC proxy is used then request HTTP headers set to outgoing request metadata.
HttpHeaders []string `mapstructure:"http_headers" json:"http_headers,omitempty"`
HttpStatusTranslate []HttpStatusTranslate `mapstructure:"http_status_translate" json:"http_status_translate,omitempty"`
HttpHeaders []string `mapstructure:"http_headers" json:"http_headers,omitempty"`
HttpStatusTransforms []HttpStatusToCodeTransform `mapstructure:"http_status_to_code_transforms" json:"http_status_to_code_transforms,omitempty"`

// GRPCMetadata is a list of GRPC metadata keys to proxy. No meta keys used by proxy by
// default. If HTTP proxy is used then these keys become outgoing request HTTP headers.
Expand Down
30 changes: 15 additions & 15 deletions internal/tools/code_translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ import (

type ConnectCodeToHTTPStatus struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
Translates []ConnectCodeToHTTPStatusTranslate `mapstructure:"translates" json:"translates"`
Transforms []ConnectCodeToHTTPStatusTransform `mapstructure:"transforms" json:"transforms"`
}

type ConnectCodeToHTTPStatusTranslate struct {
Code uint32 `mapstructure:"code" json:"code"`
ToStatusCode int `mapstructure:"to_status_code" json:"to_status_code"`
type ConnectCodeToHTTPStatusTransform struct {
Code uint32 `mapstructure:"code" json:"code"`
ToResponse TransformedConnectErrorHttpResponse `mapstructure:"to_response" json:"to_response"`
}

type TranslatedHttpResponse struct {
Status int `json:"status"`
Body []byte `json:"body"`
type TransformedConnectErrorHttpResponse struct {
Status int `mapstructure:"status_code" json:"status_code"`
Body string `mapstructure:"body" json:"body"`
}

func TranslateToHTTPResponse(err error, translates []ConnectCodeToHTTPStatusTranslate) (TranslatedHttpResponse, bool) {
func ConnectErrorToToHTTPResponse(err error, transforms []ConnectCodeToHTTPStatusTransform) (TransformedConnectErrorHttpResponse, bool) {
var code uint32
var body string
switch t := err.(type) {
Expand All @@ -37,18 +37,18 @@ func TranslateToHTTPResponse(err error, translates []ConnectCodeToHTTPStatusTran
default:
}
if code > 0 {
for _, t := range translates {
for _, t := range transforms {
if t.Code != code {
continue
}
return TranslatedHttpResponse{
Status: t.ToStatusCode,
Body: []byte(body),
}, true
if t.ToResponse.Body == "" {
t.ToResponse.Body = body
}
return t.ToResponse, true
}
}
return TranslatedHttpResponse{
return TransformedConnectErrorHttpResponse{
Status: http.StatusInternalServerError,
Body: []byte(http.StatusText(http.StatusInternalServerError)),
Body: http.StatusText(http.StatusInternalServerError),
}, false
}
4 changes: 2 additions & 2 deletions internal/unihttpstream/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

type Config struct {
// MaxRequestBodySize limits request body size.
MaxRequestBodySize int
ConnectCodeTranslates tools.ConnectCodeToHTTPStatus
MaxRequestBodySize int
ConnectCodeToHTTPStatus tools.ConnectCodeToHTTPStatus
centrifuge.PingPongConfig
}
8 changes: 4 additions & 4 deletions internal/unihttpstream/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
connectRequest.Subs = subs
}

if h.config.ConnectCodeTranslates.Enabled {
err = c.ConnectNoDisconnect(connectRequest)
if h.config.ConnectCodeToHTTPStatus.Enabled {
err = c.ConnectNoErrorToDisconnect(connectRequest)
if err != nil {
resp, ok := tools.TranslateToHTTPResponse(err, h.config.ConnectCodeTranslates.Translates)
resp, ok := tools.ConnectErrorToToHTTPResponse(err, h.config.ConnectCodeToHTTPStatus.Transforms)
if ok {
w.WriteHeader(resp.Status)
_, _ = w.Write(resp.Body)
_, _ = w.Write([]byte(resp.Body))
return
}
w.WriteHeader(http.StatusInternalServerError)
Expand Down
4 changes: 2 additions & 2 deletions internal/unisse/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

type Config struct {
// MaxRequestBodySize for POST requests when used.
MaxRequestBodySize int
ConnectCodeTranslates tools.ConnectCodeToHTTPStatus
MaxRequestBodySize int
ConnectCodeToHTTPStatus tools.ConnectCodeToHTTPStatus
centrifuge.PingPongConfig
}
8 changes: 4 additions & 4 deletions internal/unisse/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
connectRequest.Subs = subs
}

if h.config.ConnectCodeTranslates.Enabled {
err = c.ConnectNoDisconnect(connectRequest)
if h.config.ConnectCodeToHTTPStatus.Enabled {
err = c.ConnectNoErrorToDisconnect(connectRequest)
if err != nil {
resp, ok := tools.TranslateToHTTPResponse(err, h.config.ConnectCodeTranslates.Translates)
resp, ok := tools.ConnectErrorToToHTTPResponse(err, h.config.ConnectCodeToHTTPStatus.Transforms)
if ok {
w.WriteHeader(resp.Status)
_, _ = w.Write(resp.Body)
_, _ = w.Write([]byte(resp.Body))
return
}
w.WriteHeader(http.StatusInternalServerError)
Expand Down
89 changes: 44 additions & 45 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,10 @@ var defaults = map[string]any{
"uni_sse": false,
"uni_http_stream": false,

"uni_sse_connect_code_to_http_status.enabled": false,
"uni_sse_connect_code_to_http_status.translates": []any{},
"uni_http_stream_connect_code_to_http_status.enabled": false,
"uni_http_stream_connect_code_to_http_status.translates": []any{},
"uni_sse_connect_code_to_http_response.enabled": false,
"uni_sse_connect_code_to_http_response.transforms": []any{},
"uni_http_stream_connect_code_to_http_response.enabled": false,
"uni_http_stream_connect_code_to_http_response.transforms": []any{},

"log_level": "info",
"log_file": "",
Expand Down Expand Up @@ -296,15 +296,15 @@ var defaults = map[string]any{
"proxy_sub_refresh_timeout": time.Second,
"proxy_subscribe_stream_timeout": time.Second,

"proxy_http_status_translate": []any{},
"proxy_grpc_metadata": []string{},
"proxy_http_headers": []string{},
"proxy_static_http_headers": map[string]string{},
"proxy_binary_encoding": false,
"proxy_include_connection_meta": false,
"proxy_grpc_cert_file": "",
"proxy_grpc_compression": false,
"proxy_grpc_tls": tools.TLSConfig{},
"proxy_http_status_code_transforms": []any{},
"proxy_grpc_metadata": []string{},
"proxy_http_headers": []string{},
"proxy_static_http_headers": map[string]string{},
"proxy_binary_encoding": false,
"proxy_include_connection_meta": false,
"proxy_grpc_cert_file": "",
"proxy_grpc_compression": false,
"proxy_grpc_tls": tools.TLSConfig{},

"tarantool_mode": "standalone",
"tarantool_address": "tcp://127.0.0.1:3301",
Expand Down Expand Up @@ -2071,36 +2071,35 @@ func proxyMapConfig() (*client.ProxyMap, bool) {
}
proxyConfig.StaticHttpHeaders = staticHttpHeaders

var httpStatusTranslate []proxy.HttpStatusTranslate
if v.IsSet("proxy_http_status_translate") {
tools.DecodeSlice(v, &httpStatusTranslate, "proxy_http_status_translate")
var httpStatusTransforms []proxy.HttpStatusToCodeTransform
if v.IsSet("proxy_http_status_code_transforms") {
tools.DecodeSlice(v, &httpStatusTransforms, "proxy_http_status_code_transforms")
}
for _, translate := range httpStatusTranslate {
if translate.Status == 0 {
log.Fatal().Msg("proxy_http_status_translate status should be set")
for _, transform := range httpStatusTransforms {
if transform.StatusCode == 0 {
log.Fatal().Msg("status should be set in proxy_http_status_code_transforms item")
}
if translate.ToDisconnect.Code == 0 && translate.ToError.Code == 0 {
log.Fatal().Msg("no error or disconnect code set in proxy_http_status_translate")
if transform.ToDisconnect.Code == 0 && transform.ToError.Code == 0 {
log.Fatal().Msg("no error or disconnect code set in proxy_http_status_code_transforms item")
}
if translate.ToDisconnect.Code > 0 && translate.ToError.Code > 0 {
log.Fatal().Msg("only error or disconnect code can be set in proxy_http_status_translate, but not both")
if transform.ToDisconnect.Code > 0 && transform.ToError.Code > 0 {
log.Fatal().Msg("only error or disconnect code can be set in proxy_http_status_code_transforms item, but not both")
}
if !tools.IsASCII(translate.ToDisconnect.Reason) {
log.Fatal().Msg("proxy_http_status_translate disconnect reason must be ASCII")
if !tools.IsASCII(transform.ToDisconnect.Reason) {
log.Fatal().Msg("proxy_http_status_code_transforms item disconnect reason must be ASCII")
}
if !tools.IsASCII(translate.ToError.Message) {
log.Fatal().Msg("proxy_http_status_translate error message must be ASCII")
if !tools.IsASCII(transform.ToError.Message) {
log.Fatal().Msg("proxy_http_status_code_transforms item error message must be ASCII")
}
const reasonOrMessageMaxLength = 123 // limit comes from WebSocket close reason length limit. See https://datatracker.ietf.org/doc/html/rfc6455.
if len(translate.ToError.Message) > reasonOrMessageMaxLength {
log.Fatal().Msgf("proxy_http_status_translate error message can be up to %d characters long", reasonOrMessageMaxLength)
if len(transform.ToError.Message) > reasonOrMessageMaxLength {
log.Fatal().Msgf("proxy_http_status_code_transforms item error message can be up to %d characters long", reasonOrMessageMaxLength)
}
if len(translate.ToDisconnect.Reason) > reasonOrMessageMaxLength {
log.Fatal().Msgf("proxy_http_status_translate disconnect reason can be up to %d characters long", reasonOrMessageMaxLength)
if len(transform.ToDisconnect.Reason) > reasonOrMessageMaxLength {
log.Fatal().Msgf("proxy_http_status_code_transforms item disconnect reason can be up to %d characters long", reasonOrMessageMaxLength)
}
}
fmt.Println(httpStatusTranslate)
proxyConfig.HttpStatusTranslate = httpStatusTranslate
proxyConfig.HttpStatusTransforms = httpStatusTransforms

connectEndpoint := v.GetString("proxy_connect_endpoint")
connectTimeout := GetDuration("proxy_connect_timeout")
Expand Down Expand Up @@ -2566,33 +2565,33 @@ func uniWebsocketHandlerConfig() uniws.Config {
}

func uniSSEHandlerConfig() unisse.Config {
connectCodeToHttpStatusEnabled := viper.GetBool("uni_sse_connect_code_to_http_status.enabled")
var connectCodeToHttpStatusTranslates []tools.ConnectCodeToHTTPStatusTranslate
if viper.IsSet("uni_sse_connect_code_to_http_status.translates") {
tools.DecodeSlice(viper.GetViper(), &connectCodeToHttpStatusTranslates, "uni_sse_connect_code_to_http_status.translates")
connectCodeToHttpStatusEnabled := viper.GetBool("uni_sse_connect_code_to_http_response.enabled")
var connectCodeToHTTPStatusTransforms []tools.ConnectCodeToHTTPStatusTransform
if viper.IsSet("uni_sse_connect_code_to_http_response.transforms") {
tools.DecodeSlice(viper.GetViper(), &connectCodeToHTTPStatusTransforms, "uni_sse_connect_code_to_http_response.transforms")
}
return unisse.Config{
MaxRequestBodySize: viper.GetInt("uni_sse_max_request_body_size"),
PingPongConfig: getPingPongConfig(),
ConnectCodeTranslates: tools.ConnectCodeToHTTPStatus{
ConnectCodeToHTTPStatus: tools.ConnectCodeToHTTPStatus{
Enabled: connectCodeToHttpStatusEnabled,
Translates: connectCodeToHttpStatusTranslates,
Transforms: connectCodeToHTTPStatusTransforms,
},
}
}

func uniStreamHandlerConfig() unihttpstream.Config {
connectCodeToHttpStatusEnabled := viper.GetBool("uni_http_stream_connect_code_to_http_status.enabled")
var connectCodeToHttpStatusTranslates []tools.ConnectCodeToHTTPStatusTranslate
if viper.IsSet("uni_http_stream_connect_code_to_http_status.translates") {
tools.DecodeSlice(viper.GetViper(), &connectCodeToHttpStatusTranslates, "uni_http_stream_connect_code_to_http_status.translates")
connectCodeToHttpStatusEnabled := viper.GetBool("uni_http_stream_connect_code_to_http_response.enabled")
var connectCodeToHTTPStatusTransforms []tools.ConnectCodeToHTTPStatusTransform
if viper.IsSet("uni_http_stream_connect_code_to_http_response.transforms") {
tools.DecodeSlice(viper.GetViper(), &connectCodeToHTTPStatusTransforms, "uni_http_stream_connect_code_to_http_response.transforms")
}
return unihttpstream.Config{
MaxRequestBodySize: viper.GetInt("uni_http_stream_max_request_body_size"),
PingPongConfig: getPingPongConfig(),
ConnectCodeTranslates: tools.ConnectCodeToHTTPStatus{
ConnectCodeToHTTPStatus: tools.ConnectCodeToHTTPStatus{
Enabled: connectCodeToHttpStatusEnabled,
Translates: connectCodeToHttpStatusTranslates,
Transforms: connectCodeToHTTPStatusTransforms,
},
}
}
Expand Down

0 comments on commit 7647474

Please sign in to comment.