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:
Nicolas JUHEL
2024-06-14 11:44:06 +02:00
parent 2d70f142e6
commit b23addbfad
10 changed files with 374 additions and 276 deletions

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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()
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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
}