github.com/iikira/iikira-go-utils@v0.0.0-20230610031953-f2cb11cde33a/requester/fetch.go (about)

     1  package requester
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/iikira/iikira-go-utils/requester/rio"
     7  	"io"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"net/url"
    11  	"strings"
    12  )
    13  
    14  // HTTPGet 简单实现 http 访问 GET 请求
    15  func HTTPGet(urlStr string) (body []byte, err error) {
    16  	resp, err := DefaultClient.Get(urlStr)
    17  	if resp != nil {
    18  		defer resp.Body.Close()
    19  	}
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	return ioutil.ReadAll(resp.Body)
    24  }
    25  
    26  // Req 参见 *HTTPClient.Req, 使用默认 http 客户端
    27  func Req(method string, urlStr string, post interface{}, header map[string]string) (resp *http.Response, err error) {
    28  	return DefaultClient.Req(method, urlStr, post, header)
    29  }
    30  
    31  // Fetch 参见 *HTTPClient.Fetch, 使用默认 http 客户端
    32  func Fetch(method string, urlStr string, post interface{}, header map[string]string) (body []byte, err error) {
    33  	return DefaultClient.Fetch(method, urlStr, post, header)
    34  }
    35  
    36  // Req 实现 http/https 访问,
    37  // 根据给定的 method (GET, POST, HEAD, PUT 等等), urlStr (网址),
    38  // post (post 数据), header (header 请求头数据), 进行网站访问。
    39  // 返回值分别为 *http.Response, 错误信息
    40  func (h *HTTPClient) Req(method string, urlStr string, post interface{}, header map[string]string) (resp *http.Response, err error) {
    41  	h.lazyInit()
    42  	var (
    43  		req           *http.Request
    44  		obody         io.Reader
    45  		contentLength int64
    46  		contentType   string
    47  	)
    48  
    49  	if post != nil {
    50  		switch value := post.(type) {
    51  		case io.Reader:
    52  			obody = value
    53  		case map[string]string:
    54  			query := url.Values{}
    55  			for k := range value {
    56  				query.Set(k, value[k])
    57  			}
    58  			obody = strings.NewReader(query.Encode())
    59  			contentType = "application/x-www-form-urlencoded"
    60  		case map[string]interface{}:
    61  			query := url.Values{}
    62  			for k := range value {
    63  				query.Set(k, fmt.Sprint(value[k]))
    64  			}
    65  			obody = strings.NewReader(query.Encode())
    66  			contentType = "application/x-www-form-urlencoded"
    67  		case map[interface{}]interface{}:
    68  			query := url.Values{}
    69  			for k := range value {
    70  				query.Set(fmt.Sprint(k), fmt.Sprint(value[k]))
    71  			}
    72  			obody = strings.NewReader(query.Encode())
    73  			contentType = "application/x-www-form-urlencoded"
    74  		case string:
    75  			obody = strings.NewReader(value)
    76  		case []byte:
    77  			obody = bytes.NewReader(value[:])
    78  		default:
    79  			return nil, fmt.Errorf("requester.Req: unknown post type: %s", value)
    80  		}
    81  
    82  		switch value := post.(type) {
    83  		case ContentLengther:
    84  			contentLength = value.ContentLength()
    85  		case rio.Lener:
    86  			contentLength = int64(value.Len())
    87  		case rio.Lener64:
    88  			contentLength = value.Len()
    89  		}
    90  
    91  		switch value := post.(type) {
    92  		case ContentTyper:
    93  			contentType = value.ContentType()
    94  		}
    95  	}
    96  	req, err = http.NewRequest(method, urlStr, obody)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  
   101  	if req.ContentLength <= 0 && contentLength != 0 {
   102  		req.ContentLength = contentLength
   103  	}
   104  
   105  	// 设置浏览器标识
   106  	req.Header.Set("User-Agent", h.UserAgent)
   107  
   108  	// 设置Content-Type
   109  	if contentType != "" {
   110  		req.Header.Set("Content-Type", contentType)
   111  	}
   112  
   113  	if header != nil {
   114  		// 处理Host
   115  		if host, ok := header["Host"]; ok {
   116  			req.Host = host
   117  		}
   118  
   119  		for key := range header {
   120  			req.Header.Set(key, header[key])
   121  		}
   122  	}
   123  
   124  	return h.Client.Do(req)
   125  }
   126  
   127  // Fetch 实现 http/https 访问,
   128  // 根据给定的 method (GET, POST, HEAD, PUT 等等), urlStr (网址),
   129  // post (post 数据), header (header 请求头数据), 进行网站访问。
   130  // 返回值分别为 网站主体, 错误信息
   131  func (h *HTTPClient) Fetch(method string, urlStr string, post interface{}, header map[string]string) (body []byte, err error) {
   132  	h.lazyInit()
   133  	resp, err := h.Req(method, urlStr, post, header)
   134  	if resp != nil {
   135  		defer resp.Body.Close()
   136  	}
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	return ioutil.ReadAll(resp.Body)
   142  }