Go-multipart/form-data请求抓包详解

欢迎来到我的博客

背景

本文有一个疑问一直没有解决,诚心请教,有知道的大佬可以留言一下,不胜感激,点击这里跳转

最近在写一个图床小工具,
整合

  1. 读写剪贴板中的图像
  2. 读取到内存添加水印,(可供选择的文字水印和图像水印)
  3. 将图像通过协议发送到图床,(目前是对接的自己的图床)

遇到的难点

  1. 从剪贴板中读取图像
  2. 保存剪贴板中的图像
  3. multipart/form-data发送

multipart/form-data``code以及抓包代理配置

代理

这样配置代理,让代码请求走抓包软件,方便分析请求

// http https都可以抓到
proxy_raw := "127.0.0.1:8889"
	proxy_str := fmt.Sprintf("http://%s", proxy_raw)
	fmt.Println(proxy_str)
	proxy, err := url.Parse(proxy_str)
	if err != nil {
		fmt.Println(err)
	}

	client := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxy)}}

multipart/form-data code

func PostImg(filename string) {
	filePath := "./out/new_" + filename

	client := &http.Client{}
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)
	//添加表单属性
	// 参数1 (File参数)添加文件
	f, err := os.Open(filePath)
	if err != nil {
		return
	}
	fw1, err := bodyWriter.CreateFormFile("file", filepath.Base(filePath))

	//把文件流写入到缓冲区里去
	_, err1 := io.Copy(fw1, f)
	if err1 != nil {
		return
	}
	err = bodyWriter.Close()
	if err != nil {
		logrus.Errorf("bodyWriter close error: %v", err.Error())
		return
	}
	//http://logrus.Info("请求报文:", requst.JSONString())
	//发送post请求
	uri := "https://xxxxxxxxxxx"
	req, err := http.NewRequest("POST", uri, bodyBuf)
	if err != nil {
		return
	}
	// 设置cookie
	req.AddCookie(&http.Cookie{Name: "user", Value: "superman"})
	req.AddCookie(&http.Cookie{Name: "token", Value: "xxxxxxxxxxxxxxxxxxxxx"})
	//添加头文件
	// req.Header.Add("Content-Type", "multipart/form-data")用这句大概率报错,他添加了一个字段,会导致识别不了文件
	req.Header.Add("User-Agent", "Mozi")
	req.Header.Add("Content-Type", bodyWriter.FormDataContentType())
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9,en")
	// req.Header.Add("cookie", "user=superman; token=xxxxxxxxx")

	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	fmt.Println(string(body))
	// fmt.Println(ioutil.ReadFile(filePath))
	return
}

使用上面代码请求是这样的

直接在浏览器请求是这样的,

这时候,我们发现Content-Type: image/png这个字段不一样

无论待上传的文件是什么类型,CreateFormFile均将Content-Type置为application/octet-stream这一默认值。如果我们要自定义file partHeader字段Content-Type的值,我们就不能直接使用CreateFormFile

要定制这个的话也有办法,可以使用下面的代码

	bodyWriter := multipart.NewWriter(bodyBuf)
	//添加表单属性
	// 参数1 (File参数)
	//添加文件
	f, err := os.Open(filePath)
	if err != nil {
		return
	}

	h := make(textproto.MIMEHeader)
	h.Set("Content-Disposition",
		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
			escapeQuotes("file"), escapeQuotes("new_"+filename)))
	h.Set("Content-Type", "image/png")
	fw1, _ := bodyWriter.CreatePart(h)
	if err != nil {
		return
	}
	_, err1 := io.Copy(fw1, f)

这样的话,就达到目的了

补充

要达到这样的效果,需要下面的代码

	// 参数2 fileType (普通参数)
	fileWriter2, err := bodyWriter.CreateFormField("Content-Disposition")
	if err != nil {
		return
	}
	_, errs2 := fileWriter2.Write([]byte("form-data; name=\"file\"; filename=\"" + filepath.Base(filename) + "\""))
	if errs2 != nil {
		return
	}
	fileWriter3, _ := bodyWriter.CreateFormField("Content-Type")
	_, errs3 := fileWriter3.Write([]byte("image/png"))
	if errs3 != nil {
		return
	}
// 完整代码
func PostImg(filename string) {
	filePath := "./out/new_" + filename

	client := &http.Client{}
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)
	//添加表单属性
	// 参数1 (File参数)添加文件
	f, err := os.Open(filePath)
	if err != nil {
		return
	}
	fw1, err := bodyWriter.CreateFormFile("file", filepath.Base(filePath))

	//把文件流写入到缓冲区里去
	_, err1 := io.Copy(fw1, f)
	if err1 != nil {
		return
	}
	// 参数2 fileType (普通参数)
	fileWriter2, err := bodyWriter.CreateFormField("Content-Disposition")
	if err != nil {
		return
	}
	_, errs2 := fileWriter2.Write([]byte("form-data; name=\"file\"; filename=\"" + filepath.Base(filename) + "\""))
	if errs2 != nil {
		return
	}
	fileWriter3, _ := bodyWriter.CreateFormField("Content-Type")
	_, errs3 := fileWriter3.Write([]byte("image/png"))
	if errs3 != nil {
		return
	}
	// 接剩下的逻辑
	err = bodyWriter.Close()
	if err != nil {
		logrus.Errorf("bodyWriter close error: %v", err.Error())
		return
	}
	//http://logrus.Info("请求报文:", requst.JSONString())
	//发送post请求
	uri := "https://xxxxxxxxxxx"
	req, err := http.NewRequest("POST", uri, bodyBuf)
	if err != nil {
		return
	}
	// 设置cookie
	req.AddCookie(&http.Cookie{Name: "user", Value: "superman"})
	req.AddCookie(&http.Cookie{Name: "token", Value: "xxxxxxxxxxxxxxxxxxxxx"})
	//添加头文件
	// req.Header.Add("Content-Type", "multipart/form-data")用这句大概率报错,他添加了一个字段,会导致识别不了文件
	req.Header.Add("User-Agent", "Mozi")
	req.Header.Add("Content-Type", bodyWriter.FormDataContentType())
	req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9,en")
	// req.Header.Add("cookie", "user=superman; token=xxxxxxxxx")

	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	fmt.Println(string(body))
	// fmt.Println(ioutil.ReadFile(filePath))
	return
}

疑问

在线蹲一个大佬,下面的问题依然没有解决,如果您知道的话,诚求您的留言,不胜感激

这是正常的请求,注意划线部分

下面是通过协议发的请求

这两处划线的地方不一样,没找到在哪生成的,

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值