github.com/profzone/eden-framework@v1.0.10/pkg/courier/transport_http/request.go (about) 1 package transport_http 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "net" 8 "net/http" 9 "strings" 10 "time" 11 12 "github.com/sirupsen/logrus" 13 14 "github.com/profzone/eden-framework/pkg/courier" 15 "github.com/profzone/eden-framework/pkg/courier/httpx" 16 "github.com/profzone/eden-framework/pkg/courier/status_error" 17 "github.com/profzone/eden-framework/pkg/courier/transport_http/transform" 18 "github.com/profzone/eden-framework/pkg/duration" 19 ) 20 21 type TransportWrapper func(rt http.RoundTripper) http.RoundTripper 22 23 type HttpRequest struct { 24 BaseURL string 25 Method string 26 URI string 27 ID string 28 Metadata courier.Metadata 29 Timeout time.Duration 30 Req interface{} 31 WrapTransport TransportWrapper 32 } 33 34 func (httpRequest *HttpRequest) Do() (result courier.Result) { 35 result = courier.Result{} 36 request, err := transform.NewRequest(httpRequest.Method, httpRequest.BaseURL+httpRequest.URI, httpRequest.Req, httpRequest.Metadata) 37 if err != nil { 38 result.Err = status_error.InvalidRequestParams.StatusError().WithDesc(err.Error()) 39 return 40 } 41 42 d := duration.NewDuration() 43 defer func() { 44 logger := d.ToLogger().WithFields(logrus.Fields{ 45 "request": httpRequest.ID, 46 "method": httpRequest.Method, 47 "url": request.URL.String(), 48 "metadata": httpRequest.Metadata, 49 }) 50 51 if result.Err == nil { 52 logger.Debugf("success") 53 } else { 54 logger.Warnf("do http request failed %s", result.Err) 55 } 56 }() 57 58 httpClient := GetShortConnClient(httpRequest.Timeout) 59 60 if httpRequest.WrapTransport != nil { 61 httpClient.Transport = httpRequest.WrapTransport(httpClient.Transport) 62 } 63 64 resp, err := httpClient.Do(request) 65 if err != nil { 66 result.Err = status_error.HttpRequestFailed.StatusError().WithDesc(err.Error()) 67 return 68 } 69 defer resp.Body.Close() 70 71 data, err := ioutil.ReadAll(resp.Body) 72 73 result.Data = data 74 result.Meta = courier.Metadata(resp.Header) 75 76 contentType := resp.Header.Get(httpx.HeaderContentType) 77 78 if strings.Contains(contentType, httpx.MIME_JSON) { 79 result.Unmarshal = json.Unmarshal 80 // todo add more structUnmarshal 81 } 82 83 if !HttpStatusOK(resp.StatusCode) { 84 statusError := &status_error.StatusError{} 85 err := json.Unmarshal(result.Data, statusError) 86 if err != nil { 87 msg := fmt.Sprintf("[%d] %s %s", resp.StatusCode, request.Method, request.URL) 88 result.Err = status_error.HttpRequestFailed.StatusError().WithDesc(msg) 89 return 90 } 91 result.Err = statusError 92 } 93 return 94 } 95 96 func HttpStatusOK(code int) bool { 97 return code >= http.StatusOK && code < http.StatusMultipleChoices 98 } 99 100 func GetShortConnClient(timeout time.Duration) *http.Client { 101 return &http.Client{ 102 Timeout: timeout, 103 Transport: &http.Transport{ 104 Dial: (&net.Dialer{ 105 Timeout: timeout, 106 KeepAlive: 0, 107 }).Dial, 108 DisableKeepAlives: true, 109 }, 110 } 111 } 112 113 func GetLongConnClient(timeout time.Duration) *http.Client { 114 return &http.Client{ 115 Timeout: timeout, 116 Transport: &http.Transport{ 117 Dial: (&net.Dialer{ 118 Timeout: timeout, 119 KeepAlive: 0, 120 }).Dial, 121 DisableKeepAlives: false, 122 }, 123 } 124 }