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  }