restful-user-resource.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package main
  2. import (
  3. "log"
  4. "net/http"
  5. "strconv"
  6. "github.com/emicklei/go-restful"
  7. "github.com/emicklei/go-restful/swagger"
  8. )
  9. // This example show a complete (GET,PUT,POST,DELETE) conventional example of
  10. // a REST Resource including documentation to be served by e.g. a Swagger UI
  11. // It is recommended to create a Resource struct (UserResource) that can encapsulate
  12. // an object that provide domain access (a DAO)
  13. // It has a Register method including the complete Route mapping to methods together
  14. // with all the appropriate documentation
  15. //
  16. // POST http://localhost:8080/users
  17. // <User><Id>1</Id><Name>Melissa Raspberry</Name></User>
  18. //
  19. // GET http://localhost:8080/users/1
  20. //
  21. // PUT http://localhost:8080/users/1
  22. // <User><Id>1</Id><Name>Melissa</Name></User>
  23. //
  24. // DELETE http://localhost:8080/users/1
  25. //
  26. type User struct {
  27. Id, Name string
  28. }
  29. type UserResource struct {
  30. // normally one would use DAO (data access object)
  31. users map[string]User
  32. }
  33. func (u UserResource) Register(container *restful.Container) {
  34. ws := new(restful.WebService)
  35. ws.
  36. Path("/users").
  37. Doc("Manage Users").
  38. Consumes(restful.MIME_XML, restful.MIME_JSON).
  39. Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well
  40. ws.Route(ws.GET("/{user-id}").To(u.findUser).
  41. // docs
  42. Doc("get a user").
  43. Operation("findUser").
  44. Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
  45. Writes(User{})) // on the response
  46. ws.Route(ws.PUT("/{user-id}").To(u.updateUser).
  47. // docs
  48. Doc("update a user").
  49. Operation("updateUser").
  50. Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
  51. ReturnsError(409, "duplicate user-id", nil).
  52. Reads(User{})) // from the request
  53. ws.Route(ws.GET("").To(u.createUser).
  54. // docs
  55. Doc("create a user").
  56. Operation("createUser").
  57. Reads(User{})) // from the request
  58. ws.Route(ws.DELETE("/{user-id}").To(u.removeUser).
  59. // docs
  60. Doc("delete a user").
  61. Operation("removeUser").
  62. Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")))
  63. container.Add(ws)
  64. }
  65. // GET http://localhost:8080/users/1
  66. //
  67. func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
  68. id := request.PathParameter("user-id")
  69. usr := u.users[id]
  70. if len(usr.Id) == 0 {
  71. response.AddHeader("Content-Type", "text/plain")
  72. response.WriteErrorString(http.StatusNotFound, "404: User could not be found.")
  73. return
  74. }
  75. response.WriteEntity(usr)
  76. }
  77. // POST http://localhost:8080/users
  78. // <User><Name>Melissa</Name></User>
  79. //
  80. func (u *UserResource) createUser(request *restful.Request, response *restful.Response) {
  81. usr := new(User)
  82. err := request.ReadEntity(usr)
  83. if err != nil {
  84. response.AddHeader("Content-Type", "text/plain")
  85. response.WriteErrorString(http.StatusInternalServerError, err.Error())
  86. return
  87. }
  88. usr.Id = strconv.Itoa(len(u.users) + 1) // simple id generation
  89. u.users[usr.Id] = *usr
  90. response.WriteHeaderAndEntity(http.StatusCreated, usr)
  91. }
  92. // PUT http://localhost:8080/users/1
  93. // <User><Id>1</Id><Name>Melissa Raspberry</Name></User>
  94. //
  95. func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) {
  96. usr := new(User)
  97. err := request.ReadEntity(&usr)
  98. if err != nil {
  99. response.AddHeader("Content-Type", "text/plain")
  100. response.WriteErrorString(http.StatusInternalServerError, err.Error())
  101. return
  102. }
  103. u.users[usr.Id] = *usr
  104. response.WriteEntity(usr)
  105. }
  106. // DELETE http://localhost:8080/users/1
  107. //
  108. func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) {
  109. id := request.PathParameter("user-id")
  110. delete(u.users, id)
  111. }
  112. func main() {
  113. // to see what happens in the package, uncomment the following
  114. //restful.TraceLogger(log.New(os.Stdout, "[restful] ", log.LstdFlags|log.Lshortfile))
  115. wsContainer := restful.NewContainer()
  116. u := UserResource{map[string]User{}}
  117. u.Register(wsContainer)
  118. // Optionally, you can install the Swagger Service which provides a nice Web UI on your REST API
  119. // You need to download the Swagger HTML5 assets and change the FilePath location in the config below.
  120. // Open http://localhost:8080/apidocs and enter http://localhost:8080/apidocs.json in the api input field.
  121. config := swagger.Config{
  122. WebServices: wsContainer.RegisteredWebServices(), // you control what services are visible
  123. WebServicesUrl: "http://localhost:8080",
  124. ApiPath: "/apidocs.json",
  125. // Optionally, specifiy where the UI is located
  126. SwaggerPath: "/apidocs/",
  127. SwaggerFilePath: "/Users/emicklei/xProjects/swagger-ui/dist"}
  128. swagger.RegisterSwaggerService(config, wsContainer)
  129. log.Printf("start listening on localhost:8080")
  130. server := &http.Server{Addr: ":8080", Handler: wsContainer}
  131. log.Fatal(server.ListenAndServe())
  132. }