gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/api/handler/registry/registry.go (about) 1 // Package registry is a go-micro/registry handler 2 package registry 3 4 import ( 5 "encoding/json" 6 "io/ioutil" 7 "net/http" 8 "strconv" 9 "time" 10 11 "github.com/gorilla/websocket" 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/api/handler" 13 "gitee.com/liuxuezhan/go-micro-v1.18.0/registry" 14 ) 15 16 const ( 17 Handler = "registry" 18 19 pingTime = (readDeadline * 9) / 10 20 readLimit = 16384 21 readDeadline = 60 * time.Second 22 writeDeadline = 10 * time.Second 23 ) 24 25 type registryHandler struct { 26 opts handler.Options 27 reg registry.Registry 28 } 29 30 func (rh *registryHandler) add(w http.ResponseWriter, r *http.Request) { 31 r.ParseForm() 32 b, err := ioutil.ReadAll(r.Body) 33 if err != nil { 34 http.Error(w, err.Error(), 500) 35 return 36 } 37 defer r.Body.Close() 38 39 var opts []registry.RegisterOption 40 41 // parse ttl 42 if ttl := r.Form.Get("ttl"); len(ttl) > 0 { 43 d, err := time.ParseDuration(ttl) 44 if err == nil { 45 opts = append(opts, registry.RegisterTTL(d)) 46 } 47 } 48 49 var service *registry.Service 50 err = json.Unmarshal(b, &service) 51 if err != nil { 52 http.Error(w, err.Error(), 500) 53 return 54 } 55 err = rh.reg.Register(service, opts...) 56 if err != nil { 57 http.Error(w, err.Error(), 500) 58 return 59 } 60 } 61 62 func (rh *registryHandler) del(w http.ResponseWriter, r *http.Request) { 63 r.ParseForm() 64 b, err := ioutil.ReadAll(r.Body) 65 if err != nil { 66 http.Error(w, err.Error(), 500) 67 return 68 } 69 defer r.Body.Close() 70 71 var service *registry.Service 72 err = json.Unmarshal(b, &service) 73 if err != nil { 74 http.Error(w, err.Error(), 500) 75 return 76 } 77 err = rh.reg.Deregister(service) 78 if err != nil { 79 http.Error(w, err.Error(), 500) 80 return 81 } 82 } 83 84 func (rh *registryHandler) get(w http.ResponseWriter, r *http.Request) { 85 r.ParseForm() 86 service := r.Form.Get("service") 87 88 var s []*registry.Service 89 var err error 90 91 if len(service) == 0 { 92 // 93 upgrade := r.Header.Get("Upgrade") 94 connect := r.Header.Get("Connection") 95 96 // watch if websockets 97 if upgrade == "websocket" && connect == "Upgrade" { 98 rw, err := rh.reg.Watch() 99 if err != nil { 100 http.Error(w, err.Error(), 500) 101 return 102 } 103 watch(rw, w, r) 104 return 105 } 106 107 // otherwise list services 108 s, err = rh.reg.ListServices() 109 } else { 110 s, err = rh.reg.GetService(service) 111 } 112 113 if err != nil { 114 http.Error(w, err.Error(), 500) 115 return 116 } 117 118 if s == nil || (len(service) > 0 && (len(s) == 0 || len(s[0].Name) == 0)) { 119 http.Error(w, "Service not found", 404) 120 return 121 } 122 123 b, err := json.Marshal(s) 124 if err != nil { 125 http.Error(w, err.Error(), 500) 126 return 127 } 128 129 w.Header().Set("Content-Type", "application/json") 130 w.Header().Set("Content-Length", strconv.Itoa(len(b))) 131 w.Write(b) 132 } 133 134 func ping(ws *websocket.Conn, exit chan bool) { 135 ticker := time.NewTicker(pingTime) 136 137 for { 138 select { 139 case <-ticker.C: 140 ws.SetWriteDeadline(time.Now().Add(writeDeadline)) 141 err := ws.WriteMessage(websocket.PingMessage, []byte{}) 142 if err != nil { 143 return 144 } 145 case <-exit: 146 return 147 } 148 } 149 } 150 151 func watch(rw registry.Watcher, w http.ResponseWriter, r *http.Request) { 152 upgrader := websocket.Upgrader{ 153 ReadBufferSize: 1024, 154 WriteBufferSize: 1024, 155 } 156 157 ws, err := upgrader.Upgrade(w, r, nil) 158 if err != nil { 159 http.Error(w, err.Error(), 500) 160 return 161 } 162 163 // we need an exit chan 164 exit := make(chan bool) 165 166 defer func() { 167 close(exit) 168 }() 169 170 // ping the socket 171 go ping(ws, exit) 172 173 for { 174 // get next result 175 r, err := rw.Next() 176 if err != nil { 177 http.Error(w, err.Error(), 500) 178 return 179 } 180 181 // write to client 182 ws.SetWriteDeadline(time.Now().Add(writeDeadline)) 183 if err := ws.WriteJSON(r); err != nil { 184 return 185 } 186 } 187 } 188 189 func (rh *registryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 190 switch r.Method { 191 case "GET": 192 rh.get(w, r) 193 case "POST": 194 rh.add(w, r) 195 case "DELETE": 196 rh.del(w, r) 197 } 198 } 199 200 func (rh *registryHandler) String() string { 201 return "registry" 202 } 203 204 func NewHandler(opts ...handler.Option) handler.Handler { 205 options := handler.NewOptions(opts...) 206 207 return ®istryHandler{ 208 opts: options, 209 reg: options.Service.Client().Options().Registry, 210 } 211 }