package main
import (
"log"
"net/http"
"strconv"
"github.com/emicklei/go-restful"
"github.com/emicklei/go-restful/swagger"
)
// This example show a complete (GET,PUT,POST,DELETE) conventional example of
// a REST Resource including documentation to be served by e.g. a Swagger UI
// It is recommended to create a Resource struct (UserResource) that can encapsulate
// an object that provide domain access (a DAO)
// It has a Register method including the complete Route mapping to methods together
// with all the appropriate documentation
//
// POST http://localhost:8080/users
// 1Melissa Raspberry
//
// GET http://localhost:8080/users/1
//
// PUT http://localhost:8080/users/1
// 1Melissa
//
// DELETE http://localhost:8080/users/1
//
type User struct {
Id, Name string
}
type UserResource struct {
// normally one would use DAO (data access object)
users map[string]User
}
func (u UserResource) Register(container *restful.Container) {
ws := new(restful.WebService)
ws.
Path("/users").
Doc("Manage Users").
Consumes(restful.MIME_XML, restful.MIME_JSON).
Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well
ws.Route(ws.GET("/{user-id}").To(u.findUser).
// docs
Doc("get a user").
Operation("findUser").
Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
Writes(User{})) // on the response
ws.Route(ws.PUT("/{user-id}").To(u.updateUser).
// docs
Doc("update a user").
Operation("updateUser").
Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
ReturnsError(409, "duplicate user-id", nil).
Reads(User{})) // from the request
ws.Route(ws.POST("").To(u.createUser).
// docs
Doc("create a user").
Operation("createUser").
Reads(User{})) // from the request
ws.Route(ws.DELETE("/{user-id}").To(u.removeUser).
// docs
Doc("delete a user").
Operation("removeUser").
Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")))
container.Add(ws)
}
// GET http://localhost:8080/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, "404: User could not be found.")
return
}
response.WriteEntity(usr)
}
// POST http://localhost:8080/users
// Melissa
//
func (u *UserResource) createUser(request *restful.Request, response *restful.Response) {
usr := new(User)
err := request.ReadEntity(usr)
if err != nil {
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusInternalServerError, err.Error())
return
}
usr.Id = strconv.Itoa(len(u.users) + 1) // simple id generation
u.users[usr.Id] = *usr
response.WriteHeaderAndEntity(http.StatusCreated, usr)
}
// PUT http://localhost:8080/users/1
// 1Melissa Raspberry
//
func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) {
usr := new(User)
err := request.ReadEntity(&usr)
if err != nil {
response.AddHeader("Content-Type", "text/plain")
response.WriteErrorString(http.StatusInternalServerError, err.Error())
return
}
u.users[usr.Id] = *usr
response.WriteEntity(usr)
}
// DELETE http://localhost:8080/users/1
//
func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) {
id := request.PathParameter("user-id")
delete(u.users, id)
}
func main() {
// to see what happens in the package, uncomment the following
//restful.TraceLogger(log.New(os.Stdout, "[restful] ", log.LstdFlags|log.Lshortfile))
wsContainer := restful.NewContainer()
u := UserResource{map[string]User{}}
u.Register(wsContainer)
// Optionally, you can install the Swagger Service which provides a nice Web UI on your REST API
// You need to download the Swagger HTML5 assets and change the FilePath location in the config below.
// Open http://localhost:8080/apidocs and enter http://localhost:8080/apidocs.json in the api input field.
config := swagger.Config{
WebServices: wsContainer.RegisteredWebServices(), // you control what services are visible
WebServicesUrl: "http://localhost:8080",
ApiPath: "/apidocs.json",
// Optionally, specifiy where the UI is located
SwaggerPath: "/apidocs/",
SwaggerFilePath: "/Users/emicklei/xProjects/swagger-ui/dist"}
swagger.RegisterSwaggerService(config, wsContainer)
log.Printf("start listening on localhost:8080")
server := &http.Server{Addr: ":8080", Handler: wsContainer}
log.Fatal(server.ListenAndServe())
}