diff --git a/bin/serve/main.go b/bin/serve/main.go index b0a3e19..7034c58 100644 --- a/bin/serve/main.go +++ b/bin/serve/main.go @@ -133,26 +133,6 @@ func main() { log.Fatalf("While loading configuration got %v", err) } - // If HTTPS is to be used, verify both TLS_* environment variables are set. - if 0 < len(config.Get.TLSCert) || 0 < len(config.Get.TLSKey) { - if 0 == len(config.Get.TLSCert) || 0 == len(config.Get.TLSKey) { - log.Fatalln( - "If value for environment variable 'TLS_CERT' or 'TLS_KEY' is set " + - "then value for environment variable 'TLS_KEY' or 'TLS_CERT' must " + - "also be set.", - ) - } - } - - // If the URL path prefix is to be used, verify it is properly formatted. - if 0 < len(config.Get.URLPrefix) && - (!strings.HasPrefix(config.Get.URLPrefix, "/") || strings.HasSuffix(config.Get.URLPrefix, "/")) { - log.Fatalln( - "Value for environment variable 'URL_PREFIX' must start " + - "with '/' and not end with '/'. Example: '/my/prefix'", - ) - } - // Choose and set the appropriate, optimized static file serving function. var handler http.HandlerFunc if 0 == len(config.Get.URLPrefix) { diff --git a/config/config.go b/config/config.go index 0bcf18e..4e970bc 100644 --- a/config/config.go +++ b/config/config.go @@ -77,8 +77,9 @@ func Load(filename string) (err error) { if err = yaml.Unmarshal(contents, &Get); nil != err { return } + overrideWithEnvVars() - return + return validate() } // overrideWithEnvVars the default values and the configuration file values. @@ -93,6 +94,38 @@ func overrideWithEnvVars() { Get.URLPrefix = envAsStr(urlPrefixKey, Get.URLPrefix) } +// validate the configuration. +func validate() error { + // If HTTPS is to be used, verify both TLS_* environment variables are set. + if 0 < len(Get.TLSCert) || 0 < len(Get.TLSKey) { + if 0 == len(Get.TLSCert) || 0 == len(Get.TLSKey) { + msg := "if value for either 'TLS_CERT' or 'TLS_KEY' is set then " + + "then value for the other must also be set (values are " + + "currently '%s' and '%s', respectively)" + return fmt.Errorf(msg, Get.TLSCert, Get.TLSKey) + } + if _, err := os.Stat(Get.TLSCert); nil != err { + msg := "value of TLS_CERT is set with filename '%s' that returns %v" + return fmt.Errorf(msg, err) + } + if _, err := os.Stat(Get.TLSKey); nil != err { + msg := "value of TLS_KEY is set with filename '%s' that returns %v" + return fmt.Errorf(msg, err) + } + } + + // If the URL path prefix is to be used, verify it is properly formatted. + if 0 < len(Get.URLPrefix) && + (!strings.HasPrefix(Get.URLPrefix, "/") || strings.HasSuffix(Get.URLPrefix, "/")) { + msg := "if value for 'URL_PREFIX' is set then the value must start " + + "with '/' and not end with '/' (current value of '%s' vs valid " + + "example of '/my/prefix'" + return fmt.Errorf(msg, Get.URLPrefix) + } + + return nil +} + // envAsStr returns the value of the environment variable as a string if set. func envAsStr(key, fallback string) string { if value := os.Getenv(key); "" != value { diff --git a/config/config_test.go b/config/config_test.go index af0ac65..1aa9e24 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -135,6 +135,51 @@ func TestOverrideWithEnvvars(t *testing.T) { equalStrings(t, phase, urlPrefixKey, testURLPrefix, Get.URLPrefix) } +func TestValidate(t *testing.T) { + validPath := "config.go" + invalidPath := "should/never/exist.txt" + empty := "" + prefix := "/my/prefix" + + testCases := []struct { + name string + cert string + key string + prefix string + isError bool + }{ + {"Valid paths w/prefix", validPath, validPath, prefix, false}, + {"Valid paths wo/prefix", validPath, validPath, empty, false}, + {"Empty paths w/prefix", empty, empty, prefix, false}, + {"Empty paths wo/prefix", empty, empty, empty, false}, + {"Mixed paths w/prefix", empty, validPath, prefix, true}, + {"Alt mixed paths w/prefix", validPath, empty, prefix, true}, + {"Mixed paths wo/prefix", empty, validPath, empty, true}, + {"Alt mixed paths wo/prefix", validPath, empty, empty, true}, + {"Invalid cert w/prefix", invalidPath, validPath, prefix, true}, + {"Invalid key w/prefix", validPath, invalidPath, prefix, true}, + {"Invalid cert & key w/prefix", invalidPath, invalidPath, prefix, true}, + {"Prefix missing leading /", empty, empty, "my/prefix", true}, + {"Prefix with trailing /", empty, empty, "/my/prefix/", true}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + Get.TLSCert = tc.cert + Get.TLSKey = tc.key + Get.URLPrefix = tc.prefix + err := validate() + hasError := nil != err + if hasError && !tc.isError { + t.Errorf("Expected no error but got %v", err) + } + if !hasError && tc.isError { + t.Error("Expected an error but got no error") + } + }) + } +} + func TestEnvAsStr(t *testing.T) { sv := "STRING_VALUE" fv := "FLOAT_VALUE"