func (srv Server) Handler(w http.ResponseWriter, r *http.Request) { l := log.New() l.SetPrefix(fmt.Sprintf("[HTTP:%p]", r)) l.Info("%+v", r) body, err := ioutil.ReadAll(r.Body) if err != nil { l.Error(err) http.Error(w, err.Error(), 500) return } params, err := NewUserRequest(body) if err != nil { l.Error(err) http.Error(w, err.Error(), 400) return } l.Infof("Invoking: %s %+v", params.SubCommandName, params.Arguments) output, cmdErr, err := params.Run(srv.Commands) if err != nil { l.Error(err) http.Error(w, err.Error(), 400) } else { if cmdErr != nil { // XXX: perhaps we should wrap the error as a JSON object // just as we do for 200-code responses. l.Error(err) http.Error(w, err.Error(), 500) } else { // Command ran successfully. Send the output back. if _, err = w.Write([]byte(output)); err != nil { l.Error(err) } } } }
// FIXME: best way to report errors in ServerHTTP? func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Create a logger with a prefix unique to this request. Assuming // that a new request object is created per request, its memory // address (%p) should give us an unique identifier. l := log.New() l.SetPrefix(fmt.Sprintf("[HTTP:%p] ", r)) l.Infof("%+v", r) request := reflect.New(reflect.TypeOf(h.RequestStruct)).Interface().(RequestParams) body, err := ioutil.ReadAll(r.Body) if err != nil { l.Error(err) return } if err := json.Unmarshal(body, request); err != nil { l.Errorf("Unable to decode JSON body in POST request (%s). Original body was: %s", err, string(body)) return } response, err := request.HandleRequest() if err != nil { l.Errorf("Failed to handle this request -- %s", err) http.Error(w, err.Error(), 500) } else { data, err := json.Marshal(response) if err != nil { err = fmt.Errorf("Unable to response into JSON: %s", err) http.Error(w, err.Error(), 500) } else { _, err = w.Write(data) if err != nil { l.Errorf("Unable to write http response: %s", err) } } } }