mirror of
https://github.com/nabbar/golib.git
synced 2025-12-24 11:51:02 +08:00
Package Request:
- fix bug with retryer and io reader body (body was not resend on retryed request) - remove mutex and use atomic on potential race field - simplify & optimize some code
This commit is contained in:
@@ -36,6 +36,29 @@ const (
|
||||
contentTypeJson = "application/json"
|
||||
)
|
||||
|
||||
type bds struct {
|
||||
b []byte
|
||||
}
|
||||
|
||||
func (b *bds) Retry() io.Reader {
|
||||
var p = make([]byte, len(b.b), cap(b.b))
|
||||
copy(p, b.b)
|
||||
return bytes.NewBuffer(p)
|
||||
}
|
||||
|
||||
type bdf struct {
|
||||
f io.ReadSeeker
|
||||
p int64
|
||||
}
|
||||
|
||||
func (b *bdf) Retry() io.Reader {
|
||||
if _, e := b.f.Seek(b.p, io.SeekStart); e != nil {
|
||||
return nil
|
||||
} else {
|
||||
return b.f
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) BodyJson(body interface{}) error {
|
||||
if p, e := json.Marshal(body); e != nil {
|
||||
return e
|
||||
@@ -44,23 +67,41 @@ func (r *request) BodyJson(body interface{}) error {
|
||||
} else {
|
||||
r.ContentType(contentTypeJson)
|
||||
r.ContentLength(uint64(len(p)))
|
||||
r._BodyReader(bytes.NewBuffer(p))
|
||||
r._BodyReader(&bds{
|
||||
b: p,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) BodyReader(body io.Reader, contentType string) {
|
||||
r._BodyReader(body)
|
||||
func (r *request) BodyReader(body io.Reader, contentType string) error {
|
||||
if f, k := body.(io.ReadSeeker); k {
|
||||
if p, e := f.Seek(0, io.SeekStart); e != nil {
|
||||
return e
|
||||
} else {
|
||||
r._BodyReader(&bdf{
|
||||
f: f,
|
||||
p: p,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if p, e := io.ReadAll(body); e != nil {
|
||||
return e
|
||||
} else {
|
||||
r._BodyReader(&bds{
|
||||
b: p,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if contentType != "" {
|
||||
r.ContentType(contentType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) _BodyReader(body io.Reader) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
r.b = body
|
||||
func (r *request) _BodyReader(body BodyRetryer) {
|
||||
r.bdr = body
|
||||
}
|
||||
|
||||
@@ -32,48 +32,91 @@ import (
|
||||
)
|
||||
|
||||
type requestError struct {
|
||||
c int
|
||||
s string
|
||||
se bool
|
||||
b *bytes.Buffer
|
||||
be bool
|
||||
e error
|
||||
code int
|
||||
status string
|
||||
statusErr bool
|
||||
bufBody *bytes.Buffer
|
||||
bodyErr bool
|
||||
err error
|
||||
}
|
||||
|
||||
func (r *requestError) StatusCode() int {
|
||||
return r.c
|
||||
return r.code
|
||||
}
|
||||
|
||||
func (r *requestError) Status() string {
|
||||
return r.s
|
||||
return r.status
|
||||
}
|
||||
|
||||
func (r *requestError) Body() *bytes.Buffer {
|
||||
return r.b
|
||||
return r.bufBody
|
||||
}
|
||||
|
||||
func (r *requestError) Error() error {
|
||||
return r.e
|
||||
return r.err
|
||||
}
|
||||
|
||||
func (r *requestError) IsError() bool {
|
||||
return r.se || r.be || r.e != nil
|
||||
return r.statusErr || r.bodyErr || r.err != nil
|
||||
}
|
||||
|
||||
func (r *requestError) IsStatusError() bool {
|
||||
return r.se
|
||||
return r.statusErr
|
||||
}
|
||||
|
||||
func (r *requestError) IsBodyError() bool {
|
||||
return r.be
|
||||
return r.bodyErr
|
||||
}
|
||||
|
||||
func (r *requestError) ParseBody(i interface{}) bool {
|
||||
if r.b != nil && r.b.Len() > 0 {
|
||||
if e := json.Unmarshal(r.b.Bytes(), i); e == nil {
|
||||
if r.bufBody != nil && r.bufBody.Len() > 0 {
|
||||
if e := json.Unmarshal(r.bufBody.Bytes(), i); e == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *request) newError() {
|
||||
r.err.Store(&requestError{
|
||||
code: 0,
|
||||
status: "",
|
||||
statusErr: false,
|
||||
bufBody: bytes.NewBuffer(make([]byte, 0)),
|
||||
bodyErr: false,
|
||||
err: nil,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *request) getError() *requestError {
|
||||
if i := r.err.Load(); i != nil {
|
||||
if v, k := i.(*requestError); k {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
return &requestError{
|
||||
code: 0,
|
||||
status: "",
|
||||
statusErr: false,
|
||||
bufBody: bytes.NewBuffer(make([]byte, 0)),
|
||||
bodyErr: false,
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) setError(e *requestError) {
|
||||
if e == nil {
|
||||
e = &requestError{
|
||||
code: 0,
|
||||
status: "",
|
||||
statusErr: false,
|
||||
bufBody: bytes.NewBuffer(make([]byte, 0)),
|
||||
bodyErr: false,
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
r.err.Store(e)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ package request
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (r *request) ContentType(mime string) {
|
||||
@@ -40,37 +40,64 @@ func (r *request) ContentLength(size uint64) {
|
||||
}
|
||||
|
||||
func (r *request) CleanHeader() {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
var k = make([]any, 0)
|
||||
|
||||
r.h = make(url.Values)
|
||||
r.hdr.Range(func(key, value any) bool {
|
||||
k = append(k, key)
|
||||
return true
|
||||
})
|
||||
|
||||
for _, key := range k {
|
||||
r.hdr.Delete(key)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) DelHeader(key string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
r.h.Del(key)
|
||||
r.hdr.Delete(key)
|
||||
}
|
||||
|
||||
func (r *request) SetHeader(key, value string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
if len(r.h) < 1 {
|
||||
r.h = make(url.Values)
|
||||
}
|
||||
|
||||
r.h.Set(key, value)
|
||||
r.hdr.Store(key, append(make([]string, 0), value))
|
||||
}
|
||||
|
||||
func (r *request) AddHeader(key, value string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
if len(r.h) < 1 {
|
||||
r.h = make(url.Values)
|
||||
var val []string
|
||||
if i, l := r.hdr.Load(key); i != nil && l {
|
||||
if v, k := i.([]string); k && len(v) > 0 {
|
||||
val = v
|
||||
}
|
||||
}
|
||||
|
||||
r.h.Add(key, value)
|
||||
if len(val) < 1 {
|
||||
val = make([]string, 0)
|
||||
}
|
||||
|
||||
r.hdr.Store(key, append(val, value))
|
||||
}
|
||||
|
||||
func (r *request) GetHeader(key string) []string {
|
||||
if i, l := r.hdr.Load(key); i != nil && l {
|
||||
if v, k := i.([]string); k && len(v) > 0 {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
return make([]string, 0)
|
||||
}
|
||||
|
||||
func (r *request) httpHeader() http.Header {
|
||||
var hdr = make(http.Header)
|
||||
|
||||
r.hdr.Range(func(key, value any) bool {
|
||||
if u, k := key.(string); !k {
|
||||
return true
|
||||
} else if v, l := value.([]string); !l {
|
||||
return true
|
||||
} else {
|
||||
hdr[u] = v
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
return hdr
|
||||
}
|
||||
|
||||
@@ -90,7 +90,11 @@ type Header interface {
|
||||
|
||||
type Body interface {
|
||||
BodyJson(body interface{}) error
|
||||
BodyReader(body io.Reader, contentType string)
|
||||
BodyReader(body io.Reader, contentType string) error
|
||||
}
|
||||
|
||||
type BodyRetryer interface {
|
||||
Retry() io.Reader
|
||||
}
|
||||
|
||||
type Request interface {
|
||||
@@ -121,23 +125,23 @@ type Request interface {
|
||||
|
||||
func New(ctx libctx.FuncContext, opt *Options, cli libhtc.HttpClient) (Request, error) {
|
||||
r := &request{
|
||||
s: sync.Mutex{},
|
||||
o: nil,
|
||||
x: ctx,
|
||||
l: nil,
|
||||
u: nil,
|
||||
h: make(url.Values),
|
||||
p: make(url.Values),
|
||||
b: bytes.NewBuffer(make([]byte, 0)),
|
||||
m: http.MethodGet,
|
||||
e: nil,
|
||||
c: new(atomic.Value),
|
||||
mux: sync.Mutex{},
|
||||
opt: new(atomic.Value),
|
||||
ctx: new(atomic.Value),
|
||||
log: new(atomic.Value),
|
||||
uri: nil,
|
||||
hdr: sync.Map{},
|
||||
prm: make(url.Values),
|
||||
bdr: nil,
|
||||
mth: http.MethodGet,
|
||||
err: new(atomic.Value),
|
||||
cli: new(atomic.Value),
|
||||
}
|
||||
|
||||
if cli != nil {
|
||||
r.c.Store(cli)
|
||||
r.cli.Store(cli)
|
||||
} else {
|
||||
r.c.Store(libhtc.GetClient())
|
||||
r.cli.Store(libhtc.GetClient())
|
||||
}
|
||||
|
||||
if e := r.SetOption(opt); e != nil {
|
||||
|
||||
154
request/model.go
154
request/model.go
@@ -28,14 +28,14 @@ package request
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/url"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -47,35 +47,43 @@ const (
|
||||
)
|
||||
|
||||
type request struct {
|
||||
s sync.Mutex
|
||||
mux sync.Mutex
|
||||
|
||||
o *atomic.Value // Options
|
||||
x libctx.FuncContext // Context function
|
||||
l liblog.FuncLog // Default logger
|
||||
u *url.URL // endpoint url
|
||||
h url.Values // header values
|
||||
p url.Values // parameters values
|
||||
b io.Reader // body io reader
|
||||
m string // method
|
||||
e *requestError // Error pointer
|
||||
c *atomic.Value // libhtc HTTPClient
|
||||
opt *atomic.Value // Options
|
||||
ctx *atomic.Value // Context function: libctx.FuncContext
|
||||
log *atomic.Value // Default logger : liblog.FuncLog
|
||||
uri *url.URL // endpoint url
|
||||
hdr sync.Map // header values
|
||||
prm url.Values // parameters values
|
||||
bdr BodyRetryer // body io reader
|
||||
mth string // method
|
||||
err *atomic.Value // Error pointer: *requestError
|
||||
cli *atomic.Value // libhtc HTTPClient
|
||||
}
|
||||
|
||||
func (r *request) Clone() (Request, error) {
|
||||
if n, e := r.New(); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
n.CleanHeader()
|
||||
for k := range r.h {
|
||||
n.SetHeader(k, r.h.Get(k))
|
||||
}
|
||||
|
||||
r.hdr.Range(func(key, value any) bool {
|
||||
if u, l := key.(string); !l {
|
||||
return true
|
||||
} else if v, k := value.([]string); !k {
|
||||
return true
|
||||
} else {
|
||||
for _, w := range v {
|
||||
n.AddHeader(u, w)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
n.CleanParams()
|
||||
for k := range r.p {
|
||||
n.SetParams(k, r.p.Get(k))
|
||||
for k := range r.prm {
|
||||
n.SetParams(k, r.prm.Get(k))
|
||||
}
|
||||
|
||||
return n, nil
|
||||
@@ -83,9 +91,6 @@ func (r *request) Clone() (Request, error) {
|
||||
}
|
||||
|
||||
func (r *request) New() (Request, error) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
var (
|
||||
n *request
|
||||
c = r.options()
|
||||
@@ -95,66 +100,103 @@ func (r *request) New() (Request, error) {
|
||||
c = &Options{}
|
||||
}
|
||||
|
||||
if i, e := New(r.x, c, r.client()); e != nil {
|
||||
if i, e := New(r.getFuncContext(), c, r.client()); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
n = i.(*request)
|
||||
}
|
||||
|
||||
if r.u != nil {
|
||||
n.u = &url.URL{
|
||||
Scheme: r.u.Scheme,
|
||||
Opaque: r.u.Opaque,
|
||||
User: r.u.User,
|
||||
Host: r.u.Host,
|
||||
Path: r.u.Path,
|
||||
RawPath: r.u.RawPath,
|
||||
ForceQuery: r.u.ForceQuery,
|
||||
RawQuery: r.u.RawQuery,
|
||||
Fragment: r.u.Fragment,
|
||||
RawFragment: r.u.RawFragment,
|
||||
if r.uri != nil {
|
||||
n.uri = &url.URL{
|
||||
Scheme: r.uri.Scheme,
|
||||
Opaque: r.uri.Opaque,
|
||||
User: r.uri.User,
|
||||
Host: r.uri.Host,
|
||||
Path: r.uri.Path,
|
||||
RawPath: r.uri.RawPath,
|
||||
ForceQuery: r.uri.ForceQuery,
|
||||
RawQuery: r.uri.RawQuery,
|
||||
Fragment: r.uri.Fragment,
|
||||
RawFragment: r.uri.RawFragment,
|
||||
}
|
||||
}
|
||||
|
||||
if r.l != nil {
|
||||
n.l = r.l
|
||||
if r.log != nil {
|
||||
n.log = r.log
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (r *request) context() context.Context {
|
||||
if r.x != nil {
|
||||
if x := r.x(); x != nil {
|
||||
return x
|
||||
func (r *request) RegisterDefaultLogger(fct liblog.FuncLog) {
|
||||
if fct == nil {
|
||||
fct = func() liblog.Logger {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return context.Background()
|
||||
r.log.Store(fct)
|
||||
}
|
||||
|
||||
func (r *request) _getDefaultLogger() liblog.Logger {
|
||||
if i := r.log.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(liblog.FuncLog); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) RegisterContext(fct libctx.FuncContext) {
|
||||
if fct == nil {
|
||||
fct = context.Background
|
||||
}
|
||||
|
||||
r.ctx.Store(fct)
|
||||
}
|
||||
|
||||
func (r *request) getFuncContext() libctx.FuncContext {
|
||||
if i := r.ctx.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(libctx.FuncContext); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) context() context.Context {
|
||||
if f := r.getFuncContext(); f == nil {
|
||||
return context.Background()
|
||||
} else {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) RegisterHTTPClient(cli libhtc.HttpClient) {
|
||||
if cli == nil {
|
||||
cli = libhtc.GetClient()
|
||||
}
|
||||
|
||||
r.cli.Store(cli)
|
||||
}
|
||||
|
||||
func (r *request) client() libhtc.HttpClient {
|
||||
if i := r.c.Load(); i != nil {
|
||||
if i := r.cli.Load(); i != nil {
|
||||
if c, k := i.(libhtc.HttpClient); k {
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
c := libhtc.GetClient()
|
||||
r.c.Store(c)
|
||||
return c
|
||||
return libhtc.GetClient()
|
||||
}
|
||||
|
||||
func (r *request) Error() Error {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
return r.e
|
||||
return r.getError()
|
||||
}
|
||||
|
||||
func (r *request) IsError() bool {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
return r.e != nil && r.e.IsError()
|
||||
err := r.getError()
|
||||
return err.IsError()
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
var (
|
||||
opts = r.GetOption()
|
||||
ednp = r.GetFullUrl()
|
||||
head = make(http.Header)
|
||||
ent logent.Entry
|
||||
)
|
||||
|
||||
@@ -58,14 +59,6 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
ent = log.Entry(loglvl.ErrorLevel, "healthcheck")
|
||||
}
|
||||
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
head := make(url.Values, 0)
|
||||
if v := r.h.Get(_Authorization); v != "" {
|
||||
head.Set(_Authorization, v)
|
||||
}
|
||||
|
||||
if !opts.Health.Enable {
|
||||
return nil
|
||||
}
|
||||
@@ -95,7 +88,7 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
ent.FieldAdd("method", http.MethodGet)
|
||||
}
|
||||
|
||||
req, err = r._MakeRequest(ctx, ednp, http.MethodGet, nil, head, nil)
|
||||
req, err = r.makeRequest(ctx, ednp, http.MethodGet, nil, head, nil)
|
||||
|
||||
if err != nil {
|
||||
if ent != nil {
|
||||
@@ -113,7 +106,7 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if buf, err = r._CheckResponse(rsp); err != nil {
|
||||
if buf, err = r.checkResponse(rsp); err != nil {
|
||||
if ent != nil {
|
||||
ent.ErrorAdd(true, err).Check(loglvl.NilLevel)
|
||||
}
|
||||
@@ -121,7 +114,7 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if len(opts.Health.Result.ValidHTTPCode) > 0 {
|
||||
if !r._IsValidCode(opts.Health.Result.ValidHTTPCode, rsp.StatusCode) {
|
||||
if !r.isValidCode(opts.Health.Result.ValidHTTPCode, rsp.StatusCode) {
|
||||
err = ErrorResponseStatus.Error(fmt.Errorf("status: %s", rsp.Status))
|
||||
if ent != nil {
|
||||
ent.ErrorAdd(true, err).Check(loglvl.NilLevel)
|
||||
@@ -129,7 +122,7 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
} else if len(opts.Health.Result.InvalidHTTPCode) > 0 {
|
||||
if r._IsValidCode(opts.Health.Result.InvalidHTTPCode, rsp.StatusCode) {
|
||||
if r.isValidCode(opts.Health.Result.InvalidHTTPCode, rsp.StatusCode) {
|
||||
err = ErrorResponseStatus.Error(fmt.Errorf("status: %s", rsp.Status))
|
||||
if ent != nil {
|
||||
ent.ErrorAdd(true, err).Check(loglvl.NilLevel)
|
||||
@@ -139,7 +132,7 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if len(opts.Health.Result.Contain) > 0 {
|
||||
if !r._IsValidContents(opts.Health.Result.Contain, buf) {
|
||||
if !r.isValidContents(opts.Health.Result.Contain, buf) {
|
||||
err = ErrorResponseContainsNotFound.Error(nil)
|
||||
if ent != nil {
|
||||
ent.ErrorAdd(true, err).Check(loglvl.NilLevel)
|
||||
@@ -147,7 +140,7 @@ func (r *request) HealthCheck(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
} else if len(opts.Health.Result.NotContain) > 0 {
|
||||
if r._IsValidContents(opts.Health.Result.NotContain, buf) {
|
||||
if r.isValidContents(opts.Health.Result.NotContain, buf) {
|
||||
err = ErrorResponseNotContainsFound.Error(nil)
|
||||
if ent != nil {
|
||||
ent.ErrorAdd(true, err).Check(loglvl.NilLevel)
|
||||
@@ -192,7 +185,7 @@ func (r *request) Monitor(ctx context.Context, vrs libver.Version) (montps.Monit
|
||||
})
|
||||
}
|
||||
|
||||
if mon, e = libmon.New(r.x, inf); e != nil {
|
||||
if mon, e = libmon.New(r.getFuncContext(), inf); e != nil {
|
||||
return nil, e
|
||||
} else if mon == nil {
|
||||
return nil, nil
|
||||
@@ -200,7 +193,7 @@ func (r *request) Monitor(ctx context.Context, vrs libver.Version) (montps.Monit
|
||||
|
||||
mon.RegisterLoggerDefault(r._getDefaultLogger)
|
||||
|
||||
if e = mon.SetConfig(r.x, opt.Health.Monitor); e != nil {
|
||||
if e = mon.SetConfig(r.getFuncContext(), opt.Health.Monitor); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ package request
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
libval "github.com/go-playground/validator/v10"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
@@ -187,9 +186,9 @@ func (o *Options) Update(ctx libctx.FuncContext, req Request) (Request, error) {
|
||||
}
|
||||
|
||||
func (r *request) options() *Options {
|
||||
if r.o == nil {
|
||||
if r.opt == nil {
|
||||
return nil
|
||||
} else if i := r.o.Load(); i == nil {
|
||||
} else if i := r.opt.Load(); i == nil {
|
||||
return nil
|
||||
} else if o, ok := i.(*Options); !ok {
|
||||
return nil
|
||||
@@ -199,8 +198,6 @@ func (r *request) options() *Options {
|
||||
}
|
||||
|
||||
func (r *request) GetOption() *Options {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
return r.options()
|
||||
}
|
||||
|
||||
@@ -215,42 +212,10 @@ func (r *request) SetOption(opt *Options) error {
|
||||
r.AuthBearer(opt.Auth.Bearer.Token)
|
||||
}
|
||||
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
if r.o == nil {
|
||||
r.o = new(atomic.Value)
|
||||
}
|
||||
|
||||
r.o.Store(opt)
|
||||
r.opt.Store(opt)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) RegisterHTTPClient(cli libhtc.HttpClient) {
|
||||
if cli == nil {
|
||||
return
|
||||
}
|
||||
r.c.Store(cli)
|
||||
}
|
||||
|
||||
func (r *request) RegisterDefaultLogger(fct liblog.FuncLog) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
r.l = fct
|
||||
}
|
||||
|
||||
func (r *request) _getDefaultLogger() liblog.Logger {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
if r.l == nil {
|
||||
return nil
|
||||
} else {
|
||||
return r.l()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) defaultTLS() libtls.TLSConfig {
|
||||
if cfg := r.options(); cfg != nil {
|
||||
return cfg.defaultTLS()
|
||||
@@ -258,10 +223,3 @@ func (r *request) defaultTLS() libtls.TLSConfig {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) RegisterContext(fct libctx.FuncContext) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
r.x = fct
|
||||
}
|
||||
|
||||
@@ -29,51 +29,48 @@ package request
|
||||
import "net/url"
|
||||
|
||||
func (r *request) CleanParams() {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
r.p = make(url.Values)
|
||||
r.prm = make(url.Values)
|
||||
}
|
||||
|
||||
func (r *request) DelParams(key string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
r.p.Del(key)
|
||||
r.prm.Del(key)
|
||||
}
|
||||
|
||||
func (r *request) SetParams(key, val string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if len(r.p) < 1 {
|
||||
r.p = make(url.Values)
|
||||
if len(r.prm) < 1 {
|
||||
r.prm = make(url.Values)
|
||||
}
|
||||
|
||||
r.p.Set(key, val)
|
||||
r.prm.Set(key, val)
|
||||
}
|
||||
|
||||
func (r *request) AddParams(key, val string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if len(r.p) < 1 {
|
||||
r.p = make(url.Values)
|
||||
if len(r.prm) < 1 {
|
||||
r.prm = make(url.Values)
|
||||
}
|
||||
|
||||
r.p.Set(key, val)
|
||||
r.prm.Set(key, val)
|
||||
}
|
||||
|
||||
func (r *request) GetFullUrl() *url.URL {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
return r.u
|
||||
return r.uri
|
||||
}
|
||||
|
||||
func (r *request) SetFullUrl(u *url.URL) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
r.u = u
|
||||
r.uri = u
|
||||
}
|
||||
|
||||
@@ -38,23 +38,23 @@ import (
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
)
|
||||
|
||||
func (r *request) _MakeRequest(ctx context.Context, u *url.URL, mtd string, body io.Reader, head url.Values, params url.Values) (*http.Request, error) {
|
||||
func (r *request) makeRequest(ctx context.Context, u *url.URL, mtd string, body BodyRetryer, head http.Header, params url.Values) (*http.Request, error) {
|
||||
var (
|
||||
req *http.Request
|
||||
err error
|
||||
)
|
||||
|
||||
req, err = http.NewRequestWithContext(ctx, mtd, u.String(), body)
|
||||
if body != nil {
|
||||
req, err = http.NewRequestWithContext(ctx, mtd, u.String(), body.Retry())
|
||||
} else {
|
||||
req, err = http.NewRequestWithContext(ctx, mtd, u.String(), nil)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, ErrorCreateRequest.Error(err)
|
||||
}
|
||||
|
||||
if len(head) > 0 {
|
||||
for k := range head {
|
||||
req.Header.Set(k, head.Get(k))
|
||||
}
|
||||
}
|
||||
req.Header = head
|
||||
|
||||
if len(params) > 0 {
|
||||
q := req.URL.Query()
|
||||
@@ -67,7 +67,7 @@ func (r *request) _MakeRequest(ctx context.Context, u *url.URL, mtd string, body
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (r *request) _CheckResponse(rsp *http.Response, validStatus ...int) (*bytes.Buffer, error) {
|
||||
func (r *request) checkResponse(rsp *http.Response, validStatus ...int) (*bytes.Buffer, error) {
|
||||
var (
|
||||
e error
|
||||
b = bytes.NewBuffer(make([]byte, 0))
|
||||
@@ -89,14 +89,14 @@ func (r *request) _CheckResponse(rsp *http.Response, validStatus ...int) (*bytes
|
||||
}
|
||||
}
|
||||
|
||||
if !r._IsValidCode(validStatus, rsp.StatusCode) {
|
||||
if !r.isValidCode(validStatus, rsp.StatusCode) {
|
||||
return b, ErrorResponseStatus.Error(nil)
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (r *request) _IsValidCode(listValid []int, statusCode int) bool {
|
||||
func (r *request) isValidCode(listValid []int, statusCode int) bool {
|
||||
if len(listValid) < 1 {
|
||||
return true
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func (r *request) _IsValidCode(listValid []int, statusCode int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *request) _IsValidContents(contains []string, buf *bytes.Buffer) bool {
|
||||
func (r *request) isValidContents(contains []string, buf *bytes.Buffer) bool {
|
||||
if len(contains) < 1 {
|
||||
return true
|
||||
} else if buf.Len() < 1 {
|
||||
@@ -127,39 +127,37 @@ func (r *request) _IsValidContents(contains []string, buf *bytes.Buffer) bool {
|
||||
}
|
||||
|
||||
func (r *request) Do() (*http.Response, error) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if r.m == "" || r.u == nil || r.u.String() == "" {
|
||||
if r.mth == "" || r.uri == nil || r.uri.String() == "" {
|
||||
return nil, ErrorParamInvalid.Error(nil)
|
||||
}
|
||||
|
||||
var (
|
||||
e error
|
||||
req *http.Request
|
||||
rer *requestError
|
||||
rsp *http.Response
|
||||
err error
|
||||
)
|
||||
|
||||
r.e = &requestError{
|
||||
c: 0,
|
||||
s: "",
|
||||
se: false,
|
||||
b: bytes.NewBuffer(make([]byte, 0)),
|
||||
be: false,
|
||||
e: nil,
|
||||
}
|
||||
r.newError()
|
||||
rer = r.getError()
|
||||
|
||||
req, err = r.makeRequest(r.context(), r.uri, r.mth, r.bdr, r.httpHeader(), r.prm)
|
||||
|
||||
req, err = r._MakeRequest(r.context(), r.u, r.m, r.b, r.h, r.p)
|
||||
if err != nil {
|
||||
r.e.e = err
|
||||
return nil, err
|
||||
rer.err = err
|
||||
r.setError(rer)
|
||||
return nil, ErrorCreateRequest.Error(err)
|
||||
}
|
||||
|
||||
rsp, e = r.client().Do(req)
|
||||
|
||||
if e != nil {
|
||||
r.e.e = e
|
||||
rer.err = e
|
||||
r.setError(rer)
|
||||
return nil, ErrorSendRequest.Error(e)
|
||||
}
|
||||
|
||||
@@ -173,40 +171,35 @@ func (r *request) DoParse(model interface{}, validStatus ...int) error {
|
||||
|
||||
err error
|
||||
rsp *http.Response
|
||||
rer *requestError
|
||||
)
|
||||
|
||||
r.e = &requestError{
|
||||
c: 0,
|
||||
s: "",
|
||||
se: false,
|
||||
b: bytes.NewBuffer(make([]byte, 0)),
|
||||
be: false,
|
||||
e: nil,
|
||||
}
|
||||
|
||||
if rsp, err = r.Do(); err != nil {
|
||||
return err
|
||||
} else if rsp == nil {
|
||||
return ErrorResponseInvalid.Error(nil)
|
||||
} else {
|
||||
r.e.c = rsp.StatusCode
|
||||
r.e.s = rsp.Status
|
||||
rer = r.getError()
|
||||
rer.code = rsp.StatusCode
|
||||
rer.status = rsp.Status
|
||||
}
|
||||
|
||||
b, err = r._CheckResponse(rsp, validStatus...)
|
||||
r.e.b = b
|
||||
b, err = r.checkResponse(rsp, validStatus...)
|
||||
rer.bufBody = b
|
||||
|
||||
if er := liberr.Get(err); er != nil && er.HasCode(ErrorResponseStatus) {
|
||||
r.e.se = true
|
||||
rer.statusErr = true
|
||||
} else if err != nil {
|
||||
r.e.e = err
|
||||
rer.err = err
|
||||
r.setError(rer)
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Len() > 0 {
|
||||
if e = json.Unmarshal(b.Bytes(), model); e != nil {
|
||||
r.e.be = true
|
||||
r.e.e = e
|
||||
rer.bodyErr = true
|
||||
rer.err = e
|
||||
r.setError(rer)
|
||||
return ErrorResponseUnmarshall.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,45 +37,45 @@ func (r *request) SetEndpoint(u string) error {
|
||||
if uri, err := url.Parse(u); err != nil {
|
||||
return err
|
||||
} else {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
r.u = uri
|
||||
r.uri = uri
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) GetEndpoint() string {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
return r.u.String()
|
||||
return r.uri.String()
|
||||
}
|
||||
|
||||
func (r *request) SetPath(raw bool, path string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if raw {
|
||||
r.u.RawPath = path
|
||||
r.uri.RawPath = path
|
||||
} else {
|
||||
r.u.Path = path
|
||||
r.uri.Path = path
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) AddPath(raw bool, pathPart ...string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if r.u == nil {
|
||||
if r.uri == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var str string
|
||||
if raw {
|
||||
str = path.Clean(r.u.RawPath)
|
||||
str = path.Clean(r.uri.RawPath)
|
||||
} else {
|
||||
str = path.Clean(r.u.Path)
|
||||
str = path.Clean(r.uri.Path)
|
||||
}
|
||||
|
||||
for i := range pathPart {
|
||||
@@ -91,47 +91,47 @@ func (r *request) AddPath(raw bool, pathPart ...string) {
|
||||
}
|
||||
|
||||
if raw {
|
||||
r.u.RawPath = path.Clean(str)
|
||||
r.uri.RawPath = path.Clean(str)
|
||||
} else {
|
||||
r.u.Path = path.Clean(str)
|
||||
r.uri.Path = path.Clean(str)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) SetMethod(method string) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
switch strings.ToUpper(method) {
|
||||
case http.MethodGet:
|
||||
r.m = http.MethodGet
|
||||
r.mth = http.MethodGet
|
||||
case http.MethodHead:
|
||||
r.m = http.MethodHead
|
||||
r.mth = http.MethodHead
|
||||
case http.MethodPost:
|
||||
r.m = http.MethodPost
|
||||
r.mth = http.MethodPost
|
||||
case http.MethodPut:
|
||||
r.m = http.MethodPut
|
||||
r.mth = http.MethodPut
|
||||
case http.MethodPatch:
|
||||
r.m = http.MethodPatch
|
||||
r.mth = http.MethodPatch
|
||||
case http.MethodDelete:
|
||||
r.m = http.MethodDelete
|
||||
r.mth = http.MethodDelete
|
||||
case http.MethodConnect:
|
||||
r.m = http.MethodConnect
|
||||
r.mth = http.MethodConnect
|
||||
case http.MethodOptions:
|
||||
r.m = http.MethodOptions
|
||||
r.mth = http.MethodOptions
|
||||
case http.MethodTrace:
|
||||
r.m = http.MethodTrace
|
||||
r.mth = http.MethodTrace
|
||||
default:
|
||||
r.m = strings.ToUpper(method)
|
||||
r.mth = strings.ToUpper(method)
|
||||
}
|
||||
|
||||
if r.m == "" {
|
||||
r.m = http.MethodGet
|
||||
if r.mth == "" {
|
||||
r.mth = http.MethodGet
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) GetMethod() string {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
return r.m
|
||||
return r.mth
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user