gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/sync/lock/http/http.go (about) 1 // Package http adds a http lock implementation 2 package http 3 4 import ( 5 "errors" 6 "fmt" 7 "hash/crc32" 8 "io/ioutil" 9 "net/http" 10 "net/url" 11 "path/filepath" 12 "strings" 13 14 "gitee.com/liuxuezhan/go-micro-v1.18.0/sync/lock" 15 ) 16 17 var ( 18 DefaultPath = "/sync/lock" 19 DefaultAddress = "localhost:8080" 20 ) 21 22 type httpLock struct { 23 opts lock.Options 24 } 25 26 func (h *httpLock) url(do, id string) (string, error) { 27 sum := crc32.ChecksumIEEE([]byte(id)) 28 node := h.opts.Nodes[sum%uint32(len(h.opts.Nodes))] 29 30 // parse the host:port or whatever 31 uri, err := url.Parse(node) 32 if err != nil { 33 return "", err 34 } 35 36 if len(uri.Scheme) == 0 { 37 uri.Scheme = "http" 38 } 39 40 // set path 41 // build path 42 path := filepath.Join(DefaultPath, do, h.opts.Prefix, id) 43 uri.Path = path 44 45 // return url 46 return uri.String(), nil 47 } 48 49 func (h *httpLock) Acquire(id string, opts ...lock.AcquireOption) error { 50 var options lock.AcquireOptions 51 for _, o := range opts { 52 o(&options) 53 } 54 55 uri, err := h.url("acquire", id) 56 if err != nil { 57 return err 58 } 59 60 ttl := fmt.Sprintf("%d", int64(options.TTL.Seconds())) 61 wait := fmt.Sprintf("%d", int64(options.Wait.Seconds())) 62 63 rsp, err := http.PostForm(uri, url.Values{ 64 "id": {id}, 65 "ttl": {ttl}, 66 "wait": {wait}, 67 }) 68 if err != nil { 69 return err 70 } 71 defer rsp.Body.Close() 72 73 b, err := ioutil.ReadAll(rsp.Body) 74 if err != nil { 75 return err 76 } 77 78 // success 79 if rsp.StatusCode == 200 { 80 return nil 81 } 82 83 // return error 84 return errors.New(string(b)) 85 } 86 87 func (h *httpLock) Release(id string) error { 88 uri, err := h.url("release", id) 89 if err != nil { 90 return err 91 } 92 93 vals := url.Values{ 94 "id": {id}, 95 } 96 97 req, err := http.NewRequest("DELETE", uri, strings.NewReader(vals.Encode())) 98 if err != nil { 99 return err 100 } 101 102 rsp, err := http.DefaultClient.Do(req) 103 if err != nil { 104 return err 105 } 106 defer rsp.Body.Close() 107 108 b, err := ioutil.ReadAll(rsp.Body) 109 if err != nil { 110 return err 111 } 112 113 // success 114 if rsp.StatusCode == 200 { 115 return nil 116 } 117 118 // return error 119 return errors.New(string(b)) 120 } 121 122 func NewLock(opts ...lock.Option) lock.Lock { 123 var options lock.Options 124 for _, o := range opts { 125 o(&options) 126 } 127 128 if len(options.Nodes) == 0 { 129 options.Nodes = []string{DefaultAddress} 130 } 131 132 return &httpLock{ 133 opts: options, 134 } 135 }