Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- connect with me through social media networks
- GitHub: https://github.com/restuwahyu13
- Linkedin: https://www.linkedin.com/in/restuwahyu13
- UpWork: https://www.upwork.com/freelancers/~016e91d99e2bf0bdcf
- */
- package helpers
- import (
- "bytes"
- "context"
- "crypto/tls"
- "errors"
- "fmt"
- "io"
- "net"
- "net/http"
- "net/http/httputil"
- "strings"
- "time"
- "github.com/sirupsen/logrus"
- ahelpers "github.com/x-id/worker/internal/domain/adapters/helpers"
- dto "github.com/x-id/worker/internal/domain/dto/helpers"
- )
- type (
- roundTripper struct {
- Transport http.RoundTripper
- Headers map[string]string
- }
- httpClient struct {
- transport *roundTripper
- ctx context.Context
- }
- )
- func NewHttpClient(ctx context.Context) ahelpers.HttpClient {
- transport := &roundTripper{
- Transport: &http.Transport{
- ReadBufferSize: http.DefaultMaxHeaderBytes,
- TLSClientConfig: &tls.Config{
- MinVersion: tls.VersionTLS12,
- InsecureSkipVerify: true,
- },
- },
- }
- return &httpClient{ctx: ctx, transport: transport}
- }
- /**
- * ===========================================
- * HANDLER METHOD - WithoutFormData
- * ===========================================
- **/
- func (h *httpClient) WithoutFormData(options *dto.HttpClientOptions, dest any) (*http.Response, error) {
- var (
- req *http.Request = nil
- bodyBytes *bytes.Buffer = nil
- dataByte []byte = nil
- err error = nil
- parser ahelpers.Parser = NewParser()
- )
- timeout := time.Second * 65
- ctx, cancel := context.WithTimeout(h.ctx, timeout)
- defer cancel()
- h.transport.Headers = options.Configs.Headers
- if options.Method != http.MethodGet && options.Method != http.MethodHead && options.Method != http.MethodOptions {
- if options.DataJson != nil {
- data, err := NewParser().Marshal(options.DataJson)
- if err != nil {
- return nil, err
- }
- dataByte = data
- }
- bodyBytes = bytes.NewBuffer(dataByte)
- } else {
- bodyBytes = bytes.NewBuffer(nil)
- }
- for {
- select {
- case <-ctx.Done():
- if err := ctx.Err(); err != nil {
- h.ctx = context.Background()
- req, err = http.NewRequest(options.Method, options.Url, bodyBytes)
- if err != nil {
- if err.(net.Error).Timeout() {
- return nil, errors.New("External network timeout")
- }
- return nil, err
- }
- return h.withoutFormData(req, parser, timeout, dest)
- }
- default:
- req, err = http.NewRequestWithContext(h.ctx, options.Method, options.Url, bodyBytes)
- if err != nil {
- if err.(net.Error).Timeout() {
- return nil, errors.New("External network timeout")
- }
- return nil, err
- }
- return h.withoutFormData(req, parser, timeout, dest)
- }
- }
- }
- func (h *httpClient) withoutFormData(req *http.Request, parser ahelpers.Parser, timeout time.Duration, dest any) (*http.Response, error) {
- req.Header.Add("Content-Type", "application/json")
- res, err := h.transport.RoundTrip(req)
- if err != nil {
- return nil, err
- }
- h.transport.httpRequestDump(req)
- h.transport.httpResponseDump(res)
- client := http.Client{Transport: h.transport, Timeout: timeout}
- if res, err := client.Do(req); err != nil {
- return res, err
- }
- buffer, err := io.ReadAll(res.Body)
- if err != nil {
- return nil, err
- }
- defer res.Body.Close()
- res.Body = io.NopCloser(io.MultiReader(bytes.NewReader(buffer), res.Body))
- if !strings.Contains(string(buffer), "html") {
- if err := parser.Decode(res.Body, dest); err != nil {
- return nil, err
- }
- defer res.Body.Close()
- return res, nil
- } else {
- return res, errors.New("Output is not as expected")
- }
- }
- /**
- * ===========================================
- * HANDLER METHOD - WithFormData
- * ===========================================
- **/
- func (h *httpClient) WithFormData(options *dto.HttpClientOptions, dest any) (*http.Response, error) {
- var (
- req *http.Request = nil
- err error = nil
- parser ahelpers.Parser = NewParser()
- )
- timeout := time.Second * 65
- ctx, cancel := context.WithTimeout(h.ctx, timeout)
- defer cancel()
- h.transport.Headers = options.Configs.Headers
- for {
- select {
- case <-ctx.Done():
- if err := ctx.Err(); err != nil {
- h.ctx = context.Background()
- req, err = http.NewRequest(options.Method, options.Url, bytes.NewBuffer([]byte(options.DataForm.Encode())))
- if err != nil {
- if err.(net.Error).Timeout() {
- return nil, errors.New("External network timeout")
- }
- return nil, err
- }
- return h.formData(req, parser, timeout, dest)
- }
- default:
- req, err = http.NewRequestWithContext(h.ctx, options.Method, options.Url, bytes.NewBuffer([]byte(options.DataForm.Encode())))
- if err != nil {
- if err.(net.Error).Timeout() {
- return nil, errors.New("External network timeout")
- }
- return nil, err
- }
- return h.formData(req, parser, timeout, dest)
- }
- }
- }
- func (h *httpClient) formData(req *http.Request, parser ahelpers.Parser, timeout time.Duration, dest any) (*http.Response, error) {
- req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
- res, err := h.transport.RoundTrip(req)
- if err != nil {
- return nil, err
- }
- h.transport.httpRequestDump(req)
- h.transport.httpResponseDump(res)
- client := http.Client{Transport: h.transport, Timeout: timeout}
- if res, err := client.Do(req); err != nil {
- return res, err
- }
- buffer, err := io.ReadAll(res.Body)
- if err != nil {
- return nil, err
- }
- defer res.Body.Close()
- res.Body = io.NopCloser(io.MultiReader(bytes.NewReader(buffer), res.Body))
- if !strings.Contains(string(buffer), "html") {
- res.Body = io.NopCloser(res.Body)
- if err := parser.Decode(res.Body, dest); err != nil {
- return nil, err
- }
- defer res.Body.Close()
- return res, nil
- } else {
- return res, errors.New("Output is not as expected")
- }
- }
- /**
- * ===========================================
- * HANDLER METHOD - RoundTripper
- * ===========================================
- **/
- func (h *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- if h.Headers != nil {
- for k, v := range h.Headers {
- req.Header.Add(k, v)
- }
- }
- return http.DefaultTransport.RoundTrip(req)
- }
- func (h *roundTripper) httpRequestDump(req *http.Request) {
- dumpReq, err := httputil.DumpRequest(req, true)
- if err != nil {
- logrus.Errorf("RoundTripper httpRequestDump - httputil.DumpRequest: %v", err)
- return
- }
- fmt.Print("\n\n\n")
- fmt.Println("=============== START DUMP HTTP REQUEST ================")
- fmt.Print("\n")
- fmt.Println(string(dumpReq))
- fmt.Print("\n")
- fmt.Println("=============== END DUMP HTTP REQUEST =================")
- fmt.Print("\n\n\n")
- }
- func (h *roundTripper) httpResponseDump(res *http.Response) {
- dumpRes, err := httputil.DumpResponse(res, true)
- if err != nil {
- logrus.Errorf("RoundTripper httpResponseDump - httputil.DumpResponse: %v", err)
- return
- }
- fmt.Print("\n\n\n")
- fmt.Println("=============== START DUMP HTTP RESPONSE ================")
- fmt.Print("\n")
- fmt.Println(string(dumpRes))
- fmt.Print("\n")
- fmt.Println("=============== END DUMP HTTP RESPONSE =================")
- fmt.Print("\n\n\n")
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement