Req
最后修改时间 2024 年 4 月 11 日
在本文中,我们展示了如何使用 Req HTTP 客户端创建 HTTP 请求。HTTP 客户端向由 URL 标识的资源发送 HTTP 请求并接收 HTTP 响应。
HTTP
超文本传输协议(Hypertext Transfer Protocol (HTTP))是一种用于分布式、协作式、超媒体信息系统的应用层协议。HTTP 协议是万维网数据通信的基础。
Req
Req 是一个功能丰富的第三方 HTTP 客户端。它提供了许多便捷的功能,便于配置、调试和测试。
响应状态码
HTTP 响应状态码指示特定的 HTTP 请求是否已成功完成。有五种可用类别:
- 信息性响应(100–199)
- 成功响应(200–299)
- 重定向(300–399)
- 客户端错误(400–499)
- 服务器错误(500–599)
package main
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
func main() {
res, err := req.Get("http://webcode.me")
if err != nil {
log.Fatal(err)
}
fmt.Println(res.Status)
fmt.Println(res.StatusCode)
}
此示例创建一个 GET 请求到一个小型网站。我们获取请求的状态码。
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
我们导入 req 包。
res, err := req.Get("http://webcode.me")
我们使用 Get 生成一个 GET 请求。
fmt.Println(res.Status) fmt.Println(res.StatusCode)
Status 提供状态码的字符串表示,而 StatusCode 提供数字表示。
Go Req 开发模式
通过 DevMode 函数,我们启用了开发模式。在此模式下,HTTP 命令、HTTP 头和响应会自动打印到控制台。
package main
import (
"log"
"github.com/imroc/req/v3"
)
func main() {
req.DevMode()
_, err := req.Get("http://webcode.me")
if err != nil {
log.Fatal(err)
}
}
我们在开发模式下创建一个简单的 GET 请求。
$ go run main.go 2022/05/31 12:39:14.685055 DEBUG [req] HTTP/1.1 GET http://webcode.me GET / HTTP/1.1 Host: webcode.me User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ... Accept-Encoding: gzip HTTP/1.1 200 OK Server: nginx/1.6.2 Date: Tue, 31 May 2022 10:39:14 GMT Content-Type: text/html ...
Go Req GET 请求
以下示例在 Req 中创建了一个简单的 GET 请求。
package main
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
func main() {
res, err := req.Get("http://webcode.me")
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
bytes, err := res.ToBytes()
if err != nil {
log.Fatal(err)
}
fmt.Println(string(bytes))
}
我们向 webcode.me 发送一个 GET 请求。
res, err := req.Get("http://webcode.me")
使用 Get 函数发出 GET 请求。
if err != nil {
log.Fatal(err)
}
我们检查错误。
fmt.Println(res)
我们打印响应。
bytes, err := res.ToBytes() ... fmt.Println(string(bytes))
或者,我们可以获取字节并将其转换为字符串。
Go Req HEAD 请求
HTTP HEAD 方法请求如果使用 HTTP GET 方法请求指定资源会返回的头部信息。
package main
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
func main() {
res, err := req.Head("http://webcode.me")
if err != nil {
log.Fatal(err)
}
for k, v := range res.Header {
fmt.Printf("%s %s\n", k, v)
}
}
该示例使用 Head 发出 HEAD 请求,并打印响应头中的所有键/值对。
$ go run main.go Connection [keep-alive] Etag ["61ed305d-18a"] Content-Type [text/html] Content-Length [394] Last-Modified [Sun, 23 Jan 2022 10:39:25 GMT] Server [nginx/1.6.2] Date [Tue, 31 May 2022 10:50:54 GMT] Accept-Ranges [bytes]
Go Req User-Agent
User-Agent 请求头是一个字符串,它允许服务器和网络对等方识别请求用户代理的应用程序、操作系统、供应商和/或版本。
package main
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
func main() {
res, err := req.C().SetUserAgent("Go program").
R().Get("http://webcode.me/ua.php")
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
该示例使用 SetUserAgent 设置 User-Agent 头。请求的资源仅返回客户端的 User-Agent 字符串。
res, err := req.C().SetUserAgent("Go program").
R().Get("http://webcode.me/ua.php")
C 是用于创建客户端的辅助函数,而 R 是用于创建请求的辅助函数。
$ go run main.go Go program
查询参数
查询参数是统一资源定位符 (URL) 的一部分,它为指定的参数分配值。这是将数据发送到目标服务器的一种方式。
http://example.com/api/users?name=John%20Doe&occupation=gardener
查询参数在 ? 字符之后指定。多个字段用 & 分隔。特殊字符,如空格,会被编码。在上面的字符串中,空格被编码为 %20 值。
package main
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
func main() {
res, err := req.C().R().Get("https://:8080/hello?name=Peter")
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
在示例中,我们将一个查询参数 (name=Peter) 添加到请求 URL。或者,我们也可以使用请求的 SetQueryParam 函数。
为了测试该示例,我们使用 Echo 框架创建了一个简单的服务器。
package main
import (
"fmt"
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/hello/:name/", func(c echo.Context) error {
name := c.Param("name")
msg := fmt.Sprintf("Hello %s!", name)
return c.String(http.StatusOK, msg)
})
e.Logger.Fatal(e.Start(":8080"))
}
服务器处理请求,使用 Param 检索查询参数,并将消息返回给客户端。
路径参数
值可以通过查询参数或路径参数发送到服务器。路径参数直接在 URL 路径中指定。
package main
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
func main() {
res, err := req.C().R().SetPathParam("name", "Peter").
Get("https://:8080/hello/{name}/")
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
我们使用 SetPathParam 设置路径参数。
以下服务器示例处理带有路径变量的请求。
package main
import (
"fmt"
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/hello/:name/", func(c echo.Context) error {
name := c.Param("name")
msg := fmt.Sprintf("Hello %s!", name)
return c.String(http.StatusOK, msg)
})
e.Logger.Fatal(e.Start(":8080"))
}
在服务器应用程序中,我们使用冒号字符指定一个路径变量。我们使用 Param 获取变量,构建消息并将其发送给客户端。
下载文件
以下示例下载一个二进制文件。
package main
import (
"log"
"github.com/imroc/req/v3"
)
func main() {
client := req.C()
url := "http://webcode.me/favicon.ico"
_, err := client.R().SetOutputFile("favicon.ico").Get(url)
if err != nil {
log.Fatal(err)
}
}
SetOutputFile 函数设置响应体将被下载到的文件。
上传文件
下一个示例上传一个二进制文件。
package main
import (
"fmt"
"log"
"github.com/imroc/req/v3"
)
func main() {
client := req.C()
res, err := client.R().
SetFile("file", "sid.png").
Post("https://:8080/upload")
if err != nil {
log.Fatal(err)
}
fmt.Println(res.Status)
}
SetFile 函数设置一个用于上传的文件路径的 multipart 表单,该表单会自动从 filePath 读取文件进行上传。
我们创建一个服务器来处理请求。
package main
import (
"io"
"net/http"
"os"
"github.com/labstack/echo/v4"
)
func upload(c echo.Context) error {
file, err := c.FormFile("file")
if err != nil {
return err
}
src, err := file.Open()
if err != nil {
return err
}
defer src.Close()
dst, err := os.Create(file.Filename)
if err != nil {
return err
}
defer dst.Close()
if _, err = io.Copy(dst, src); err != nil {
return err
}
return c.HTML(http.StatusOK, "File uploaded")
}
func main() {
e := echo.New()
e.POST("/upload", upload)
e.Logger.Fatal(e.Start(":8080"))
}
服务器从请求中读取二进制数据并将其写入文件系统。
来源
在本文中,我们使用了 Req HTTP 客户端。