http/http.go (64 lines of code) (raw):

// Copyright 2017 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "context" "errors" "fmt" "io/ioutil" "net/http" "github.com/GoogleCloudPlatform/ubbagent/sdk" ) type HttpInterface struct { agent *sdk.Agent port int mux http.ServeMux srv *http.Server } // NewHttpInterface creates a new agent interface that listens on the given port. The interface // must be started with a call to ListenAndServe(). func NewHttpInterface(agent *sdk.Agent, port int) *HttpInterface { h := &HttpInterface{agent: agent, port: port} h.mux.HandleFunc("/report", h.handleAdd) h.mux.HandleFunc("/status", h.handleStatus) return h } func (h *HttpInterface) handleAdd(w http.ResponseWriter, r *http.Request) { // TODO(volkman): better error handling (internal vs client errors) // TODO(volkman): request logging reportData, err := ioutil.ReadAll(r.Body) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } err = h.agent.AddReportJson(reportData) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } w.WriteHeader(http.StatusOK) } func (h *HttpInterface) handleStatus(w http.ResponseWriter, r *http.Request) { text, err := h.agent.GetStatusJson() if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) } else { w.WriteHeader(http.StatusOK) w.Write(text) } } // Start starts the HttpInterface in the background. It returns an error immediately if background // starting fails, but otherwise returns nil. The errHandler callback receives any errors returned // by the underlying call to ListenAndServe(). Note that the background service may fail quickly // after startup, such as in the case of a port already in use. func (h *HttpInterface) Start(errHandler func(error)) error { if h.srv != nil { return errors.New("already started") } h.srv = &http.Server{Addr: fmt.Sprintf("localhost:%v", h.port), Handler: &h.mux} go func() { errHandler(h.srv.ListenAndServe()) }() return nil } // Shutdown initiates a graceful shutdown of the HttpInterface and blocks until the operation // finishes. func (h *HttpInterface) Shutdown() error { if h.srv == nil { return errors.New("not started") } err := h.srv.Shutdown(context.Background()) h.srv = nil return err }