diff options
author | unknwon <u@gogs.io> | 2019-07-28 16:03:54 -0700 |
---|---|---|
committer | unknwon <u@gogs.io> | 2019-07-28 16:03:54 -0700 |
commit | 025972ef643fa7628551529c2fd145e2a184465b (patch) | |
tree | 1066a33af394fc4fb7bdbcaa2b2fe29875576877 /vendor/github.com/smartystreets/goconvey/web/server/api/server.go | |
parent | 00a3e368b482193f1a457586ab4152ffacc02fab (diff) |
vendor: update missing test deps for ci
Diffstat (limited to 'vendor/github.com/smartystreets/goconvey/web/server/api/server.go')
-rw-r--r-- | vendor/github.com/smartystreets/goconvey/web/server/api/server.go | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/vendor/github.com/smartystreets/goconvey/web/server/api/server.go b/vendor/github.com/smartystreets/goconvey/web/server/api/server.go new file mode 100644 index 00000000..6cea26da --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/web/server/api/server.go @@ -0,0 +1,164 @@ +package api + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "strconv" + "time" + + "github.com/smartystreets/goconvey/web/server/contract" + "github.com/smartystreets/goconvey/web/server/messaging" +) + +type HTTPServer struct { + watcher chan messaging.WatcherCommand + executor contract.Executor + latest *contract.CompleteOutput + currentRoot string + longpoll chan chan string + paused bool +} + +func (self *HTTPServer) ReceiveUpdate(root string, update *contract.CompleteOutput) { + self.currentRoot = root + self.latest = update +} + +func (self *HTTPServer) Watch(response http.ResponseWriter, request *http.Request) { + if request.Method == "POST" { + self.adjustRoot(response, request) + } else if request.Method == "GET" { + response.Write([]byte(self.currentRoot)) + } +} + +func (self *HTTPServer) adjustRoot(response http.ResponseWriter, request *http.Request) { + newRoot := self.parseQueryString("root", response, request) + if newRoot == "" { + return + } + info, err := os.Stat(newRoot) // TODO: how to unit test? + if !info.IsDir() || err != nil { + http.Error(response, err.Error(), http.StatusNotFound) + return + } + + self.watcher <- messaging.WatcherCommand{ + Instruction: messaging.WatcherAdjustRoot, + Details: newRoot, + } +} + +func (self *HTTPServer) Ignore(response http.ResponseWriter, request *http.Request) { + paths := self.parseQueryString("paths", response, request) + if paths != "" { + self.watcher <- messaging.WatcherCommand{ + Instruction: messaging.WatcherIgnore, + Details: paths, + } + } +} + +func (self *HTTPServer) Reinstate(response http.ResponseWriter, request *http.Request) { + paths := self.parseQueryString("paths", response, request) + if paths != "" { + self.watcher <- messaging.WatcherCommand{ + Instruction: messaging.WatcherReinstate, + Details: paths, + } + } +} + +func (self *HTTPServer) parseQueryString(key string, response http.ResponseWriter, request *http.Request) string { + value := request.URL.Query()[key] + + if len(value) == 0 { + http.Error(response, fmt.Sprintf("No '%s' query string parameter included!", key), http.StatusBadRequest) + return "" + } + + path := value[0] + if path == "" { + http.Error(response, "You must provide a non-blank path.", http.StatusBadRequest) + } + return path +} + +func (self *HTTPServer) Status(response http.ResponseWriter, request *http.Request) { + status := self.executor.Status() + response.Write([]byte(status)) +} + +func (self *HTTPServer) LongPollStatus(response http.ResponseWriter, request *http.Request) { + if self.executor.ClearStatusFlag() { + response.Write([]byte(self.executor.Status())) + return + } + + timeout, err := strconv.Atoi(request.URL.Query().Get("timeout")) + if err != nil || timeout > 180000 || timeout < 0 { + timeout = 60000 // default timeout is 60 seconds + } + + myReqChan := make(chan string) + + select { + case self.longpoll <- myReqChan: // this case means the executor's status is changing + case <-time.After(time.Duration(timeout) * time.Millisecond): // this case means the executor hasn't changed status + return + } + + out := <-myReqChan + + if out != "" { // TODO: Why is this check necessary? Sometimes it writes empty string... + response.Write([]byte(out)) + } +} + +func (self *HTTPServer) Results(response http.ResponseWriter, request *http.Request) { + response.Header().Set("Content-Type", "application/json") + response.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + response.Header().Set("Pragma", "no-cache") + response.Header().Set("Expires", "0") + if self.latest != nil { + self.latest.Paused = self.paused + } + stuff, _ := json.Marshal(self.latest) + response.Write(stuff) +} + +func (self *HTTPServer) Execute(response http.ResponseWriter, request *http.Request) { + go self.execute() +} + +func (self *HTTPServer) execute() { + self.watcher <- messaging.WatcherCommand{Instruction: messaging.WatcherExecute} +} + +func (self *HTTPServer) TogglePause(response http.ResponseWriter, request *http.Request) { + instruction := messaging.WatcherPause + if self.paused { + instruction = messaging.WatcherResume + } + + self.watcher <- messaging.WatcherCommand{Instruction: instruction} + self.paused = !self.paused + + fmt.Fprint(response, self.paused) // we could write out whatever helps keep the UI honest... +} + +func NewHTTPServer( + root string, + watcher chan messaging.WatcherCommand, + executor contract.Executor, + status chan chan string) *HTTPServer { + + self := new(HTTPServer) + self.currentRoot = root + self.watcher = watcher + self.executor = executor + self.longpoll = status + return self +} |