GET请求
func CurlGetWithParam(link string, param map[string]string) (response string, err error) {
u, _ := url.Parse(link)
q := u.Query()
for k, val := range param {
q.Set(k, val)
}
u.RawQuery = q.Encode()
link = u.String()
resp, err := http.Get(link)
if err != nil {
return response, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return string(body), nil
}
POST请求
由于数据在请求体中,根据数据的解析规则,POST有几种Content-Type,具体说明可以阅读 https://blog.csdn.net/raoxiaoya/article/details/106446863
Content-Type常用的两种格式:multipart/form-data, application/x-www-form-urlencoded
1、multipart/form-data
可以上传文件,数据以boundary分割,类似于 multipart/form-data; boundary---------------xxxxxxxxxx
根据Content-Type,接收者就可以解析数据了。
boundary后面的字符串是随机生成的。
func CurlPostWithParam4(link string, param map[string][]string, header map[string]string, files map[string]string) (response string, err error) {
data := &bytes.Buffer{}
writer := multipart.NewWriter(data)
// 处理文件内容
for name, path := range files {
part, err := writer.CreateFormFile(name, path)
if err != nil {
return response, err
}
f, err := os.Open(path)
if err != nil {
return response, err
}
_, err = io.Copy(part, f)
if err != nil {
return response, err
}
}
// 处理其他字段
for k, sli := range param {
for _, s := range sli {
writer.WriteField(k, s)
}
}
err = writer.Close()
if err != nil {
return response, err
}
// 查看数据流
// p, _ := ioutil.ReadAll(data)
// fmt.Println(string(p))
req, err := http.NewRequest("POST", link, data)
if err != nil {
return response, err
}
// 处理header
for k, v := range header {
req.Header.Set(k, v)
}
// **** 重要
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return response, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return string(body), nil
}
本函数支持header, 文件,切片value
func main() {
p4 := map[string][]string{"key": {"aaaa"}, "id": {"123", "456"}}
file := map[string]string{"out": "./note.ttt"}
rep4, err := CurlPostWithParam4("http://192.168.2.157:8000/vote2/Vote", p4, nil, file)
fmt.Println(rep4)
fmt.Println(err)
}
查看打印数据流
p, _ := ioutil.ReadAll(data)
fmt.Println(string(p))
打印信息:
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="out"; filename="./note.ttt"
Content-Type: application/octet-stream
aaaaaaa
bbbbbbb
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="key"
aaaa
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="id"
123
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="id"
456
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf--
2、application/x-www-form-urlencoded
发送普通key-value,以&拼接。
func CurlPostWithParam1(link string, param map[string]string) (response string, err error) {
str := ""
for k, val := range param {
if str == "" {
str = k + "=" + val
} else {
str = str + "&" + k + "=" + val
}
}
r := strings.NewReader(str)
resp, err := http.Post(link, "application/x-www-form-urlencoded", r)
if err != nil {
return response, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return string(body), nil
}
发送的value是一个切片,也就是可以发送数组。
func CurlPostWithParam2(link string, param map[string][]string) (response string, err error) {
// fmt.Println(url.Values(param).Encode()) // id=123&key=Value&key=aaaa
resp, err := http.PostForm(link, url.Values(param))
if err != nil {
return response, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return string(body), nil
}
带请求头的
func CurlPostWithParam3(link string, param map[string][]string, header map[string]string) (response string, err error) {
r := strings.NewReader(url.Values(param).Encode())
req, err := http.NewRequest("POST", link, r)
if err != nil {
return response, err
}
for k, v := range header {
req.Header.Set(k, v)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return response, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return string(body), nil
}
3、其他类型
如果要传递的数据是自定义格式的,接收者自定义解析的,比如 json, xml。
text => text/plain
javascript => application/javascript
json => application/json
html => text/html
xml => application/xml
可通过设置 req.Header.Set(“Content-Type”, “application/json”)
func CurlPostWithParam5(link string, param string, header map[string]string) (response string, err error) {
r := strings.NewReader(param)
req, err := http.NewRequest("POST", link, r)
if err != nil {
return response, err
}
for k, v := range header {
req.Header.Set(k, v)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return response, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return string(body), nil
}
超时设置
超时设置是在 http.Client 对象里面的 Timeout 字段
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
http 包下的快捷方式,如 http.Get(), http.Post() 使用的是默认的client,因此 Timeout 为零值,就是 0 ,也就是不超时。
func Get(url string) (resp *Response, err error) {
return DefaultClient.Get(url)
}
var DefaultClient = &Client{}
所以,想要设置超时,需要使用自定义的client来发起请求,类似于。
c := http.Client{
Timeout: time.Second * 2,
}
req, err := http.NewRequest("GET", "http://192.168.2.157:8001/common/GetOpenidByCode?code=xxxx", strings.NewReader(""))
if err != nil {
panic(err)
}
resp, err := c.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
fmt.Println(err)
综合一下
var (
// Clients and Transports are safe for concurrent use by multiple goroutines and for efficiency should only be created once and re-used.
customizedClient = http.Client{Timeout: time.Second * 10}
)
// proxy代理服务器地址,比如 http://127.0.0.1:1080/
func HttpRequestProxy(link string, proxy string, method string, headers map[string]string, body string) (response string, err error) {
cli := &customizedClient
proxyAddress, _ := url.Parse(proxy)
cli.Transport = &http.Transport{Proxy: http.ProxyURL(proxyAddress)}
return HttpClientRequest(cli, link, method, headers, body)
}
// HttpRequest
// GET: HttpRequest("http..", "GET", nil, "")
// POST: HttpRequest("http..", "POST", [content-type=application/x-www-form-urlencoded], "a=1&b=2")
// POST: HttpRequest("http..", "POST", [content-type=application/json], "{a:1, b:2}")
func HttpRequest(link string, method string, headers map[string]string, body string) (response string, err error) {
return HttpClientRequest(&customizedClient, link, method, headers, body)
}
func HttpClientRequest(client *http.Client, link string, method string, headers map[string]string, body string) (response string, err error) {
method = strings.ToUpper(method)
req, err := http.NewRequest(method, link, strings.NewReader(body))
if err != nil {
return "", errors.New("NewRequest error")
}
for k, v := range headers {
req.Header.Set(k, v)
}
resp, err := client.Do(req)
if err != nil {
return "", errors.New("client.Do error")
}
data, err := io.ReadAll(resp.Body)
if err != nil || resp.StatusCode != 200 {
return string(data), errors.New(resp.Status)
}
return string(data), nil
}
func CurlGetWithParam(link string, param map[string]interface{}) (response string, err error) {
u, _ := url.Parse(link)
q := u.Query()
for k, v := range param {
var val string
switch ins := v.(type) {
case string:
val = ins
case int:
val = strconv.Itoa(ins)
case bool:
val = strconv.FormatBool(ins)
case float64:
val = strconv.FormatFloat(ins, 'f', -1, 64)
}
q.Set(k, val)
}
u.RawQuery = q.Encode()
return HttpRequest(u.String(), "GET", nil, "")
}
func CurlWithParam(link string, method string, param map[string]string) (response string, err error) {
u, _ := url.Parse(link)
q := u.Query()
for k, val := range param {
q.Set(k, val)
}
u.RawQuery = q.Encode()
headers := map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
}
method = strings.ToUpper(method)
if method == "GET" {
link = u.String()
headers = nil
}
return HttpRequest(link, method, headers, q.Encode())
}
本文详细介绍了HTTP的GET和POST请求方法,包括它们的区别、使用场景以及如何在Go语言中实现。GET用于获取资源,而POST用于提交数据。对于POST请求,还讲解了Content-Type的两种常见类型:multipart/form-data和application/x-www-form-urlencoded,并给出了文件上传和参数处理的示例。同时,文章涵盖了设置HTTP请求超时的方法。
1719

被折叠的 条评论
为什么被折叠?



