IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> golang常用库之http客户端-Sling、标准库net/http包 | go标准库mime/multipart -> 正文阅读

[网络协议]golang常用库之http客户端-Sling、标准库net/http包 | go标准库mime/multipart

一、golang http客户端

1. 基础知识:http请求四种常见的POST提交数据方式

**服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请
求中的消息主体是用何种方式编码,再对主体进行解析。**也就是说, Content-Type 指定了消息主体中的编码方式 。因
此,POST 提交数据方案,直接跟 Content-Type 和消息主体两部分有关。

http请求常见的content-type分为4种:application/json、x-www-form-urlencoded、multipart/form-data、text/plain。
在这里插入图片描述
1)application/x-www-form-urlencoded

HTTP中默认的提交数据的方式。浏览器的原生表单,如果不设置enctype属性,那么最终就会以application/x-www-form-urlencoded方式提交数据

const (
    http_address = "http://yourIP:8080/****"
)

// 用url.values方式构造form-data参数
formValues := url.Values{}
formValues .Set("first",firstData)
formValues .Set("second",secondData)
formDataStr := formValues.Encode()
formDataBytes := []byte(formDataStr )
formBytesReader := bytes.NewReader(formDataBytes )

//生成post请求
client := &http.Client{}
req, err := http.NewRequest("POST", http_address, formBytesReader )
if err != nil {
	// handle error
	log.Fatal("生成请求失败!",err)
	return
}

//注意别忘了设置header
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

//Do方法发送请求
resp, err := client.Do(req)

2)multipart/form-data

一个常见的POST数据提交的方式。我们使用表单上传文件时,必须将enctype设为multipart/form-data。

上面两种 POST 数据方式,都是浏览器原生支持的,而且现阶段原生 form 表单也只支持这两种方式。但

3)application/json

application/json作为请求头,用来告诉服务端消息主体是序列化的JSON字符串。方便提交复杂的结构化数据,特别适合RESTFul接口。
各大抓包工具如Chrome自带的开发者工具、Firebug、Fiddler,都会以树形结构展示JSON数据,非常友好。

Google 的 AngularJS 中的 Ajax 功能,默认就是提交 JSON 字符串。

4)text/xml
XML-RPC(XML Remote Procdure Call)。它是一种使用HTTP作为传输协议,XML作为编码方式的远程调用规范。

二、golang 标准库net/http包

golang系列——实战http客户端
参考URL: https://zhuanlan.zhihu.com/p/134146738

golang的net/http包已经提供了强大了网络操作函数。

1. golang使用http client发起get和post请求示例

get请求:

package csdn

import (
	"io/ioutil"
	"log"
	"net/http"
	"testing"
)

func TestNewPublisher(t *testing.T) {
	res, err := http.Get("http://www.csdn.com")
	if err != nil {
		log.Fatal(err)
	}
	//利用ioutil包读取服务器返回的数据
	data, err := ioutil.ReadAll(res.Body)
	res.Body.Close()//一定要记得关闭连接
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("%s", data)
}

2. Golang http添加cookie

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {

	client := &http.Client{}

	req, _ := http.NewRequest("GET", "http://localhost:8082/cookie_test",nil)
	req.Header.Add("Cookie","ds=req.Header.Add")

	resp, err := client.Do(req)
	if err != nil {
		panic(nil)
	}

	body, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

	fmt.Println(string(body))

}

工作技巧: 使用浏览器的cookie参数时您可以先拿postman测试验证没有问题,再写到代码中。

3. Go post方式发送带有form-data参数的http请求

golang学习之如何构造一个multipart/form格式的HTTP请求
参考URL: http://blog.codeg.cn/2015/03/18/golang-how-to-make-a-multipart-http-request/
https://www.easck.com/cos/2020/1218/594591.shtml

思路和方法:通过Go标准库提供的mime/multipart包,我们可以很容易地构建出满足要求的包体。

3.1 go标准库的学习-mime/multipart

go标准库的学习-mime/multipart
参考URL: https://www.cnblogs.com/wanghui-garcia/p/10402796.html

import "mime/multipart"

multipart实现了MIME的multipart解析,参见RFC 2046。该实现适用于HTTP(RFC 2388)和常见浏览器生成的multipart主体。

案例一:普通普通表单上传后端程序

func main() {
    buf:=new(bytes.Buffer)
    bodywriter:=multipart.NewWriter(buf)
    bodywriter.WriteField("name","lisi")
    bodywriter.WriteField("age","40")
    contentType:=bodywriter.FormDataContentType()
    defer bodywriter.Close()
    url:="http://www.shop.com:8088/index/index/aa"
    http.Post(url,contentType,buf)
}

三、Sling 库

1. 什么是Sling 库

https://github.com/dghubble/sling
https://pkg.go.dev/github.com/dghubble/sling#section-readme

Sling是用于创建和发送API请求的Go HTTP客户端库。

项目开发中,发送http请求的场景,推荐使用Sling库。Sling本身是基于net/http来处理发送请求,同时做了较好的封装,既可以利用net/http的一些特性(如:httptrace),同时又不必关心net/http库的一些琐碎细节。

Sling的默认实现可以覆盖大部分对于http发送请求场景,同时可以通过实现Doer和ResponseDecoder接口来扩展个性化的场景。

Sling支持以下主要的功能:

  • 支持GET/POST/PUT/PATCH/DELETE/HEAD
  • 基于Base/Path可以扩展和复用Sling
  • query参数可以用结构体来Encode
  • Request Body支持form和json
  • 可将Json格式的Response直接Decode到定义好的结构体
  • 可扩展Response的Decoder,以及Doer。

Sling 存储HTTP请求属性以简化发送请求和解码响应。检查使用情况示例以了解如何将Sling 组成API客户端。

由上使用案例,Sling 常被用来封装 http client sdk。

2. Sling使用方法

https://pkg.go.dev/github.com/dghubble/sling?utm_source=godoc
【GoCN酷Go推荐】灵活的Go http client库-Sling
参考URL: https://jishuin.proginn.com/p/763bfbd5b75f

Sling对http请求的要素method、baseUrl、Path、query、body、request、response等做了封装,基本使用可以参考https://github.com/dghubble/sling 上的示例代码。

可以通过实现ResponseDecoder和Doer的接口,来定制响应的decoder和发送请求的具体实现。

Sling拓展

每个Sling都会创建一个标准的http.request Request()调用(例如,使用某些路径和查询参数)。您可能希望扩展现有Sling以最大限度地减少重复(例如常见客户端或基本URL)。

每个Sling实例都提供了一种创建一个独立副本的New()方法,因此,子组的设置属性不会使父Sling变异。

const twitterApi = "https://api.twitter.com/1.1/"
base := sling.New().Base(twitterApi).Client(authClient)

// statuses/show.json Sling
tweetShowSling := base.New().Get("statuses/show.json").QueryStruct(params)
req, err := tweetShowSling.Request()

// statuses/update.json Sling
tweetPostSling := base.New().Post("statuses/update.json").BodyForm(params)
req, err := tweetPostSling.Request()

如果要扩展吊索,请使用New()创建一个新的子副本。

修改Request

Sling提供raw http.Request ,因此可以使用标准的 net/http 功能进行修改。

例如,在Go 1.7+中,将HTTP跟踪添加到具有上下文的请求:

req, err := sling.New().Get("https://example.com").QueryStruct(params).Request()
// handle error

trace := &httptrace.ClientTrace{
   DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
      fmt.Printf("DNS Info: %+v\n", dnsInfo)
   },
   GotConn: func(connInfo httptrace.GotConnInfo) {
      fmt.Printf("Got Conn: %+v\n", connInfo)
   },
}

req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
client.Do(req)

post请求form-data demo

查看Sling 源码 得知,Sling 不直接支持 multipart/form-data

const (
	contentType     = "Content-Type"
	jsonContentType = "application/json"
	formContentType = "application/x-www-form-urlencoded"
)

提供的2个传内容的方法里面没有 处理 multipart/form-data 情况
如下,一个是json,一个是在body中 进行url编码。

// BodyJSON sets the Sling's bodyJSON. The value pointed to by the bodyJSON
// will be JSON encoded as the Body on new requests (see Request()).
// The bodyJSON argument should be a pointer to a JSON tagged struct. See
// https://golang.org/pkg/encoding/json/#MarshalIndent for details.
func (s *Sling) BodyJSON(bodyJSON interface{}) *Sling {
	if bodyJSON == nil {
		return s
	}
	return s.BodyProvider(jsonBodyProvider{payload: bodyJSON})
}

// BodyForm sets the Sling's bodyForm. The value pointed to by the bodyForm
// will be url encoded as the Body on new requests (see Request()).
// The bodyForm argument should be a pointer to a url tagged struct. See
// https://godoc.org/github.com/google/go-querystring/query for details.
func (s *Sling) BodyForm(bodyForm interface{}) *Sling {
	if bodyForm == nil {
		return s
	}
	return s.BodyProvider(formBodyProvider{payload: bodyForm})
}

解决思路:
Sling 本质还是使用标准库的http。Sling 封装的 不支持处理 multipart/form-data 情况。

亲测,尝试直接利用 Sling 失败,这里暂时使用标准http库的写法来实现。

读者如果直接利用Sling 可以实现,可以联系告诉我~!

用于构建一个API

APIs typically define an endpoint (also called a service) for each type of resource. For example, here is a tiny Github IssueService which lists repository issues.

APIs 通常为每种类型的资源定义端点(也称为服务)。例如,这是一个小型gihub IssueService,用于列出了github仓库issues。

const baseURL = "https://api.github.com/"

type IssueService struct {
    sling *sling.Sling
}

func NewIssueService(httpClient *http.Client) *IssueService {
    return &IssueService{
        sling: sling.New().Client(httpClient).Base(baseURL),
    }
}

func (s *IssueService) ListByRepo(owner, repo string, params *IssueListParams) ([]Issue, *http.Response, error) {
    issues := new([]Issue)
    githubError := new(GithubError)
    path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)
    resp, err := s.sling.New().Get(path).QueryStruct(params).Receive(issues, githubError)
    if err == nil {
        err = githubError
    }
    return *issues, resp, err
}

使用Sling构建APIs示例

  • Digits dghubble/go-digits
  • GoSquared drinkin/go-gosquared
  • Kala ajvb/kala
  • Parse fergstar/go-parse
  • Swagger Generator swagger-api/swagger-codegen
  • Twitter dghubble/go-twitter
  • Stacksmith jesustinoco/go-smith

由上知,
twitter的client就是利用 Sling 封装的 go sdk,
项目参考 github.com/dghubble/go-twitter/twitter

在这里插入图片描述

四、参考

golang系列——实战http客户端
参考URL: https://zhuanlan.zhihu.com/p/134146738
【GoCN酷Go推荐】灵活的Go http client库-Sling
参考URL: https://jishuin.proginn.com/p/763bfbd5b75f

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-22 20:58:43  更:2022-03-22 21:00:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:45:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码