From b998c05ca0b8f44fa703c01ec40ff60a98477b6e Mon Sep 17 00:00:00 2001 From: Deluan Date: Sun, 26 Mar 2023 21:26:55 -0400 Subject: [PATCH] Some refactorings --- server/middlewares.go | 17 ++------- server/server.go | 2 +- server/subsonic/middlewares.go | 2 +- utils/gg/gg.go | 22 ++++++++++-- utils/gg/gg_test.go | 66 +++++++++++++++++++++------------- 5 files changed, 66 insertions(+), 43 deletions(-) diff --git a/server/middlewares.go b/server/middlewares.go index 17f63e41c..cdbefacb8 100644 --- a/server/middlewares.go +++ b/server/middlewares.go @@ -135,7 +135,7 @@ func clientUniqueIDMiddleware(next http.Handler) http.Handler { HttpOnly: true, Secure: true, SameSite: http.SameSiteStrictMode, - Path: IfZero(conf.Server.BasePath, "/"), + Path: If(conf.Server.BasePath, "/"), } http.SetCookie(w, c) } else { @@ -210,11 +210,11 @@ func serverAddress(r *http.Request) (scheme, host string) { } xfh = xfh[:i] } - host = firstOr(r.Host, xfh) + host = FirstOr(r.Host, xfh) // Determine the protocol and scheme of the request based on the presence of // X-Forwarded-* headers or the scheme of the request URL. - scheme = firstOr( + scheme = FirstOr( protocol, r.Header.Get(xForwardedProto), r.Header.Get(xForwardedScheme), @@ -231,17 +231,6 @@ func serverAddress(r *http.Request) (scheme, host string) { return scheme, host } -// firstOr is a helper function that returns the first non-empty string from a list -// of strings, or a default value if all the strings are empty. -func firstOr(or string, strings ...string) string { - for _, s := range strings { - if s != "" { - return s - } - } - return or -} - // URLParamsMiddleware is a middleware function that decodes the query string of // the incoming HTTP request, adds the URL parameters from the routing context, // and re-encodes the modified query string. diff --git a/server/server.go b/server/server.go index 275ce761b..2dbf8f153 100644 --- a/server/server.go +++ b/server/server.go @@ -171,7 +171,7 @@ func AbsoluteURL(r *http.Request, u string, params url.Values) string { if strings.HasPrefix(u, "/") { buildUrl.Path = path.Join(conf.Server.BasePath, buildUrl.Path) if conf.Server.BaseHost != "" { - buildUrl.Scheme = IfZero(conf.Server.BaseScheme, "http") + buildUrl.Scheme = If(conf.Server.BaseScheme, "http") buildUrl.Host = conf.Server.BaseHost } else { buildUrl.Scheme = r.URL.Scheme diff --git a/server/subsonic/middlewares.go b/server/subsonic/middlewares.go index 4a6ea1a35..1efe61663 100644 --- a/server/subsonic/middlewares.go +++ b/server/subsonic/middlewares.go @@ -166,7 +166,7 @@ func getPlayer(players core.Players) func(next http.Handler) http.Handler { MaxAge: consts.CookieExpiry, HttpOnly: true, SameSite: http.SameSiteStrictMode, - Path: IfZero(conf.Server.BasePath, "/"), + Path: If(conf.Server.BasePath, "/"), } http.SetCookie(w, cookie) } diff --git a/utils/gg/gg.go b/utils/gg/gg.go index e5cb88124..6da9082a1 100644 --- a/utils/gg/gg.go +++ b/utils/gg/gg.go @@ -1,14 +1,32 @@ // Package gg implements simple "extensions" to Go language. Based on https://github.com/icza/gog package gg -// IfZero returns v if it is a non-zero value, orElse otherwise. +// If returns v if it is a non-zero value, orElse otherwise. // // This is similar to elvis operator (?:) in Groovy and other languages. // Note: Different from the real elvis operator, the orElse expression will always get evaluated. -func IfZero[T comparable](v T, orElse T) T { +func If[T comparable](v T, orElse T) T { var zero T if v != zero { return v } return orElse } + +// FirstOr is a generic helper function that returns the first non-zero value from +// a list of comparable values, or a default value if all the values are zero. +func FirstOr[T comparable](or T, values ...T) T { + // Initialize a zero value of the same type as the input values. + var zero T + + // Loop through each input value and check if it is non-zero. If a non-zero value + // is found, return it immediately. + for _, v := range values { + if v != zero { + return v + } + } + + // If all the input values are zero, return the default value. + return or +} diff --git a/utils/gg/gg_test.go b/utils/gg/gg_test.go index 59e460827..e492fae9d 100644 --- a/utils/gg/gg_test.go +++ b/utils/gg/gg_test.go @@ -15,29 +15,45 @@ func TestGG(t *testing.T) { RunSpecs(t, "GG Suite") } -var _ = Describe("IfZero", func() { - DescribeTable("string", - func(v, orElse, expected string) { - Expect(gg.IfZero(v, orElse)).To(Equal(expected)) - }, - Entry("zero value", "", "default", "default"), - Entry("non-zero value", "anything", "default", "anything"), - ) - DescribeTable("numeric", - func(v, orElse, expected int) { - Expect(gg.IfZero(v, orElse)).To(Equal(expected)) - }, - Entry("zero value", 0, 2, 2), - Entry("non-zero value", -1, 2, -1), - ) - type testStruct struct { - field1 int - } - DescribeTable("struct", - func(v, orElse, expected testStruct) { - Expect(gg.IfZero(v, orElse)).To(Equal(expected)) - }, - Entry("zero value", testStruct{}, testStruct{123}, testStruct{123}), - Entry("non-zero value", testStruct{456}, testStruct{123}, testStruct{456}), - ) +var _ = Describe("GG", func() { + Describe("If", func() { + DescribeTable("string", + func(v, orElse, expected string) { + Expect(gg.If(v, orElse)).To(Equal(expected)) + }, + Entry("zero value", "", "default", "default"), + Entry("non-zero value", "anything", "default", "anything"), + ) + DescribeTable("numeric", + func(v, orElse, expected int) { + Expect(gg.If(v, orElse)).To(Equal(expected)) + }, + Entry("zero value", 0, 2, 2), + Entry("non-zero value", -1, 2, -1), + ) + type testStruct struct { + field1 int + } + DescribeTable("struct", + func(v, orElse, expected testStruct) { + Expect(gg.If(v, orElse)).To(Equal(expected)) + }, + Entry("zero value", testStruct{}, testStruct{123}, testStruct{123}), + Entry("non-zero value", testStruct{456}, testStruct{123}, testStruct{456}), + ) + }) + + Describe("FirstOr", func() { + Context("when given a list of strings", func() { + It("returns the first non-empty value", func() { + Expect(gg.FirstOr("default", "foo", "bar", "baz")).To(Equal("foo")) + Expect(gg.FirstOr("default", "", "", "qux")).To(Equal("qux")) + }) + + It("returns the default value if all values are empty", func() { + Expect(gg.FirstOr("default", "", "", "")).To(Equal("default")) + Expect(gg.FirstOr("", "", "", "")).To(Equal("")) + }) + }) + }) })