简介

golang 里的 http 标准库,发起 http 请求时,写法比较繁琐。所以智慧又“偷懒的”程序员们,发挥自己的创造力,写出了一些好用的第三方库,这里介绍其中的一个 http 库:go-resty

go-resty 特性

go-resty 有很多特性:

  • 发起 GET, POST, PUT, DELETE, HEAD, PATCH, OPTIONS, etc. 请求
  • 简单的链式书写
  • 自动解析 JSON 和 XML 类型的文档
  • 上传文件
  • 重试功能
  • 客户端测试功能
  • Resty client
  • Custom Root Certificates and Client Certificates
  • ... ....

    等等很多特性。

go-resty更多功能特性请查看文档:go-resty features

go-resty 使用

go-resty: v2.3.0

用法 example:https://github.com/go-resty/resty#usage

简单的GET

simple_get.go

package main

import (
"fmt" "github.com/go-resty/resty/v2"
) func main() {
client := resty.New() // 创建一个restry客户端
resp, err := client.R().EnableTrace().Get("https://httpbin.org/get") // Explore response object
fmt.Println("Response Info:")
fmt.Println(" Error :", err)
fmt.Println(" Status Code:", resp.StatusCode())
fmt.Println(" Status :", resp.Status())
fmt.Println(" Proto :", resp.Proto())
fmt.Println(" Time :", resp.Time())
fmt.Println(" Received At:", resp.ReceivedAt())
fmt.Println(" Body :\n", resp)
fmt.Println() // Explore trace info
fmt.Println("Request Trace Info:")
ti := resp.Request.TraceInfo()
fmt.Println(" DNSLookup :", ti.DNSLookup)
fmt.Println(" ConnTime :", ti.ConnTime)
fmt.Println(" TCPConnTime :", ti.TCPConnTime)
fmt.Println(" TLSHandshake :", ti.TLSHandshake)
fmt.Println(" ServerTime :", ti.ServerTime)
fmt.Println(" ResponseTime :", ti.ResponseTime)
fmt.Println(" TotalTime :", ti.TotalTime)
fmt.Println(" IsConnReused :", ti.IsConnReused)
fmt.Println(" IsConnWasIdle :", ti.IsConnWasIdle)
fmt.Println(" ConnIdleTime :", ti.ConnIdleTime)
// fmt.Println(" RequestAttempt:", ti.RequestAttempt)
// fmt.Println(" RemoteAddr :", ti.RemoteAddr.String())
}

增强的GET

client := resty.New()
resp, err := client.R().
SetQueryParams(map[string]string{
"page_no": "1",
"limit": "20",
"sort": "name",
"order": "asc",
"random": strconv.FormatInt(time.Now().Unix(), 10),
}).
SetHeader("Accept", "application/json").
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
Get("/search_result") // Request.SetQueryString method
resp, err := client.R().
SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more").
SetHeader("Accept", "application/json").
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
Get("/show_product") // 解析返回的内容,内容是json解析到struct
resp, err := client.R().
SetResult(result).
ForceContentType("application/json").
Get("v2/alpine/mainfestes/latest")

各种POST方法

doc:

https://github.com/go-resty/resty#various-post-method-combinations


// Create a Resty Clientclient := resty.New() // POST JSON string// No need to set content type, if you have client level settingresp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(`{"username":"testuser", "password":"testpass"}`).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
Post("https://myapp.com/login") // POST []byte array// No need to set content type, if you have client level settingresp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
Post("https://myapp.com/login") // POST Struct, default is JSON content type. No need to set oneresp, err := client.R().
SetBody(User{Username: "testuser", Password: "testpass"}).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
SetError(&AuthError{}). // or SetError(AuthError{}).
Post("https://myapp.com/login") // POST Map, default is JSON content type. No need to set oneresp, err := client.R().
SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
SetError(&AuthError{}). // or SetError(AuthError{}).
Post("https://myapp.com/login") // POST of raw bytes for file upload. For example: upload file to DropboxfileBytes, _ := ioutil.ReadFile("/Users/jeeva/mydocument.pdf") // See we are not setting content-type header, since go-resty automatically detects Content-Type for youresp, err := client.R().
SetBody(fileBytes).
SetContentLength(true). // Dropbox expects this value
SetAuthToken("<your-auth-token>").
SetError(&DropboxError{}). // or SetError(DropboxError{}).
Post("https://content.dropboxapi.com/1/files_put/auto/resty/mydocument.pdf") // for upload Dropbox supports PUT too // Note: resty detects Content-Type for request body/payload if content type header is not set.// * For struct and map data type defaults to 'application/json'// * Fallback is plain text content type

PUT


// Note: This is one sample of PUT method usage, refer POST for more combination // Create a Resty Clientclient := resty.New() // Request goes as JSON content type// No need to set auth token, error, if you have client level settingsresp, err := client.R().
SetBody(Article{
Title: "go-resty",
Content: "This is my article content, oh ya!",
Author: "Jeevanandam M",
Tags: []string{"article", "sample", "resty"},
}).
SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
SetError(&Error{}). // or SetError(Error{}).
Put("https://myapp.com/article/1234")

PATCH


// Note: This is one sample of PUT method usage, refer POST for more combination // Create a Resty Clientclient := resty.New() // Request goes as JSON content type// No need to set auth token, error, if you have client level settingsresp, err := client.R().
SetBody(Article{
Tags: []string{"new tag1", "new tag2"},
}).
SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
SetError(&Error{}). // or SetError(Error{}).
Patch("https://myapp.com/articles/1234")

DELETE, HEAD, OPTIONS


// Create a Resty Clientclient := resty.New() // DELETE a article// No need to set auth token, error, if you have client level settingsresp, err := client.R().
SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
SetError(&Error{}). // or SetError(Error{}).
Delete("https://myapp.com/articles/1234") // DELETE a articles with payload/body as a JSON string// No need to set auth token, error, if you have client level settingsresp, err := client.R().
SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
SetError(&Error{}). // or SetError(Error{}).
SetHeader("Content-Type", "application/json").
SetBody(`{article_ids: [1002, 1006, 1007, 87683, 45432] }`).
Delete("https://myapp.com/articles") // HEAD of resource// No need to set auth token, if you have client level settingsresp, err := client.R().
SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
Head("https://myapp.com/videos/hi-res-video") // OPTIONS of resource// No need to set auth token, if you have client level settingsresp, err := client.R().
SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
Options("https://myapp.com/servers/nyc-dc-01")

Requst and Response Middleware


// Create a Resty Clientclient := resty.New() // Registering Request Middlewareclient.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
// Now you have access to Client and current Request object
// manipulate it as per your need return nil // if its success otherwise return error
}) // Registering Response Middlewareclient.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
// Now you have access to Client and current Response object
// manipulate it as per your need return nil // if its success otherwise return error
})

重试 Retries


// Create a Resty Clientclient := resty.New() // Retries are configured per clientclient.
// Set retry count to non zero to enable retries
SetRetryCount(3).
// You can override initial retry wait time.
// Default is 100 milliseconds.
SetRetryWaitTime(5 * time.Second).
// MaxWaitTime can be overridden as well.
// Default is 2 seconds.
SetRetryMaxWaitTime(20 * time.Second).
// SetRetryAfter sets callback to calculate wait time between retries.
// Default (nil) implies exponential backoff with jitter
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
return 0, errors.New("quota exceeded")
})

Above setup will result in resty retrying requests returned non nil error up to 3 times with delay increased after each attempt.

You can optionally provide client with custom retry conditions:


// Create a Resty Clientclient := resty.New() client.AddRetryCondition(
// RetryConditionFunc type is for retry condition function
// input: non-nil Response OR request execution error
func(r *resty.Response) (bool, error) {
return r.StatusCode() == http.StatusTooManyRequests
},
)

多个客户端请求


// Here you go!// Client 1client1 := resty.New()
client1.R().Get("http://httpbin.org")
// ... // Client 2client2 := resty.New()
client2.R().Head("http://httpbin.org")
// ... // Bend it as per your need!!!

也可以到我的公众号:九卷技术录-go-resty 库使用详解 讨论

参考

golang常用库包:http和API客户端请求库-go-resty的更多相关文章

  1. Python库,让你相见恨晚的第三方库

    环境管理 管理 Python 版本和环境的工具 p – 非常简单的交互式 python 版本管理工具.pyenv – 简单的 Python 版本管理工具.Vex – 可以在虚拟环境中执行命令.virt ...

  2. Python3 网络爬虫(请求库的安装)

    Python3 网络爬虫(请求库的安装) 爬虫可以简单分为几步:抓取页面,分析页面和存储数据 在页面爬取的过程中我们需要模拟浏览器向服务器发送请求,所以需要用到一些python库来实现HTTP的请求操 ...

  3. Go 标准库,常用的包及功能

    Go 的标准库 Go语言的标准库覆盖网络.系统.加密.编码.图形等各个方面,可以直接使用标准库的 http 包进行 HTTP 协议的收发处理:网络库基于高性能的操作系统通信模型(Linux 的 epo ...

  4. ROS常用库(四)API学习之常用common_msgs(下)

    一.前言 承接ROS常用库(三)API学习之常用common_msgs(上). 二.sensor_msgs 1.sensor_msgs / BatteryState.msg #电源状态 uint8 P ...

  5. golang常用库:cli命令行/应用程序生成工具-cobra使用

    golang常用库:cli命令行/应用程序生成工具-cobra使用 一.Cobra 介绍 我前面有一篇文章介绍了配置文件解析库 Viper 的使用,这篇介绍 Cobra 的使用,你猜的没错,这 2 个 ...

  6. Go 的 golang.org/x/ 系列包和标准库包有什么区别?

    在开发过程中可能会遇到这样的情况,有一些包是引入自不同地方的,比如: golang.org/x/net/html 和 net/html, golang.org/x/crypto 和 crypto. 那 ...

  7. golang学习笔记--包导入及go 常用命令及参数

    包导入:包导入路劲即代码包在工作区的src目录下的相对路径. 同一个源码文件中导入的多个代码包的最后一个元素不能重复,否则引起编译错误,如果只导入不使用,同样会引起编译错误 若想导入最后一个元素名相同 ...

  8. golang常用库:日志记录库-logrus使用

    介绍 logrus 它是一个结构化.插件化的日志记录库.完全兼容 golang 标准库中的日志模块.它还内置了 2 种日志输出格式 JSONFormatter 和 TextFormatter,来定义输 ...

  9. java开发常用jar包介绍(转载)

    jta.jar 标准JTA API必要 commons-collections.jar 集合类 必要 antlr.jar  ANother Tool for Language Recognition ...

  10. Golang构建HTTP服务(一)--- net/http库源码笔记

    搭建一个简单的Go Web服务器 Go语言标准库 - net/http 在学习Go语言有一个很好的起点,Go语言官方文档很详细,今天我们学习的Go Web服务器的搭建就需要用到Go语言官方提供的标准库 ...

随机推荐

  1. [转帖]NUMA导致的Oracle性能问题

    https://www.cnblogs.com/realcp1018/p/6903721.html 背景简介: Oracle版本:11.2.0.4 OS 版本:OEL5.8 在一次Oracle的Dat ...

  2. [转帖]oracle中Rman增量备份下各级别level的区别

    RMAN备份分为全备和增量备份两部分 增量备份:分为0 1 2级 ORACLE官方解释:  A level 1 incremental backup can be either of the foll ...

  3. [转帖]SIMD指令集 SSE/AVX

    SIMD指令集 SSE/AVX 概述 参考手册 Intel Intrinsics Guide Tommesani.com Docs Intel 64 and IA-32 Architectures S ...

  4. [转帖]jmeter实现不写代码把测试结果存入execl

    这里使用数据库作为中间件来实现不写代码就把测试结果存入execl,下面是步骤 1.新建一个setup线程组用来设置数据库连接信息和新建数据库,如下图所示,我们使用sqlite数据库来存储信息,因为不需 ...

  5. 【转帖】linux环境下使用route指令设置多个网络连接的优先级(通过修改路由表的默认网关条目)

    1. 背景 在生活中的会经常遇见一台PC同时连接多个网络的场景.最典型的,一台笔记本可以同时连接一个无线网(手机热点)和一个有线网(以太网).linux和window操作系统在默认情况都会使用最早连接 ...

  6. [转帖]深入理解Redis的scan命令

    熟悉Redis的人都知道,它是单线程的.因此在使用一些时间复杂度为O(N)的命令时要非常谨慎.可能一不小心就会阻塞进程,导致Redis出现卡顿. 有时,我们需要针对符合条件的一部分命令进行操作,比如删 ...

  7. Specjvm2008的简单学习

    Specjvm2008的简单学习 摘要 前期整理过很多需要通过编译指定命令进行性能测试的工具 但是这种工具无法充分模式JAVA应用. 并且无法模拟不同jvm版本的性能情况. 早上去北京出差路上看到了 ...

  8. 【图论】CF1508C Complete the MST

    Problem Link 有一张 \(n\) 个点的完全图,其中 \(m\) 条边已经标有边权.你需要给剩下的边都标上权值,使得所有边权的异或和为 \(0\),并且整张图的最小生成树边权和最小. \( ...

  9. 解决Edge浏览器提示“此网站已被人举报不安全”

    今天下午微软旗下的 Microsoft Edge 浏览器将百度搜索的跳转域名 (*.baidu.com/link?url=*) 封杀,百度搜索首页可以打开,但搜索任何关键词点击搜索结果都会被拦截. 当 ...

  10. 【1】windows下安装OpenCV(4.3)+VS2017安装+opencv_contrib4.3.0配置

    相关文章: [1]windows下安装OpenCV(4.3)+VS2017安装+opencv_contrib4.3.0配置 [2]Visual Studio 2017同时配置OpenCV2.4 以及O ...