diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e5d1ca0..d1fa2da 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -20,14 +20,14 @@ jobs: - uses: actions/setup-go@v3 with: - go-version: '^1.18' + go-version: '^1.19' - name: Run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.45.1 + version: v1.49.0 only-new-issues: true - args: -c ./.golangci.yml + args: -c ./.golangci.yml --timeout 15m - name: Get dependencies run: go mod download @@ -45,7 +45,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '^1.18' + go-version: '^1.19' - name: Get dependencies run: go mod download diff --git a/.golangci.yml b/.golangci.yml index 6c348ac..8202fea 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,6 +8,7 @@ linters: - contextcheck - cyclop - exhaustivestruct + - exhaustruct - forbidigo - funlen - gochecknoglobals @@ -17,6 +18,7 @@ linters: - goerr113 - gomnd - ifshort + - interfacebloat - interfacer - ireturn - lll @@ -24,6 +26,9 @@ linters: - nilnil - nlreturn - noctx + - nolintlint + - nonamedreturns + - nosnakecase - revive - tagliatelle - testpackage @@ -31,7 +36,6 @@ linters: - whitespace - wrapcheck - wsl - - nolintlint linters-settings: revive: diff --git a/api/database.go b/api/database.go index 970dc38..5df98be 100644 --- a/api/database.go +++ b/api/database.go @@ -82,7 +82,7 @@ func startDatabaseAPI(w http.ResponseWriter, r *http.Request) { if err != nil { errMsg := fmt.Sprintf("could not upgrade: %s", err) log.Error(errMsg) - http.Error(w, errMsg, 400) + http.Error(w, errMsg, http.StatusBadRequest) return } diff --git a/api/endpoints_debug.go b/api/endpoints_debug.go index 163e948..3baf1a2 100644 --- a/api/endpoints_debug.go +++ b/api/endpoints_debug.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "runtime/pprof" + "strings" "time" "github.com/safing/portbase/utils/debug" @@ -44,11 +45,16 @@ func registerDebugEndpoints() error { } if err := RegisterEndpoint(Endpoint{ - Path: "debug/cpu", - Read: PermitAnyone, - DataFunc: handleCPUProfile, - Name: "Get CPU Profile", - Description: "", + Path: "debug/cpu", + Read: PermitAnyone, + DataFunc: handleCPUProfile, + Name: "Get CPU Profile", + Description: strings.ReplaceAll(`Gather and return the CPU profile. +This data needs to gathered over a period of time, which is specified using the duration parameter. + +You can easily view this data in your browser with this command (with Go installed): +"go tool pprof -http :8888 http://127.0.0.1:817/api/v1/debug/cpu" +`, `"`, "`"), Parameters: []Parameter{{ Method: http.MethodGet, Field: "duration", @@ -60,21 +66,29 @@ func registerDebugEndpoints() error { } if err := RegisterEndpoint(Endpoint{ - Path: "debug/heap", - Read: PermitAnyone, - DataFunc: handleHeapProfile, - Name: "Get Heap Profile", - Description: "", + Path: "debug/heap", + Read: PermitAnyone, + DataFunc: handleHeapProfile, + Name: "Get Heap Profile", + Description: strings.ReplaceAll(`Gather and return the heap memory profile. + + You can easily view this data in your browser with this command (with Go installed): + "go tool pprof -http :8888 http://127.0.0.1:817/api/v1/debug/heap" + `, `"`, "`"), }); err != nil { return err } if err := RegisterEndpoint(Endpoint{ - Path: "debug/allocs", - Read: PermitAnyone, - DataFunc: handleAllocsProfile, - Name: "Get Allocs Profile", - Description: "", + Path: "debug/allocs", + Read: PermitAnyone, + DataFunc: handleAllocsProfile, + Name: "Get Allocs Profile", + Description: strings.ReplaceAll(`Gather and return the memory allocation profile. + + You can easily view this data in your browser with this command (with Go installed): + "go tool pprof -http :8888 http://127.0.0.1:817/api/v1/debug/allocs" + `, `"`, "`"), }); err != nil { return err } diff --git a/api/router.go b/api/router.go index 860767c..6cc9ae4 100644 --- a/api/router.go +++ b/api/router.go @@ -23,7 +23,9 @@ var ( mainMux = mux.NewRouter() // server is the main server. - server = &http.Server{} + server = &http.Server{ + ReadHeaderTimeout: 10 * time.Second, + } handlerLock sync.RWMutex allowedDevCORSOrigins = []string{ diff --git a/modules/mgmt.go b/modules/mgmt.go index 78bdeb9..adb460d 100644 --- a/modules/mgmt.go +++ b/modules/mgmt.go @@ -71,6 +71,12 @@ func EnableModuleManagement(changeNotifyFn func(*Module)) bool { return false } +// DisableModuleManagement disables module management and returns the module +// system to the default start/stop behavior. +func DisableModuleManagement() { + moduleMgmtEnabled.UnSet() +} + func (m *Module) notifyOfChange() { if moduleMgmtEnabled.IsSet() && modulesChangeNotifyFn != nil { m.StartWorker("notify of change", func(ctx context.Context) error { diff --git a/run/main.go b/run/main.go index c14c880..6e2623d 100644 --- a/run/main.go +++ b/run/main.go @@ -33,6 +33,7 @@ func Run() int { // Start err := modules.Start() if err != nil { + // Immediately return for a clean exit. if errors.Is(err, modules.ErrCleanExit) { return 0 } @@ -41,8 +42,17 @@ func Run() int { printStackTo(os.Stdout, "PRINTING STACK ON EXIT (STARTUP ERROR)") } + // Trigger shutdown and wait for it to complete. _ = modules.Shutdown() - return modules.GetExitStatusCode() + exitCode := modules.GetExitStatusCode() + + // Return the exit code, if it was set. + if exitCode > 0 { + return exitCode + } + + // Otherwise, return a default 1. + return 1 } // Shutdown