diff --git a/config.go b/config.go index 3c05e86..337e1d2 100644 --- a/config.go +++ b/config.go @@ -6,6 +6,8 @@ import ( "net/http" "net/url" "time" + + "github.com/tinh-tinh/tinhtinh/v2/core" ) type Config struct { @@ -27,6 +29,10 @@ type Config struct { ResponseType string // Cancel token CancelToken context.Context + // Encoder + Encoder core.Encode + // Decoder + Decoder core.Decode } // GetConfig returns a new *http.Request with the given method, uri and input. @@ -40,7 +46,7 @@ func (f *Fetch) GetConfig(method string, uri string, input io.Reader) (*http.Req formatUrl = f.Config.BaseUrl } - formatUrl += IfSlashPrefixString(uri) + formatUrl += core.IfSlashPrefixString(uri) if len(f.Config.Params) > 0 { formatUrl += "?" + ParseQuery(f.Config.Params) } diff --git a/fetch.go b/fetch.go index 4b1bd4a..e8d31ba 100644 --- a/fetch.go +++ b/fetch.go @@ -1,6 +1,7 @@ package fetch import ( + "encoding/json" "io" "net/http" ) @@ -15,6 +16,12 @@ type Fetch struct { // The configuration includes details like BaseUrl, Headers, Params, and more, // which are used to customize HTTP requests made by the Fetch instance. func Create(config *Config) *Fetch { + if config.Encoder == nil { + config.Encoder = json.Marshal + } + if config.Decoder == nil { + config.Decoder = json.Unmarshal + } return &Fetch{ Config: config, } @@ -51,7 +58,7 @@ func (f *Fetch) Post(url string, data interface{}, params ...interface{}) *Respo url += "?" + ParseQuery(params) } - return f.do("POST", url, ParseData(data)) + return f.do("POST", url, ParseData(data, f.Config.Encoder)) } // Patch makes a PATCH request to the specified URL and returns a Response @@ -70,7 +77,7 @@ func (f *Fetch) Patch(url string, data interface{}, params ...interface{}) *Resp url += "?" + ParseQuery(params) } - return f.do("PATCH", url, ParseData(data)) + return f.do("PATCH", url, ParseData(data, f.Config.Encoder)) } // Put makes a PUT request to the specified URL and returns a Response @@ -89,7 +96,7 @@ func (f *Fetch) Put(url string, data interface{}, params ...interface{}) *Respon url += "?" + ParseQuery(params) } - return f.do("PUT", url, ParseData(data)) + return f.do("PUT", url, ParseData(data, f.Config.Encoder)) } // Delete makes a DELETE request to the specified URL and returns a Response @@ -133,7 +140,9 @@ func (f *Fetch) do(method string, uri string, input io.Reader) *Response { client.Timeout = f.Config.Timeout } - response := &Response{} + response := &Response{ + decoder: f.Config.Decoder, + } resp, err := client.Do(req) if err != nil { response.Error = err diff --git a/response.go b/response.go index 5459d47..eaa2f63 100644 --- a/response.go +++ b/response.go @@ -1,19 +1,22 @@ package fetch -import "encoding/json" +import ( + "github.com/tinh-tinh/tinhtinh/v2/core" +) type Response struct { Data []byte Status int StatusText string Error error + decoder core.Decode } // Format deserializes the response data into the given model. If the model is nil, the method does nothing. // If the deserialization fails, the error is stored in the Response instance. func (r *Response) Format(model interface{}) *Response { if model != nil { - err := json.Unmarshal(r.Data, model) + err := r.decoder(r.Data, model) if err != nil { r.Error = err } diff --git a/response_test.go b/response_test.go index 914f35e..0aa3767 100644 --- a/response_test.go +++ b/response_test.go @@ -27,6 +27,7 @@ func Test_Schema(t *testing.T) { res := instance.Get("comments", &QueryComment{ PostID: 1, }).Format(&comments) + require.Nil(t, res.Error) require.Equal(t, 200, res.Status) if len(comments) > 0 { diff --git a/utils.go b/utils.go index 69ee503..fd6a686 100644 --- a/utils.go +++ b/utils.go @@ -1,13 +1,14 @@ package fetch import ( - "encoding/json" "fmt" "io" "log" "reflect" "strconv" "strings" + + "github.com/tinh-tinh/tinhtinh/v2/core" ) // ParseQuery takes an interface{} argument and returns a string representing @@ -99,34 +100,13 @@ func ParseQuery(queryVal interface{}) string { // containing the JSON data. If the input data is nil, the function returns nil. // If the serialization fails, the function panics. The returned io.Reader can // be used to read the JSON data as a stream. -func ParseData(data interface{}) io.Reader { +func ParseData(data interface{}, encoder core.Encode) io.Reader { if data == nil { return nil } - buffer, err := json.Marshal(data) + buffer, err := encoder(data) if err != nil { panic(err) } return strings.NewReader(string(buffer)) } - -// IfSlashPrefixString trims a trailing slash from the string if present, -// and ensures that the resulting string has a leading slash. If the input -// string is empty, it returns the empty string. The function formats the -// string using the ToFormat function before returning it. -func IfSlashPrefixString(s string) string { - if s == "" { - return s - } - s = strings.TrimSuffix(s, "/") - if strings.HasPrefix(s, "/") { - return ToFormat(s) - } - return "/" + ToFormat(s) -} - -// ToFormat takes a string and returns a formatted string. The string is -// converted to lowercase and spaces are removed. -func ToFormat(s string) string { - return strings.ReplaceAll(s, " ", "") -} diff --git a/utils_test.go b/utils_test.go index f1d84f9..ad46632 100644 --- a/utils_test.go +++ b/utils_test.go @@ -1,6 +1,7 @@ package fetch_test import ( + "encoding/json" "strings" "testing" @@ -78,10 +79,10 @@ func Test_ParseData(t *testing.T) { Age: 13, } - str := fetch.ParseData(data) + str := fetch.ParseData(data, json.Marshal) reader := strings.NewReader("{\"name\":\"Abc\",\"age\":13}") require.Equal(t, reader, str) - null := fetch.ParseData(nil) + null := fetch.ParseData(nil, json.Marshal) require.Nil(t, null) }