Skip to content

Commit

Permalink
Package Request:
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
nabbar committed Jun 14, 2024
1 parent 2d70f14 commit 26d297e
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 275 deletions.
57 changes: 49 additions & 8 deletions request/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
}

func (r *request) _BodyReader(body io.Reader) {
r.s.Lock()
defer r.s.Unlock()
return nil
}

r.b = body
func (r *request) _BodyReader(body BodyRetryer) {
r.bdr = body
}
73 changes: 58 additions & 15 deletions request/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
67 changes: 47 additions & 20 deletions request/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ package request

import (
"fmt"
"net/url"
"net/http"
)

func (r *request) ContentType(mime string) {
Expand All @@ -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()
r.hdr.Store(key, append(make([]string, 0), value))
}

if len(r.h) < 1 {
r.h = make(url.Values)
func (r *request) AddHeader(key, value string) {
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.Set(key, value)
}
if len(val) < 1 {
val = make([]string, 0)
}

func (r *request) AddHeader(key, value string) {
r.s.Lock()
defer r.s.Unlock()
r.hdr.Store(key, append(val, value))
}

if len(r.h) < 1 {
r.h = make(url.Values)
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
}
}

r.h.Add(key, value)
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
}
32 changes: 18 additions & 14 deletions request/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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: make(url.Values),
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 {
Expand Down
Loading

0 comments on commit 26d297e

Please sign in to comment.