在使用golang的net/http发送http请求的时候,碰到了不少问题,总结了http的常见使用方式
json格式传参
优点:传参方式用json,代码简洁
缺点:Content-Type为application/json发送,php中获取不到post数据,只能从输入流获取;不能设置request的header信息
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main () {
path := "http://test.com"
values := map[string]string{"username":"username","passwd":"passwd"}
jsonvalue, _ := json.Marshal(values)
resp,err := http.Post(path, "application/json", bytes.NewBuffer(jsonvalue))
defer resp.Body.Close()
respBody,_:=ioutil.ReadAll(resp.Body)
fmt.Println(string(respBody), err)
}
//$_POST['username']获取不到;只能file_get_contents("php://input")
postform模拟表单
优点:php中能获取post数据,代码简洁
缺点:不能设置request的header信息
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
)
func main() {
UserName := "username"
PassWD := "passwd"
v := url.Values{}
v.Set("username", UserName)
v.Set("password", PassWD)
resp, err := http.PostForm("http://test.com", v)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
fmt.Println(string(content))
}
request方式
优点:能设置header
缺点:代码稍微复杂
发送普通post请求示例
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
Params := map[string]string{
"is_init" : "1",
"name" : "a.mp4",
"size" : "111",
}
body, _ := json.Marshal(Params)
client := &http.Client{}//客户端,被Get,Head以及Post使用
reqest, err := http.NewRequest("POST", "http://test.com", bytes.NewBuffer(body))
fmt.Println(Params, body, bytes.NewBuffer(body))
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
reqest.Header.Set("Content-Type", "application/json") //必须设定该参数,POST参数才能正常提交
resp, err := client.Do(reqest)//发送请求
defer resp.Body.Close()//一定要关闭resp.Body
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
fmt.Println(string(content))
}
设置request的header信息示例
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
func main () {
v := url.Values{}
v.Set("name", "name")
v.Set("is_init", "1")
body := ioutil.NopCloser(strings.NewReader(v.Encode()))
client := &http.Client{}//客户端,被Get,Head以及Post使用
reqest, err := http.NewRequest("POST", "http://test.com", body)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
reqest.Header.Set("Content-Type", "application/x-www-form-urlencoded;param=value") //必须设定该参数,POST参数才能正常提交
reqest.Header.Set("test", "hello")//设置header
resp, err := client.Do(reqest)//发送请求
defer resp.Body.Close()//一定要关闭resp.Body
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
fmt.Println("response=>", string(content))
}
普通上传图片
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
)
func main() {
Upload("http://test.com/upload", "/tmp/upload.png");
}
func Upload(request_url, file_path string) {
file, err := os.Open(file_path)
if err != nil {
fmt.Println("error opening file")
}
defer file.Close()
//创建一个模拟的form中
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
//通过$_FILE['file']获取
fileWriter, err := bodyWriter.CreateFormFile("file", file_path)
if err != nil {
fmt.Println("error writing to buffer")
}
//这里相当于选择了文件,将文件放到form中
_, err = io.Copy(fileWriter, file)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
//获取上传文件的类型,multipart/form-data; boundary=...
contentType := bodyWriter.FormDataContentType()
//这个很关键,必须这样写关闭,不能使用defer关闭,不然会导致错误
bodyWriter.Close()
//上传的其他参数设置
params := map[string]string{
"desc": "这里可以传入别的参数",
}
for key, val := range params {
_ = bodyWriter.WriteField(key, val)
}
resp, err := http.Post(request_url, contentType, bodyBuf)
if err != nil {
fmt.Println("error writing to buffer")
}
defer resp.Body.Close()
resp_body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("error writing to buffer")
}
fmt.Println(string(resp_body))
}
上传图片,并设置header
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
func main() {
Upload("http://test.com/upload", "/tmp/upload.png", "this is code")
}
func Upload(request_url, img_path, code string) {
file, err := os.Open(img_path)
if err != nil {
fmt.Println(err.Error())
}
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
//通过$_FILE['common']获取
part, err := writer.CreateFormFile("common", filepath.Base(img_path))
if err != nil {
fmt.Println(err.Error())
}
_, err = io.Copy(part, file)
err = writer.Close()
if err != nil {
fmt.Println(err.Error())
}
req, err := http.NewRequest("POST", request_url, body)
req.Header.Set("Content-Type", writer.FormDataContentType())
//业务需要进行auth,通过$_SERVER['HTTP_AUTHORIZATION']获取
req.Header.Set("authorization", "Bearer "+code)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
resp.Body.Close()
fmt.Println(string(content))
}
以上是常见的几种方式,在使用过程中,可以把request的方式再封装一层,简化代码再调用
「注:封装的不是很好,可以按照自己的需求来」
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
func main () {
params := map[string]string{
"name": "name",
"is_init":"1",
}
headers := map[string]string{
"Content-Type" : "application/x-www-form-urlencoded;param=value",
}
Http("http://test.com", params, headers)
}
func Http(request_url string, params map[string]string, header map[string]string) string {
v := url.Values{}
for key, val := range params {
v.Set(key, val)
}
body := ioutil.NopCloser(strings.NewReader(v.Encode()))
client := &http.Client{}
reqest, err := http.NewRequest("POST", request_url, body)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
for key, val := range header {
reqest.Header.Set(key, val)
}
resp, err := client.Do(reqest)
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
fmt.Println(string(content))
return string(content)
}
—— END ——
文 | SunnySmileZ (转载请注明出处)
微信号:zhouzhi1229
github:github.com/SunnySmilez
喜欢我、想第一时间读我,你可以扫描二维码关注我