diff --git a/cmd/app/server.go b/cmd/app/server.go index 69b9c60..9774011 100644 --- a/cmd/app/server.go +++ b/cmd/app/server.go @@ -18,7 +18,7 @@ to handle potential shutdown requests and incoming HTTP requests. */ func StartServer(client *Client, projectInfo *ProjectInfo, GitInfo git.GitData) { - s := shutdown{ + s := shutdownService{ sigCh: make(chan os.Signal, 1), } @@ -26,7 +26,7 @@ func StartServer(client *Client, projectInfo *ProjectInfo, GitInfo git.GitData) r := CreateRouter( client, projectInfo, - s, + &s, func(a *data) error { a.projectInfo = projectInfo; return nil }, func(a *data) error { a.gitInfo = &GitInfo; return nil }, func(a *data) error { err := attachEmojis(a, fr); return err }, @@ -39,10 +39,8 @@ func StartServer(client *Client, projectInfo *ProjectInfo, GitInfo git.GitData) go func() { err := server.Serve(l) if err != nil { - if errors.Is(err, http.ErrServerClosed) { - os.Exit(0) - } else { - fmt.Fprintf(os.Stderr, "Server did not respond: %s\n", err) + if !errors.Is(err, http.ErrServerClosed) { + fmt.Fprintf(os.Stderr, "Server crashed: %s\n", err) os.Exit(1) } } @@ -76,7 +74,7 @@ type data struct { type optFunc func(a *data) error -func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s ShutdownHandler, optFuncs ...optFunc) http.Handler { +func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s *shutdownService, optFuncs ...optFunc) http.Handler { m := http.NewServeMux() d := data{ @@ -188,7 +186,6 @@ func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s ShutdownHand withPayloadValidation(methodToPayload{http.MethodPost: &DraftNotePublishRequest{}}), withMethodCheck(http.MethodPost), )) - m.HandleFunc("/pipeline", middleware( pipelineService{d, gitlabClient, git.Git{}}, withMethodCheck(http.MethodGet), @@ -230,8 +227,12 @@ func CreateRouter(gitlabClient *Client, projectInfo *ProjectInfo, s ShutdownHand withPayloadValidation(methodToPayload{http.MethodPost: &MergeRequestByUsernameRequest{}}), withMethodCheck(http.MethodPost), )) + m.HandleFunc("/shutdown", middleware( + *s, + withPayloadValidation(methodToPayload{http.MethodPost: &ShutdownRequest{}}), + withMethodCheck(http.MethodPost), + )) - m.HandleFunc("/shutdown", s.shutdownHandler) m.Handle("/ping", http.HandlerFunc(pingHandler)) return LoggingServer{handler: m} diff --git a/cmd/app/shutdown.go b/cmd/app/shutdown.go index 5f4bd30..043b232 100644 --- a/cmd/app/shutdown.go +++ b/cmd/app/shutdown.go @@ -3,9 +3,7 @@ package app import ( "context" "encoding/json" - "errors" "fmt" - "io" "net/http" "os" ) @@ -19,22 +17,20 @@ func (k killer) String() string { type ShutdownHandler interface { WatchForShutdown(server *http.Server) - shutdownHandler(w http.ResponseWriter, r *http.Request) + ServeHTTP(w http.ResponseWriter, r *http.Request) } -type shutdown struct { +type shutdownService struct { sigCh chan os.Signal } -func (s shutdown) WatchForShutdown(server *http.Server) { +func (s shutdownService) WatchForShutdown(server *http.Server) { /* Handles shutdown requests */ <-s.sigCh err := server.Shutdown(context.Background()) if err != nil { fmt.Fprintf(os.Stderr, "Server could not shut down gracefully: %s\n", err) os.Exit(1) - } else { - os.Exit(0) } } @@ -42,36 +38,20 @@ type ShutdownRequest struct { Restart bool `json:"restart"` } -/* shutdownHandler will shutdown the HTTP server and exit the process by signaling to the shutdown channel */ -func (s shutdown) shutdownHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - w.Header().Set("Allow", http.MethodPost) - handleError(w, errors.New("Invalid request type"), "That request type is not allowed", http.StatusMethodNotAllowed) - return - } +/* Shuts down the HTTP server and exit the process by signaling to the shutdown channel */ +func (s shutdownService) ServeHTTP(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - handleError(w, err, "Could not read request body", http.StatusBadRequest) - return - } - - var shutdownRequest ShutdownRequest - err = json.Unmarshal(body, &shutdownRequest) - if err != nil { - handleError(w, err, "Could not unmarshal data from request body", http.StatusBadRequest) - return - } + payload := r.Context().Value(payload("payload")).(*ShutdownRequest) var text = "Shut down server" - if shutdownRequest.Restart { + if payload.Restart { text = "Restarted server" } w.WriteHeader(http.StatusOK) response := SuccessResponse{Message: text} - err = json.NewEncoder(w).Encode(response) + err := json.NewEncoder(w).Encode(response) if err != nil { handleError(w, err, "Could not encode response", http.StatusInternalServerError) } else { diff --git a/doc/gitlab.nvim.txt b/doc/gitlab.nvim.txt index 2a529e0..a657e74 100644 --- a/doc/gitlab.nvim.txt +++ b/doc/gitlab.nvim.txt @@ -22,7 +22,7 @@ Table of Contents *gitlab.nvim.table-of-contents* - Creating an MR |gitlab.nvim.creating-an-mr| - Pipelines |gitlab.nvim.pipelines| - Reviewers and Assignees |gitlab.nvim.reviewers-and-assignees| - - Restarting or Shutting Down |gitlab.nvim.restarting-or-shutting-down| + - Restarting The Go Server |gitlab.nvim.restarting| - Keybindings |gitlab.nvim.keybindings| - Troubleshooting |gitlab.nvim.troubleshooting| - Api |gitlab.nvim.api| @@ -591,26 +591,12 @@ install `dressing.nvim`. If you use Dressing, please enable it: }) < -RESTARTING OR SHUTTING DOWN *gitlab.nvim.restarting-or-shutting-down* +RESTARTING THE GO SERVER *gitlab.nvim.restarting* The `gitlab.nvim` server will shut down automatically when you exit Neovim. -However, if you would like to manage this yourself (for instance, restart the -server when you check out a new branch) you may do so via the `restart` -command, or `shutdown` commands, which both accept callbacks: +You may restart the server at any time via the the `restart` command: >lua require("gitlab.server").restart() - require("gitlab.server").shutdown() -< -For instance you could set up the following keybinding to close and reopen the -reviewer when checking out a new branch: ->lua - local gitlab = require("gitlab") - vim.keymap.set("n", "glB", function () - require("gitlab.server").restart(function () - vim.cmd.tabclose() - gitlab.review() -- Reopen the reviewer after the server restarts - end) - end) < KEYBINDINGS *gitlab.nvim.keybindings*