func router(ctx context.Context, m *Middleware, s *Services) (http.Handler, context.CancelFunc) { mux := http.NewServeMux() requestBackground, cancelAll := context.WithCancel(ctx) mux.Handle("/app/", http.StripPrefix("/app/", http.FileServer(s.AppFileSystem))) mux.HandleFunc(routes.Index, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": w.Write([]byte("Who is John Galt?")) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /records/query/ mux.HandleFunc(routes.RecordsQuery, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": routes.Records.QueryGET(ctx, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /records/new/ mux.HandleFunc(routes.RecordsNew, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": routes.Records.NewGET(ctx, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /records/create/ mux.HandleFunc(routes.RecordsCreate, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": routes.Records.CreateGET(ctx, w, r, s.WebUIClient) case "POST": routes.Records.CreatePOST(ctx, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /records/edit/ mux.HandleFunc(routes.RecordsEdit, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": routes.Records.EditGET(ctx, w, r, s.WebUIClient) case "POST": routes.Records.EditPOST(ctx, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /records/view/ mux.HandleFunc(routes.RecordsView, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": routes.Records.ViewGET(ctx, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /records/delete/ mux.HandleFunc(routes.RecordsDelete, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "POST": routes.Records.DeletePOST(ctx, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /register/ mux.HandleFunc(routes.Register, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "POST": routes.RegisterPOST(requestBackground, w, r, s.WebUIClient) case "GET": routes.RegisterGET(requestBackground, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /login/ mux.HandleFunc(routes.Login, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "POST": routes.LoginPOST(ctx, w, r, s.WebUIClient) case "GET": routes.LoginGET(requestBackground, w, r, s.WebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /record/ mux.HandleFunc(routes.Record, logRequest(cors(func(w http.ResponseWriter, r *http.Request) { if r.Method == "OPTIONS" { routes.RecordOPTIONS(requestBackground, w, r) return } ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB) if !ok { return } switch r.Method { case "GET": routes.RecordGET(ctx, w, r, s.Logger, s.DB) case "POST": routes.RecordPOST(ctx, w, r, s.Logger, s.DB) case "DELETE": routes.RecordDELETE(ctx, w, r, s.Logger, s.DB) case "OPTIONS": routes.RecordOPTIONS(ctx, w, r) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }), s.Logger)) // /record/query/ mux.HandleFunc(routes.RecordQuery, logRequest(cors(func(w http.ResponseWriter, r *http.Request) { if r.Method == "OPTIONS" { routes.RecordOPTIONS(requestBackground, w, r) return } ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB) if !ok { return } switch r.Method { case "POST": routes.RecordQueryPOST(ctx, w, r, s.Logger, s.DB) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }), s.Logger)) // /event/ mux.HandleFunc(routes.Event, logRequest(cors(func(w http.ResponseWriter, r *http.Request) { ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB) if !ok { return } switch r.Method { case "POST": routes.EventPOST(ctx, w, r, s.DB, s.Logger) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }), s.Logger)) // /record/changes/ mux.HandleFunc(routes.RecordChanges, logRequest(websocket.Handler( routes.ContextualizeRecordChangesGET(requestBackground, s.DB, s.Logger), ).ServeHTTP, s.Logger)) // /command/sms/ mux.HandleFunc(routes.CommandSMS, logRequest(func(w http.ResponseWriter, r *http.Request) { ctx := requestBackground switch r.Method { case "POST": routes.CommandSMSPOST(ctx, w, r, s.Logger, s.SMSCommandSessions) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /command/web/ mux.HandleFunc(routes.CommandWeb, logRequest(websocket.Handler( routes.ContextualizeCommandWebGET(requestBackground, s.DB, s.Logger), ).ServeHTTP, s.Logger)) // /mobile/location/ mux.HandleFunc(routes.MobileLocation, logRequest(func(w http.ResponseWriter, r *http.Request) { ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB) if !ok { return } switch r.Method { case "POST": routes.MobileLocationPOST(ctx, w, r, s.Logger, s.DB) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // /cal/week/ mux.HandleFunc(routes.CalWeek, logRequest(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": cal.WeekGET(ctx, w, r, s.CalWebUIClient) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } }, s.Logger)) // Handle letsencrypt fs := http.FileServer(http.Dir("/var/www/elos/")) mux.Handle("/.well-known/", logRequest(func(w http.ResponseWriter, r *http.Request) { fs.ServeHTTP(w, r) }, s.Logger)) return mux, cancelAll }
// TestEventPOST tests a POST request to the '/event/' endpoint. // in the happy case (i.e., all parameters present). // We verify: // * The event's name // * The event's data // * The event's tags func TestEventPOST(t *testing.T) { ctx := context.Background() db := mem.NewDB() logger := services.NewTestLogger(t) s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx, ok := routes.Authenticate(ctx, w, r, logger, db) if !ok { t.Error("routes.Authenticate failed") } routes.EventPOST(ctx, w, r, db, logger) })) defer s.Close() _, _, err := user.Create(db, "username", "password") if err != nil { t.Fatalf("user.Create(db, \"username\", \"password\") error: %s", err) } u := s.URL + "?" + url.Values{ "tags": []string{"tag1", "tag2"}, }.Encode() body := map[string]interface{}{ "name": "event name", "time": time.Now(), "data": map[string]interface{}{ "arbitrary": []string{"data"}, "here": 1.0, "foo": map[string]interface{}{ "bar": "there", }, }, } b, err := json.Marshal(body) if err != nil { t.Fatal("json.Marshal(body) error: %s", err) } req, err := http.NewRequest("POST", u, bytes.NewBuffer(b)) req.SetBasicAuth("username", "password") client := new(http.Client) resp, err := client.Do(req) if err != nil { t.Fatalf("client.Do(req) error: %s", err) } defer resp.Body.Close() if got, want := resp.StatusCode, http.StatusCreated; got != want { t.Fatalf("resp.StatusCode: got %d, want %d", got, want) } b, err = ioutil.ReadAll(resp.Body) if err != nil { t.Fatalf("ioutil.ReadAll(resp.Body) error: %s", err) } e := new(models.Event) if err := json.Unmarshal(b, e); err != nil { t.Fatalf("json.Unmarshal(b, e) error: %s", err) } t.Logf("Event:\n\t%v", e) if got, want := e.Name, "event name"; got != want { t.Errorf("e.Name: got %q, want %q", got, want) } if got, want := e.Data["foo"].(map[string]interface{})["bar"], "there"; got != want { t.Errorf("e.Data[\"foo\"][\"bar\"]: got %q, want %q", got, want) } if got, want := len(e.TagsIds), 2; got != want { t.Fatalf("len(e.TagsIds): got %d, want %d", got, want) } tags, err := e.Tags(db) if err != nil { t.Fatalf("e.Tags(db) error: %s", err) } if got, want := len(tags), 2; got != want { t.Fatalf("len(tags): got %d, want %d", got, want) } if got, want := tags[0].Name, "tag1"; got != want { t.Errorf("tags[0].Name: got %q, want %q", got, want) } if got, want := tags[1].Name, "tag2"; got != want { t.Errorf("tags[1].Name: got %q, want %q", got, want) } }