github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/examples/tutorials/todo-list/dynamic-untyped/main.go (about) 1 package main 2 3 import ( 4 "log" 5 "net/http" 6 "os" 7 "sync" 8 "sync/atomic" 9 10 "github.com/go-openapi/errors" 11 "github.com/go-openapi/loads" 12 "github.com/go-openapi/loads/fmts" 13 "github.com/go-openapi/runtime" 14 "github.com/go-openapi/runtime/middleware" 15 "github.com/go-openapi/runtime/middleware/untyped" 16 ) 17 18 func init() { 19 loads.AddLoader(fmts.YAMLMatcher, fmts.YAMLDoc) 20 } 21 22 func main() { 23 if len(os.Args) == 1 { 24 log.Fatalln("this command requires the swagger spec as argument") 25 } 26 log.Printf("loading %q as contract for the server", os.Args[1]) 27 28 specDoc, err := loads.Spec(os.Args[1]) 29 if err != nil { 30 log.Fatalln(err) 31 } 32 33 // our spec doesn't have application/json in the consumes or produces 34 // so we need to clear those settings out 35 api := untyped.NewAPI(specDoc).WithoutJSONDefaults() 36 37 // register serializers 38 mediaType := "application/io.goswagger.examples.todo-list.v1+json" 39 api.DefaultConsumes = mediaType 40 api.DefaultProduces = mediaType 41 api.RegisterConsumer(mediaType, runtime.JSONConsumer()) 42 api.RegisterProducer(mediaType, runtime.JSONProducer()) 43 44 // register the operation handlers 45 api.RegisterOperation("GET", "/", findTodos) 46 api.RegisterOperation("POST", "/", addOne) 47 api.RegisterOperation("PUT", "/{id}", updateOne) 48 api.RegisterOperation("DELETE", "/{id}", destroyOne) 49 50 // validate the API descriptor, to ensure we don't have any unhandled operations 51 if err := api.Validate(); err != nil { 52 log.Fatalln(err) 53 } 54 55 // construct the application context for this server 56 // use the loaded spec document and the api descriptor with the default router 57 app := middleware.NewContext(specDoc, api, nil) 58 59 log.Println("serving", specDoc.Spec().Info.Title, "at http://localhost:8000") 60 61 // serve the api with spec and UI 62 if err := http.ListenAndServe(":8000", app.APIHandler(nil)); err != nil { 63 log.Fatalln(err) 64 } 65 } 66 67 var findTodos = runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) { 68 log.Println("received 'findTodos'") 69 log.Printf("%#v\n", params) 70 71 return items, nil 72 }) 73 74 var addOne = runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) { 75 log.Println("received 'addOne'") 76 log.Printf("%#v\n", params) 77 78 body := params.(map[string]interface{})["body"].(map[string]interface{}) 79 addItem(body) 80 return body, nil 81 }) 82 83 var updateOne = runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) { 84 log.Println("received 'updateOne'") 85 log.Printf("%#v\n", params) 86 87 data := params.(map[string]interface{}) 88 id := data["id"].(int64) 89 body := data["body"].(map[string]interface{}) 90 return updateItem(id, body) 91 }) 92 93 var destroyOne = runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) { 94 log.Println("received 'destroyOne'") 95 log.Printf("%#v\n", params) 96 97 removeItem(params.(map[string]interface{})["id"].(int64)) 98 return nil, nil 99 }) 100 101 var items = []map[string]interface{}{ 102 {"id": int64(1), "description": "feed dog", "completed": true}, 103 {"id": int64(2), "description": "feed cat"}, 104 } 105 106 var itemsLock = &sync.Mutex{} 107 var lastItemID int64 = 2 108 109 func newItemID() int64 { 110 return atomic.AddInt64(&lastItemID, 1) 111 } 112 113 func addItem(item map[string]interface{}) { 114 itemsLock.Lock() 115 defer itemsLock.Unlock() 116 item["id"] = newItemID() 117 items = append(items, item) 118 } 119 120 func updateItem(id int64, body map[string]interface{}) (map[string]interface{}, error) { 121 itemsLock.Lock() 122 defer itemsLock.Unlock() 123 124 item, err := itemByID(id) 125 if err != nil { 126 return nil, err 127 } 128 delete(body, "id") 129 for k, v := range body { 130 item[k] = v 131 } 132 return item, nil 133 } 134 135 func removeItem(id int64) { 136 itemsLock.Lock() 137 defer itemsLock.Unlock() 138 139 var newItems []map[string]interface{} 140 for _, item := range items { 141 if item["id"].(int64) != id { 142 newItems = append(newItems, item) 143 } 144 } 145 items = newItems 146 } 147 148 func itemByID(id int64) (map[string]interface{}, error) { 149 for _, item := range items { 150 if item["id"].(int64) == id { 151 return item, nil 152 } 153 } 154 return nil, errors.NotFound("not found: item %d", id) 155 }