Linter and Drone config fixes, code linting.
This commit is contained in:
		| @@ -21,8 +21,7 @@ steps: | ||||
|   - name: docker | ||||
|     image: plugins/docker | ||||
|     when: | ||||
|       branch: | ||||
|         master | ||||
|       branch: ["master"] | ||||
|     settings: | ||||
|       username: | ||||
|         from_secret: dockerhub_user | ||||
|   | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| *DS_Store* | ||||
| data/* | ||||
| .idea | ||||
| .vscode | ||||
|   | ||||
| @@ -15,6 +15,12 @@ linters: | ||||
| linters-settings: | ||||
|   lll: | ||||
|     line-length: 420 | ||||
|   gocyclo: | ||||
|     min-complexity: 40 | ||||
|    | ||||
|   cyclop: | ||||
|     max-complexity: 25 | ||||
|  | ||||
| issues: | ||||
|   exclude-rules: | ||||
|     # There will be some ToDos. | ||||
|     - linters: | ||||
|         - godox | ||||
|       text: "TODO" | ||||
|   | ||||
| @@ -1,15 +1,11 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"os" | ||||
|  | ||||
| 	// local | ||||
| 	"github.com/teris-io/cli" | ||||
| 	clientv1 "go.dev.pztrn.name/giredore/domains/client/v1" | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/teris-io/cli" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| @@ -34,6 +30,7 @@ func main() { | ||||
| 							logger.Initialize() | ||||
| 							clientv1.Initialize() | ||||
| 							clientv1.SetAllowedIPs(args, options) | ||||
|  | ||||
| 							return 0 | ||||
| 						}), | ||||
| 				), | ||||
|   | ||||
| @@ -1,12 +1,10 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"syscall" | ||||
|  | ||||
| 	// local | ||||
| 	serverv1 "go.dev.pztrn.name/giredore/domains/server/v1" | ||||
| 	"go.dev.pztrn.name/giredore/internal/configuration" | ||||
| 	"go.dev.pztrn.name/giredore/internal/httpserver" | ||||
|   | ||||
| @@ -1,10 +1,8 @@ | ||||
| package clientv1 | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"strings" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/giredore/internal/requester" | ||||
| 	"go.dev.pztrn.name/giredore/internal/structs" | ||||
| ) | ||||
|   | ||||
| @@ -1,17 +1,12 @@ | ||||
| package clientv1 | ||||
|  | ||||
| import ( | ||||
| 	// local | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
| 	"go.dev.pztrn.name/giredore/internal/requester" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/rs/zerolog" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	log zerolog.Logger | ||||
| ) | ||||
| var log zerolog.Logger | ||||
|  | ||||
| func Initialize() { | ||||
| 	log = logger.Logger.With().Str("type", "domain").Str("package", "client").Int("version", 1).Logger() | ||||
|   | ||||
| @@ -1,10 +1,8 @@ | ||||
| package clientv1 | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"strings" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/giredore/internal/requester" | ||||
| 	"go.dev.pztrn.name/giredore/internal/structs" | ||||
| ) | ||||
| @@ -29,6 +27,7 @@ func DeletePackage(args []string, options map[string]string) { | ||||
| func GetPackages(args []string, options map[string]string) { | ||||
| 	pkgs := strings.Split(args[0], ",") | ||||
|  | ||||
| 	// nolint:exhaustivestruct | ||||
| 	req := &structs.PackageGetRequest{} | ||||
| 	if pkgs[0] == "all" { | ||||
| 		req.All = true | ||||
|   | ||||
| @@ -1,32 +1,32 @@ | ||||
| package serverv1 | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"net/http" | ||||
|  | ||||
| 	// local | ||||
| 	"github.com/labstack/echo" | ||||
| 	"go.dev.pztrn.name/giredore/internal/configuration" | ||||
| 	"go.dev.pztrn.name/giredore/internal/structs" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/labstack/echo" | ||||
| ) | ||||
|  | ||||
| // This function responsible for getting runtime configuration. | ||||
| func configurationGET(ec echo.Context) error { | ||||
| 	// nolint:wrapcheck | ||||
| 	return ec.JSON(http.StatusOK, configuration.Cfg) | ||||
| } | ||||
|  | ||||
| func configurationAllowedIPsSET(ec echo.Context) error { | ||||
| func configurationAllowedIPsSET(ectx echo.Context) error { | ||||
| 	// nolint:exhaustivestruct | ||||
| 	req := &structs.AllowedIPsSetRequest{} | ||||
| 	if err := ec.Bind(req); err != nil { | ||||
| 	if err := ectx.Bind(req); err != nil { | ||||
| 		log.Error().Err(err).Msg("Failed to parse allowed IPs set request") | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrParsingAllowedIPsSetRequest}}) | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrParsingAllowedIPsSetRequest}}) | ||||
| 	} | ||||
|  | ||||
| 	log.Debug().Msgf("Got set allowed IPs request: %+v", req) | ||||
|  | ||||
| 	configuration.Cfg.SetAllowedIPs(req.AllowedIPs) | ||||
|  | ||||
| 	return ec.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess}) | ||||
| 	// nolint:exhaustivestruct,wrapcheck | ||||
| 	return ectx.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess}) | ||||
| } | ||||
|   | ||||
| @@ -1,17 +1,12 @@ | ||||
| package serverv1 | ||||
|  | ||||
| import ( | ||||
| 	// local | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"go.dev.pztrn.name/giredore/internal/httpserver" | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/rs/zerolog" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	log zerolog.Logger | ||||
| ) | ||||
| var log zerolog.Logger | ||||
|  | ||||
| func Initialize() { | ||||
| 	log = logger.Logger.With().Str("type", "domain").Str("package", "server").Int("version", 1).Logger() | ||||
|   | ||||
| @@ -1,43 +1,43 @@ | ||||
| package serverv1 | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	// local | ||||
| 	"github.com/labstack/echo" | ||||
| 	"go.dev.pztrn.name/giredore/internal/configuration" | ||||
| 	"go.dev.pztrn.name/giredore/internal/structs" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/labstack/echo" | ||||
| ) | ||||
|  | ||||
| func throwGoImports(ec echo.Context) error { | ||||
| func throwGoImports(ectx echo.Context) error { | ||||
| 	// Getting real path. This might be the package itself, or namespace | ||||
| 	// to list available packages. | ||||
| 	// For now only package itself is supported, all other features in ToDo. | ||||
| 	packageNameRaw := ec.Request().URL.Path | ||||
| 	packageNameRaw := ectx.Request().URL.Path | ||||
|  | ||||
| 	pkgs, errs := configuration.Cfg.GetPackagesInfo([]string{packageNameRaw}) | ||||
|  | ||||
| 	if errs != nil { | ||||
| 		log.Error().Str("package", packageNameRaw).Msgf("Failed to get package information: %+v", errs) | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: errs}) | ||||
|  | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: errs}) | ||||
| 	} | ||||
|  | ||||
| 	if len(pkgs) == 0 { | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrNoPackagesFound}}) | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrNoPackagesFound}}) | ||||
| 	} | ||||
|  | ||||
| 	pkg, found := pkgs[packageNameRaw] | ||||
| 	if !found { | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrNoPackagesFound}}) | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrNoPackagesFound}}) | ||||
| 	} | ||||
|  | ||||
| 	// We should compose package name using our domain under which giredore | ||||
| 	// is working. | ||||
| 	domain := ec.Request().Host | ||||
| 	domain := ectx.Request().Host | ||||
| 	packageName := domain + packageNameRaw | ||||
|  | ||||
| 	tmpl := singlePackageTemplate | ||||
| @@ -45,5 +45,6 @@ func throwGoImports(ec echo.Context) error { | ||||
| 	tmpl = strings.Replace(tmpl, "{VCS}", pkg.VCS, 1) | ||||
| 	tmpl = strings.Replace(tmpl, "{REPOPATH}", pkg.RealPath, 1) | ||||
|  | ||||
| 	return ec.HTML(http.StatusOK, tmpl) | ||||
| 	// nolint:wrapcheck | ||||
| 	return ectx.HTML(http.StatusOK, tmpl) | ||||
| } | ||||
|   | ||||
| @@ -1,24 +1,23 @@ | ||||
| package serverv1 | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	// local | ||||
| 	"github.com/labstack/echo" | ||||
| 	"go.dev.pztrn.name/giredore/internal/configuration" | ||||
| 	"go.dev.pztrn.name/giredore/internal/structs" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/labstack/echo" | ||||
| ) | ||||
|  | ||||
| // This function responsible for getting packages configuration. | ||||
| func packagesGET(ec echo.Context) error { | ||||
| func packagesGET(ectx echo.Context) error { | ||||
| 	// nolint:exhaustivestruct | ||||
| 	req := &structs.PackageGetRequest{} | ||||
| 	if err := ec.Bind(req); err != nil { | ||||
| 	if err := ectx.Bind(req); err != nil { | ||||
| 		log.Error().Err(err).Msg("Failed to parse package get request") | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrParsingPackagesGetRequest}}) | ||||
|  | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrParsingPackagesGetRequest}}) | ||||
| 	} | ||||
|  | ||||
| 	log.Info().Msgf("Received package(s) info get request: %+v", req) | ||||
| @@ -34,18 +33,23 @@ func packagesGET(ec echo.Context) error { | ||||
| 	} | ||||
|  | ||||
| 	if len(errors) > 0 { | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: errors, Data: pkgs}) | ||||
| 		// nolint:wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: errors, Data: pkgs}) | ||||
| 	} | ||||
|  | ||||
| 	return ec.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess, Data: pkgs}) | ||||
| 	// nolint:exhaustivestruct,wrapcheck | ||||
| 	return ectx.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess, Data: pkgs}) | ||||
| } | ||||
|  | ||||
| // This function responsible for deleting package. | ||||
| func packagesDELETE(ec echo.Context) error { | ||||
| func packagesDELETE(ectx echo.Context) error { | ||||
| 	// nolint:exhaustivestruct | ||||
| 	req := &structs.PackageDeleteRequest{} | ||||
| 	if err := ec.Bind(req); err != nil { | ||||
| 	if err := ectx.Bind(req); err != nil { | ||||
| 		log.Error().Err(err).Msg("Failed to parse package delete request") | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrParsingDeleteRequest}}) | ||||
|  | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrParsingDeleteRequest}}) | ||||
| 	} | ||||
|  | ||||
| 	log.Info().Msgf("Received package delete request: %+v", req) | ||||
| @@ -53,28 +57,35 @@ func packagesDELETE(ec echo.Context) error { | ||||
| 	errs := configuration.Cfg.DeletePackage(req) | ||||
|  | ||||
| 	if len(errs) > 0 { | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: errs}) | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: errs}) | ||||
| 	} | ||||
|  | ||||
| 	return ec.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess}) | ||||
| 	// nolint:exhaustivestruct,wrapcheck | ||||
| 	return ectx.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess}) | ||||
| } | ||||
|  | ||||
| // This function responsible for setting or updating packages. | ||||
| func packagesSET(ec echo.Context) error { | ||||
| func packagesSET(ectx echo.Context) error { | ||||
| 	// nolint:exhaustivestruct | ||||
| 	req := &structs.Package{} | ||||
| 	if err := ec.Bind(req); err != nil { | ||||
| 	if err := ectx.Bind(req); err != nil { | ||||
| 		log.Error().Err(err).Msg("Failed to parse package data") | ||||
| 		return ec.JSON(http.StatusBadRequest, nil) | ||||
|  | ||||
| 		// nolint:wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, nil) | ||||
| 	} | ||||
|  | ||||
| 	log.Info().Msgf("Received package set/update request: %+v", req) | ||||
|  | ||||
| 	// Validate passed package data. | ||||
| 	if !strings.HasPrefix(req.OriginalPath, "/") { | ||||
| 		return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrPackageOrigPathShouldStartWithSlash}}) | ||||
| 		// nolint:exhaustivestruct,wrapcheck | ||||
| 		return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrPackageOrigPathShouldStartWithSlash}}) | ||||
| 	} | ||||
|  | ||||
| 	configuration.Cfg.AddOrUpdatePackage(req) | ||||
|  | ||||
| 	return ec.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess}) | ||||
| 	// nolint:exhaustivestruct,wrapcheck | ||||
| 	return ectx.JSON(http.StatusOK, &structs.Reply{Status: structs.StatusSuccess}) | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package configuration | ||||
|  | ||||
| import ( | ||||
| 	// other | ||||
| 	"github.com/vrischmann/envconfig" | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,8 @@ | ||||
| package configuration | ||||
|  | ||||
| import ( | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -19,9 +16,11 @@ func Initialize() { | ||||
| 	log = logger.Logger.With().Str("type", "internal").Str("package", "configuration").Logger() | ||||
| 	log.Info().Msg("Initializing...") | ||||
|  | ||||
| 	// nolint:exhaustivestruct | ||||
| 	envCfg = &envConfig{} | ||||
| 	envCfg.Initialize() | ||||
|  | ||||
| 	// nolint:exhaustivestruct | ||||
| 	Cfg = &fileConfig{} | ||||
| 	Cfg.Initialize() | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package configuration | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"encoding/json" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| @@ -9,7 +8,6 @@ import ( | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/giredore/internal/structs" | ||||
| ) | ||||
|  | ||||
| @@ -19,22 +17,22 @@ import ( | ||||
| // may be accesses concurrently. In other words DO NOT USE EXPORTED FIELDS | ||||
| // DIRECTLY! | ||||
| type fileConfig struct { | ||||
| 	packagesMutex sync.RWMutex | ||||
| 	// Packages describes packages mapping. | ||||
| 	Packages map[string]*structs.Package | ||||
| 	// HTTP describes HTTP server configuration. | ||||
| 	HTTP struct { | ||||
| 		// AllowedIPs is a list of IPs that allowed to access API. | ||||
| 		// There might be other authentication implemented in future. | ||||
| 		AllowedIPs      []string | ||||
| 		allowedipsmutex sync.RWMutex | ||||
| 		// Listen is an address on which HTTP server will listen. | ||||
| 		Listen string | ||||
| 		// AllowedIPs is a list of IPs that allowed to access API. | ||||
| 		// There might be other authentication implemented in future. | ||||
| 		AllowedIPs []string | ||||
| 		// WaitForSeconds is a timeout during which we will wait for | ||||
| 		// HTTP server be up. If timeout will pass and HTTP server won't | ||||
| 		// start processing requests - giredore will exit. | ||||
| 		WaitForSeconds int | ||||
| 	} | ||||
| 	// Packages describes packages mapping. | ||||
| 	Packages      map[string]*structs.Package | ||||
| 	packagesMutex sync.RWMutex | ||||
| } | ||||
|  | ||||
| func (fc *fileConfig) AddOrUpdatePackage(pkg *structs.Package) { | ||||
| @@ -52,6 +50,7 @@ func (fc *fileConfig) DeletePackage(req *structs.PackageDeleteRequest) []structs | ||||
|  | ||||
| 	if !found { | ||||
| 		errors = append(errors, structs.ErrPackageWasntDefined) | ||||
|  | ||||
| 		return errors | ||||
| 	} | ||||
|  | ||||
| @@ -116,6 +115,7 @@ func (fc *fileConfig) Initialize() { | ||||
| 	// exists. | ||||
| 	if _, err2 := os.Stat(configPath); os.IsNotExist(err2) { | ||||
| 		cfgLoadLog.Error().Msg("Unable to load configuration from filesystem.") | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -141,6 +141,7 @@ func (fc *fileConfig) Initialize() { | ||||
| 	for _, ip := range fc.HTTP.AllowedIPs { | ||||
| 		if strings.Contains(ip, "127.0.0.1") { | ||||
| 			localhostIsAllowed = true | ||||
|  | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| @@ -163,6 +164,7 @@ func (fc *fileConfig) normalizePath(configPath string) (string, error) { | ||||
| 	if strings.Contains(configPath, "~") { | ||||
| 		homeDir, err := os.UserHomeDir() | ||||
| 		if err != nil { | ||||
| 			// nolint:wrapcheck | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| @@ -171,6 +173,7 @@ func (fc *fileConfig) normalizePath(configPath string) (string, error) { | ||||
|  | ||||
| 	absPath, err1 := filepath.Abs(configPath) | ||||
| 	if err1 != nil { | ||||
| 		// nolint:wrapcheck | ||||
| 		return "", err1 | ||||
| 	} | ||||
|  | ||||
| @@ -186,6 +189,7 @@ func (fc *fileConfig) Save() { | ||||
| 	data, err := json.Marshal(fc) | ||||
| 	if err != nil { | ||||
| 		cfgSaveLog.Fatal().Err(err).Msg("Failed to encode data into JSON. Configuration file won't be saved!") | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -1,26 +1,21 @@ | ||||
| package httpserver | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	// local | ||||
| 	"github.com/labstack/echo" | ||||
| 	"go.dev.pztrn.name/giredore/internal/configuration" | ||||
| 	"go.dev.pztrn.name/giredore/internal/structs" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/labstack/echo" | ||||
| ) | ||||
|  | ||||
| func checkAllowedIPs() echo.MiddlewareFunc { | ||||
| 	return func(next echo.HandlerFunc) echo.HandlerFunc { | ||||
| 		return func(ec echo.Context) error { | ||||
| 		return func(ectx echo.Context) error { | ||||
| 			// Do nothing if request came not in "/_api" namespace. | ||||
| 			if !strings.HasPrefix(ec.Request().RequestURI, "/_api") { | ||||
| 				_ = next(ec) | ||||
| 				return nil | ||||
| 			if !strings.HasPrefix(ectx.Request().RequestURI, "/_api") { | ||||
| 				return next(ectx) | ||||
| 			} | ||||
|  | ||||
| 			// Get IPs and subnets from configuration and parse them | ||||
| @@ -39,7 +34,9 @@ func checkAllowedIPs() echo.MiddlewareFunc { | ||||
| 				_, net, err := net.ParseCIDR(ipToParse) | ||||
| 				if err != nil { | ||||
| 					log.Error().Err(err).Str("subnet", ipToParse).Msg("Failed to parse CIDR. /_api/ endpoint won't be accessible, this should be fixed manually in configuration file!") | ||||
| 					return ec.JSON(http.StatusInternalServerError, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrInvalidAllowedIPDefined}}) | ||||
|  | ||||
| 					// nolint:exhaustivestruct,wrapcheck | ||||
| 					return ectx.JSON(http.StatusInternalServerError, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrInvalidAllowedIPDefined}}) | ||||
| 				} | ||||
|  | ||||
| 				subnets = append(subnets, net) | ||||
| @@ -47,23 +44,24 @@ func checkAllowedIPs() echo.MiddlewareFunc { | ||||
|  | ||||
| 			// Check if requester's IP address are within allowed IP | ||||
| 			// subnets. | ||||
| 			ipToCheck := net.ParseIP(ec.RealIP()) | ||||
| 			ipToCheck := net.ParseIP(ectx.RealIP()) | ||||
|  | ||||
| 			var allowed bool | ||||
|  | ||||
| 			for _, subnet := range subnets { | ||||
| 				if subnet.Contains(ipToCheck) { | ||||
| 					allowed = true | ||||
|  | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if allowed { | ||||
| 				_ = next(ec) | ||||
| 				return nil | ||||
| 				return next(ectx) | ||||
| 			} | ||||
|  | ||||
| 			return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrIPAddressNotAllowed}}) | ||||
| 			// nolint:exhaustivestruct,wrapcheck | ||||
| 			return ectx.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: []structs.Error{structs.ErrIPAddressNotAllowed}}) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,21 +1,17 @@ | ||||
| package httpserver | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"context" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/giredore/internal/configuration" | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/labstack/echo" | ||||
| 	"github.com/labstack/echo/middleware" | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"go.dev.pztrn.name/giredore/internal/configuration" | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -66,6 +62,7 @@ func Start() { | ||||
| 	}() | ||||
|  | ||||
| 	// Check that HTTP server was started. | ||||
| 	// nolint:exhaustivestruct | ||||
| 	httpc := &http.Client{Timeout: time.Second * 1} | ||||
| 	checks := 0 | ||||
|  | ||||
| @@ -78,9 +75,17 @@ func Start() { | ||||
|  | ||||
| 		time.Sleep(time.Second * 1) | ||||
|  | ||||
| 		resp, err := httpc.Get("http://" + configuration.Cfg.HTTP.Listen + "/_internal/waitForOnline") | ||||
| 		localCtx, cancelFunc := context.WithTimeout(context.Background(), time.Second*1) | ||||
|  | ||||
| 		req, err := http.NewRequestWithContext(localCtx, "GET", "http://"+configuration.Cfg.HTTP.Listen+"/_internal/waitForOnline", nil) | ||||
| 		if err != nil { | ||||
| 			log.Panic().Err(err).Msg("Failed to create HTTP request!") | ||||
| 		} | ||||
|  | ||||
| 		resp, err := httpc.Do(req) | ||||
| 		if err != nil { | ||||
| 			log.Debug().Err(err).Msg("HTTP error occurred, HTTP server isn't ready, waiting...") | ||||
|  | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -89,6 +94,7 @@ func Start() { | ||||
|  | ||||
| 		if err != nil { | ||||
| 			log.Debug().Err(err).Msg("Failed to read response body, HTTP server isn't ready, waiting...") | ||||
|  | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -97,23 +103,29 @@ func Start() { | ||||
| 		if resp.StatusCode == http.StatusOK { | ||||
| 			if len(response) == 0 { | ||||
| 				log.Debug().Msg("Response is empty, HTTP server isn't ready, waiting...") | ||||
|  | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			log.Debug().Int("status code", resp.StatusCode).Msgf("Response: %+v", string(response)) | ||||
|  | ||||
| 			if len(response) == 17 { | ||||
| 				// This is useless context cancel function call. Thanks to lostcancel linter. | ||||
| 				cancelFunc() | ||||
|  | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	log.Info().Msg("HTTP server is ready to process requests") | ||||
| } | ||||
|  | ||||
| func waitForHTTPServerToBeUpHandler(ec echo.Context) error { | ||||
| func waitForHTTPServerToBeUpHandler(ectx echo.Context) error { | ||||
| 	response := map[string]string{ | ||||
| 		"error": "None", | ||||
| 	} | ||||
|  | ||||
| 	return ec.JSON(200, response) | ||||
| 	// nolint:wrapcheck | ||||
| 	return ectx.JSON(200, response) | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| package httpserver | ||||
|  | ||||
| import ( | ||||
| 	// other | ||||
|  | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/labstack/echo" | ||||
| @@ -10,18 +8,18 @@ import ( | ||||
|  | ||||
| func requestLogger() echo.MiddlewareFunc { | ||||
| 	return func(next echo.HandlerFunc) echo.HandlerFunc { | ||||
| 		return func(ec echo.Context) error { | ||||
| 		return func(ectx echo.Context) error { | ||||
| 			startTime := time.Now() | ||||
|  | ||||
| 			err := next(ec) | ||||
| 			err := next(ectx) | ||||
|  | ||||
| 			log.Info(). | ||||
| 				Str("From", ec.RealIP()). | ||||
| 				Str("To", ec.Request().Host). | ||||
| 				Str("Method", ec.Request().Method). | ||||
| 				Str("Path", ec.Request().URL.Path). | ||||
| 				Int64("Length", ec.Request().ContentLength). | ||||
| 				Str("UA", ec.Request().UserAgent()). | ||||
| 				Str("From", ectx.RealIP()). | ||||
| 				Str("To", ectx.Request().Host). | ||||
| 				Str("Method", ectx.Request().Method). | ||||
| 				Str("Path", ectx.Request().URL.Path). | ||||
| 				Int64("Length", ectx.Request().ContentLength). | ||||
| 				Str("UA", ectx.Request().UserAgent()). | ||||
| 				TimeDiff("TimeMS", time.Now(), startTime). | ||||
| 				Msg("HTTP request") | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,10 @@ | ||||
| package httpserver | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/labstack/echo" | ||||
| ) | ||||
|  | ||||
| @@ -15,7 +13,7 @@ import ( | ||||
| type StrictJSONBinder struct{} | ||||
|  | ||||
| // Bind parses JSON input. | ||||
| func (sjb *StrictJSONBinder) Bind(i interface{}, c echo.Context) error { | ||||
| func (sjb *StrictJSONBinder) Bind(data interface{}, c echo.Context) error { | ||||
| 	req := c.Request() | ||||
| 	if req.ContentLength == 0 { | ||||
| 		return echo.NewHTTPError(http.StatusBadRequest, "Request body can't be empty") | ||||
| @@ -25,7 +23,9 @@ func (sjb *StrictJSONBinder) Bind(i interface{}, c echo.Context) error { | ||||
| 	decoder := json.NewDecoder(req.Body) | ||||
| 	decoder.DisallowUnknownFields() | ||||
|  | ||||
| 	if err := decoder.Decode(i); err != nil { | ||||
| 	// ToDo: rework this code. | ||||
| 	// nolint:errorlint | ||||
| 	if err := decoder.Decode(data); err != nil { | ||||
| 		if ute, ok := err.(*json.UnmarshalTypeError); ok { | ||||
| 			return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, field=%v, offset=%v", ute.Type, ute.Value, ute.Field, ute.Offset)) | ||||
| 		} else if se, ok := err.(*json.SyntaxError); ok { | ||||
|   | ||||
| @@ -1,13 +1,11 @@ | ||||
| package logger | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/rs/zerolog" | ||||
| ) | ||||
|  | ||||
| @@ -17,6 +15,7 @@ var ( | ||||
| ) | ||||
|  | ||||
| // Initialize initializes zerolog with proper formatting and log level. | ||||
| // nolint:forbidigo | ||||
| func Initialize() { | ||||
| 	// Check environment for logger level. | ||||
| 	// Defaulting to INFO. | ||||
| @@ -45,27 +44,28 @@ func Initialize() { | ||||
| 		zerolog.SetGlobalLevel(zerolog.InfoLevel) | ||||
| 	} | ||||
|  | ||||
| 	// nolint:exhaustivestruct | ||||
| 	output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: time.RFC3339} | ||||
| 	output.FormatLevel = func(i interface{}) string { | ||||
| 	output.FormatLevel = func(lvlRaw interface{}) string { | ||||
| 		var v string | ||||
|  | ||||
| 		if ii, ok := i.(string); ok { | ||||
| 			ii = strings.ToUpper(ii) | ||||
| 			switch ii { | ||||
| 		if lvl, ok := lvlRaw.(string); ok { | ||||
| 			lvl = strings.ToUpper(lvl) | ||||
| 			switch lvl { | ||||
| 			case "DEBUG": | ||||
| 				v = fmt.Sprintf("\x1b[30m%-5s\x1b[0m", ii) | ||||
| 				v = fmt.Sprintf("\x1b[30m%-5s\x1b[0m", lvl) | ||||
| 			case "ERROR": | ||||
| 				v = fmt.Sprintf("\x1b[31m%-5s\x1b[0m", ii) | ||||
| 				v = fmt.Sprintf("\x1b[31m%-5s\x1b[0m", lvl) | ||||
| 			case "FATAL": | ||||
| 				v = fmt.Sprintf("\x1b[35m%-5s\x1b[0m", ii) | ||||
| 				v = fmt.Sprintf("\x1b[35m%-5s\x1b[0m", lvl) | ||||
| 			case "INFO": | ||||
| 				v = fmt.Sprintf("\x1b[32m%-5s\x1b[0m", ii) | ||||
| 				v = fmt.Sprintf("\x1b[32m%-5s\x1b[0m", lvl) | ||||
| 			case "PANIC": | ||||
| 				v = fmt.Sprintf("\x1b[36m%-5s\x1b[0m", ii) | ||||
| 				v = fmt.Sprintf("\x1b[36m%-5s\x1b[0m", lvl) | ||||
| 			case "WARN": | ||||
| 				v = fmt.Sprintf("\x1b[33m%-5s\x1b[0m", ii) | ||||
| 				v = fmt.Sprintf("\x1b[33m%-5s\x1b[0m", lvl) | ||||
| 			default: | ||||
| 				v = ii | ||||
| 				v = lvl | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -1,22 +1,17 @@ | ||||
| package requester | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
|  | ||||
| 	// local | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
|  | ||||
| 	// other | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"go.dev.pztrn.name/giredore/internal/logger" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	log zerolog.Logger | ||||
| ) | ||||
| var log zerolog.Logger | ||||
|  | ||||
| func Initialize() { | ||||
| 	log = logger.Logger.With().Str("type", "internal").Str("package", "requester").Logger() | ||||
| @@ -27,6 +22,7 @@ func Delete(url string, data interface{}) ([]byte, error) { | ||||
| 	return execRequest("DELETE", url, data) | ||||
| } | ||||
|  | ||||
| // nolint:wrapcheck | ||||
| func execRequest(method string, url string, data interface{}) ([]byte, error) { | ||||
| 	log.Debug().Str("method", method).Str("URL", url).Msg("Trying to execute HTTP request...") | ||||
|  | ||||
| @@ -38,7 +34,7 @@ func execRequest(method string, url string, data interface{}) ([]byte, error) { | ||||
| 	} | ||||
|  | ||||
| 	// Compose HTTP request. | ||||
| 	httpReq, err := http.NewRequest(method, url, bytes.NewReader(dataToSend)) | ||||
| 	httpReq, err := http.NewRequestWithContext(context.Background(), method, url, bytes.NewReader(dataToSend)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| package requester | ||||
|  | ||||
| import ( | ||||
| 	// stdlib | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // nolint:exhaustivestruct | ||||
| func getHTTPClient() *http.Client { | ||||
| 	c := &http.Client{ | ||||
| 	client := &http.Client{ | ||||
| 		Transport: &http.Transport{ | ||||
| 			ExpectContinueTimeout: time.Second * 5, | ||||
| 			DialContext: (&net.Dialer{ | ||||
| @@ -19,5 +19,5 @@ func getHTTPClient() *http.Client { | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	return c | ||||
| 	return client | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user