• 基于Go语言实现好用的HTTP接口请求requests


    使用Go自带的net/http库可以发送各种HTTP请求。
    然而各种类型请求发送方式有点不太一致,这里参考Python requests库的使用方式,简单封装了一下。
    代码如下:

    文件requests.go内容

    package main
    
    import (
    	"encoding/json"
    	"io"
    	"io/ioutil"
    	"net/http"
    	"net/url"
    	"strings"
    	"time"
    )
    
    // 请求结构体
    type Request struct {
    	Method string `json:"method"`               // 请求方法
    	Url string `json:"url"`                     // 请求url
    	Params map[string]string `json:"params"`    // Query参数
    	Headers map[string]string `json:"headers"`  // 请求头
    	Cookies map[string]string `json:"cookies"`  // todo 处理 Cookies
    	Data map[string]string `json:"data"`        // 表单格式请求数据
    	Json map[string]string `json:"json"`        // JSON格式请求数据 todo 多层 嵌套
    	Files map[string]string `json:"files"`      // todo 处理 Files
    	Raw string `json:"raw"`                     // 原始请求数据
    }
    
    // 响应结构体
    type Response struct {
    	StatusCode int `json:"status_code"`         // 状态码
    	Reason string `json:"reason"`               // 状态码说明
    	Elapsed    float64  `json:"elapsed"`        // 请求耗时(秒)
    	Content    [] byte  `json:"content"`        // 响应二进制内容
    	Text       string  `json:"text"`            // 响应文本
    	Headers    map[string]string `json:"headers"` // 响应头
    	Cookies    map[string]string `json:"cookies"` // todo 添加响应Cookies
    	Request    *Request `json:"request"`          // 原始请求
    }
    
    // 处理请求方法
    func (r *Request) getMethod() string{
    	return strings.ToUpper(r.Method)              // 必须转为全部大写
    }
    
    // 组装URL
    func (r *Request) getUrl() string {
    	if r.Params != nil{
    		urlValues := url.Values{}
    		Url, _ := url.Parse(r.Url)  // todo 处理err
    		for key, value := range(r.Params){
    			urlValues.Set(key,value)
    		}
    		Url.RawQuery = urlValues.Encode()
    		return Url.String()
    	}
    	return r.Url
    }
    
    // 组装请求数据
    func (r *Request) getData() io.Reader {
    	var reqBody string
    	if r.Raw != "" {
    		reqBody = r.Raw
    	}else if r.Data != nil{
    		urlValues := url.Values{}
    		for key, value := range(r.Data){
    			urlValues.Add(key,value)
    		}
    		reqBody = urlValues.Encode()
    		r.Headers["Content-Type"] = "application/x-www-form-urlencoded"
    	}else if r.Json != nil{
    		bytesData, _ := json.Marshal(r.Json)
    		reqBody = string(bytesData)
    		r.Headers["Content-Type"] = "application/json"
    	}
    	return strings.NewReader(reqBody)
    }
    
    // 添加请求头-需要在getData后使用
    func (r *Request) addHeaders(req *http.Request){
    	if r.Headers != nil{
    		for key, value := range(r.Headers){
    			req.Header.Add(key, value)
    		}
    	}
    }
    
    // 准备请求
    func (r *Request) prepare() *http.Request{
    	Method := r.getMethod()
    	Url := r.getUrl()
    	Data := r.getData()
    	req, _ := http.NewRequest(Method, Url, Data)
    	r.addHeaders(req)
    	return req
    }
    
    // 组装响应对象
    func (r *Request) packResponse(res *http.Response, elapsed float64) Response {
    	var resp Response
    	resBody, _ := ioutil.ReadAll(res.Body)
    	resp.Content = resBody
    	resp.Text = string(resBody)
    	resp.StatusCode = res.StatusCode
    	resp.Reason = strings.Split(res.Status, " ")[1]
    	resp.Elapsed = elapsed
    	resp.Headers = map[string]string{}
    	for key, value := range(res.Header){
    		resp.Headers[key] = strings.Join(value, ";")
    	}
    	return resp
    }
    
    // 发送请求
    func (r *Request) Send() Response {
    	req := r.prepare()
    	client := &http.Client{}
    	start := time.Now()
    	res, _ := client.Do(req)  // todo 处理err
    	defer res.Body.Close()
    	elapsed := time.Since(start).Seconds()
    	return r.packResponse(res, elapsed)
    }
    

    使用方法如下:
    文件requests_test.go内容

    package main
    
    import (
    	"fmt"
    	"testing"
    )
    
    // 发送GET 请求
    func TestGet(t *testing.T){
    	r := Request{
    		Method: "GET",
    		Url: "https://httpbin.org/get?name=张三&age=12",
    		Headers: map[string]string{"Cookie": "abc", "Token": "123"}}
    	resp := r.Send()
    	fmt.Printf("状态码: %d\n", resp.StatusCode)
    	fmt.Printf("原因: %s\n", resp.Reason)
    	fmt.Printf("响应时间: %f秒\n", resp.Elapsed)
    	fmt.Printf("响应文本: %s\n", resp.Text)
    }
    
    // 发送GET 带单独Query参数请求
    func TestGetWithParams(t *testing.T){
    	r := Request{
    		Method: "GET",
    		Url: "https://httpbin.org/get",
    		Params: map[string]string{"name": "张三", "age": "12"},
    		Headers: map[string]string{"Cookie": "abc", "Token": "123"}}
    	resp := r.Send()
    	fmt.Printf("状态码: %d\n", resp.StatusCode)
    	fmt.Printf("原因: %s\n", resp.Reason)
    	fmt.Printf("响应时间: %f秒\n", resp.Elapsed)
    	fmt.Printf("响应文本: %s\n", resp.Text)
    }
    
    // 发送POST 表单请求
    func TestPostForm(t *testing.T){
    	r := Request{
    		Method: "POST",
    		Url: "https://httpbin.org/post",
    		Data: map[string]string{"name": "张三", "age": "12"},
    		Headers: map[string]string{"Cookie": "abc", "Token": "123"}}
    	resp := r.Send()
    	fmt.Printf("状态码: %d\n", resp.StatusCode)
    	fmt.Printf("原因: %s\n", resp.Reason)
    	fmt.Printf("响应时间: %f秒\n", resp.Elapsed)
    	fmt.Printf("响应文本: %s\n", resp.Text)
    }
    
    // 发送POST JSON请求
    func TestPostJson(t *testing.T){
    	r := Request{
    		Method: "POST",
    		Url: "https://httpbin.org/post",
    		Json: map[string]string{"name": "张三", "age": "12"},
    		Headers: map[string]string{"Cookie": "abc", "Token": "123"}}
    	resp := r.Send()
    	fmt.Printf("状态码: %d\n", resp.StatusCode)
    	fmt.Printf("原因: %s\n", resp.Reason)
    	fmt.Printf("响应时间: %f秒\n", resp.Elapsed)
    	fmt.Printf("响应文本: %s\n", resp.Text)
    }
    
    

    也可以读取json文件并发送请求,示例如下:
    文件data.json内容

    {
      "method": "post",
      "url": "https://httpbin.org/post",
      "data": {"name": "Kevin", "age":  12}
    }
    

    文件requests_test.go内容

    // 读取JSON文件发送请求
    func TestRequestFromJsonFile(t *testing.T) {
    	jsonFile, err := os.Open("data.json")
    	if err != nil {
    		fmt.Println("打开文件失败")
    	}
    	defer jsonFile.Close()
    	jsonData, err := ioutil.ReadAll(jsonFile)
    	if err != nil {
    		fmt.Println("读取JSON文件失败")
    	}
    
    	r := Request{
    		Params: map[string]string{},
    		Headers: map[string]string{},
    		Data: map[string]string{},
    		Json: map[string]string{},
    		Files: map[string]string{}}
    	err = json.Unmarshal(jsonData, &r)
    	if err != nil {
    		fmt.Printf("反序列化出错")
    	}
    	fmt.Println(r)
    	resp := r.Send()
    	fmt.Printf("状态码: %d\n", resp.StatusCode)
    	fmt.Printf("原因: %s\n", resp.Reason)
    	fmt.Printf("响应时间: %f秒\n", resp.Elapsed)
    	fmt.Printf("响应文本: %s\n", resp.Text)
    }
    

    参考:golang常用的http请求操作
    传送门:asmcos版

  • 相关阅读:
    国外的零日漏洞记录片(中文字幕)
    浅谈网络爬虫中广度优先算法和代码实现
    浅谈网络爬虫中深度优先算法和简单代码实现
    Python正则表达式的简单应用和示例演示
    Python正则表达式初识(十)附正则表达式总结
    Python正则表达式初识(九)
    Python正则表达式初识(八)
    Python正则表达式初识(七)
    Python正则表达式初识(六)
    Python正则表达式初识(五)
  • 原文地址:https://www.cnblogs.com/superhin/p/16332720.html
Copyright © 2020-2023  润新知