package main import ( "bytes" "errors" "log" "net/http" "testing" "time" "github.com/emicklei/go-restful" ) type User struct { Id, Name string } type UserResource struct { users map[string]User } func (u UserResource) Register(container *restful.Container) { ws := new(restful.WebService) ws. Path("/users"). Consumes(restful.MIME_XML, restful.MIME_JSON). Produces(restful.MIME_JSON, restful.MIME_XML) ws.Route(ws.GET("/{user-id}").To(u.findUser)) ws.Route(ws.POST("").To(u.updateUser)) ws.Route(ws.PUT("/{user-id}").To(u.createUser)) ws.Route(ws.DELETE("/{user-id}").To(u.removeUser)) container.Add(ws) } // GET http://localhost:8090/users/1 // func (u UserResource) findUser(request *restful.Request, response *restful.Response) { id := request.PathParameter("user-id") usr := u.users[id] if len(usr.Id) == 0 { response.AddHeader("Content-Type", "text/plain") response.WriteErrorString(http.StatusNotFound, "User could not be found.") } else { response.WriteEntity(usr) } } // POST http://localhost:8090/users // 1Melissa Raspberry // func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) { usr := new(User) err := request.ReadEntity(&usr) if err == nil { u.users[usr.Id] = *usr response.WriteEntity(usr) } else { response.AddHeader("Content-Type", "text/plain") response.WriteErrorString(http.StatusInternalServerError, err.Error()) } } // PUT http://localhost:8090/users/1 // 1Melissa // func (u *UserResource) createUser(request *restful.Request, response *restful.Response) { usr := User{Id: request.PathParameter("user-id")} err := request.ReadEntity(&usr) if err == nil { u.users[usr.Id] = usr response.WriteHeader(http.StatusCreated) response.WriteEntity(usr) } else { response.AddHeader("Content-Type", "text/plain") response.WriteErrorString(http.StatusInternalServerError, err.Error()) } } // DELETE http://localhost:8090/users/1 // func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) { id := request.PathParameter("user-id") delete(u.users, id) } func RunRestfulCurlyRouterServer() { wsContainer := restful.NewContainer() wsContainer.Router(restful.CurlyRouter{}) u := UserResource{map[string]User{}} u.Register(wsContainer) log.Printf("start listening on localhost:8090") server := &http.Server{Addr: ":8090", Handler: wsContainer} log.Fatal(server.ListenAndServe()) } func waitForServerUp(serverURL string) error { for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) { _, err := http.Get(serverURL + "/") if err == nil { return nil } } return errors.New("waiting for server timed out") } func TestServer(t *testing.T) { serverURL := "http://localhost:8090" go func() { RunRestfulCurlyRouterServer() }() if err := waitForServerUp(serverURL); err != nil { t.Errorf("%v", err) } // GET should give a 405 resp, err := http.Get(serverURL + "/users/") if err != nil { t.Errorf("unexpected error in GET /users/: %v", err) } if resp.StatusCode != http.StatusMethodNotAllowed { t.Errorf("unexpected response: %v, expected: %v", resp.StatusCode, http.StatusOK) } // Send a POST request. var jsonStr = []byte(`{"id":"1","name":"user1"}`) req, err := http.NewRequest("POST", serverURL+"/users/", bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", restful.MIME_JSON) client := &http.Client{} resp, err = client.Do(req) if err != nil { t.Errorf("unexpected error in sending req: %v", err) } if resp.StatusCode != http.StatusOK { t.Errorf("unexpected response: %v, expected: %v", resp.StatusCode, http.StatusOK) } // Test that GET works. resp, err = http.Get(serverURL + "/users/1") if err != nil { t.Errorf("unexpected error in GET /users/1: %v", err) } if resp.StatusCode != http.StatusOK { t.Errorf("unexpected response: %v, expected: %v", resp.StatusCode, http.StatusOK) } }