github.com/lingyao2333/mo-zero@v1.4.1/rest/httpc/service.go (about) 1 package httpc 2 3 import ( 4 "context" 5 "net/http" 6 7 "github.com/lingyao2333/mo-zero/core/breaker" 8 ) 9 10 type ( 11 // Option is used to customize the *http.Client. 12 Option func(r *http.Request) *http.Request 13 14 // Service represents a remote HTTP service. 15 Service interface { 16 // Do sends an HTTP request with the given arguments and returns an HTTP response. 17 Do(ctx context.Context, method, url string, data interface{}) (*http.Response, error) 18 // DoRequest sends a HTTP request to the service. 19 DoRequest(r *http.Request) (*http.Response, error) 20 } 21 22 namedService struct { 23 name string 24 cli *http.Client 25 opts []Option 26 } 27 ) 28 29 // NewService returns a remote service with the given name. 30 // opts are used to customize the *http.Client. 31 func NewService(name string, opts ...Option) Service { 32 return NewServiceWithClient(name, http.DefaultClient, opts...) 33 } 34 35 // NewServiceWithClient returns a remote service with the given name. 36 // opts are used to customize the *http.Client. 37 func NewServiceWithClient(name string, cli *http.Client, opts ...Option) Service { 38 return namedService{ 39 name: name, 40 cli: cli, 41 opts: opts, 42 } 43 } 44 45 // Do sends an HTTP request with the given arguments and returns an HTTP response. 46 func (s namedService) Do(ctx context.Context, method, url string, data interface{}) (*http.Response, error) { 47 req, err := buildRequest(ctx, method, url, data) 48 if err != nil { 49 return nil, err 50 } 51 52 return s.DoRequest(req) 53 } 54 55 // DoRequest sends an HTTP request to the service. 56 func (s namedService) DoRequest(r *http.Request) (*http.Response, error) { 57 return request(r, s) 58 } 59 60 func (s namedService) do(r *http.Request) (resp *http.Response, err error) { 61 for _, opt := range s.opts { 62 r = opt(r) 63 } 64 65 brk := breaker.GetBreaker(s.name) 66 err = brk.DoWithAcceptable(func() error { 67 resp, err = s.cli.Do(r) 68 return err 69 }, func(err error) bool { 70 return err == nil && resp.StatusCode < http.StatusInternalServerError 71 }) 72 73 return 74 }