Golang封装一个request类支持socks和http代理

Golang封装一个request类支持socks和http代理

1. 需要需用国外服务器做代理的时候
2. 需要使用代理服务器做白名单的时候
3. 代码还支持重试机制

封装代码如下

package utilsimport ("bytes""crypto/tls""errors""fmt""io/ioutil""mime/multipart""net/http""net/url""strings""time""golang.org/x/net/proxy"
)type SendRequest struct {client    *http.ClientretryNum  int // 重试次数retryTime int // 重试间隔时间headers   http.Headerboundary  string
}func NewSendRequest(headers http.Header, boundary string) *SendRequest {if headers == nil {headers = http.Header{}headers.Set("Content-Type", "application/x-www-form-urlencoded")}return &SendRequest{client: &http.Client{Timeout: 30 * time.Second,},retryTime: 10,headers:   headers,boundary:  boundary,}
}func (s *SendRequest) SetHeaders(headers map[string]string) {// 设置请求头for key, value := range headers {s.headers.Set(key, value)}
}func (s *SendRequest) SetProxy(proxyAddr string) {// 创建代理 URLproxyURL, err := url.Parse(proxyAddr)if err != nil {fmt.Println("Failed to parse proxy URL:", err)return}var transport *http.Transportif strings.Contains(proxyAddr, "socks") {dialer, err := proxy.FromURL(proxyURL, proxy.Direct)if err != nil {fmt.Println("Failed to create proxy dialer:", err)return}// 创建自定义的 HTTP 客户端,使用 SOCKS5 代理进行请求transport = &http.Transport{Dial: dialer.Dial,}} else {// 创建自定义的 Transporttransport = &http.Transport{Proxy: http.ProxyURL(proxyURL),TLSClientConfig: &tls.Config{InsecureSkipVerify: true,},}}s.client.Transport = transport
}func (s *SendRequest) send(method string, url string, param url.Values, headers http.Header) ([]byte, *http.Response, error) {reqBody := strings.NewReader(param.Encode())// 设置请求参数if s.boundary != "" {// 创建请求体buf := &bytes.Buffer{}writer := multipart.NewWriter(buf)// 设置分割符号(boundary)writer.SetBoundary(s.boundary)// 添加表单字段到请求体for key, value := range param {for _, v := range value {_ = writer.WriteField(key, v)}}// 关闭 multipart.Writer,以写入结尾标识符_ = writer.Close()reqBody = strings.NewReader(buf.String())}req, err := http.NewRequest(method, url, reqBody)if err != nil {return nil, nil, err}// 设置请求头if headers != nil && len(headers) > 0 {req.Header = headers} else {req.Header = s.headers}resp, err := s.client.Do(req)if err != nil {return nil, nil, err}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)if err != nil {return nil, nil, err}if resp.StatusCode != http.StatusOK {// return nil, nil, errors.New(fmt.Sprintf("状态码:%d,内容:%s", resp.StatusCode, string(body)))return nil, nil, errors.New(fmt.Sprintf("状态码:%d", resp.StatusCode))}return body, resp, nil
}func (s *SendRequest) Post(url string, param url.Values) ([]byte, *http.Response, error) {return s.send("POST", url, param, nil)
}func (s *SendRequest) RepeatPost(url string, param url.Values) ([]byte, *http.Response, error) {// fmt.Printf("[%s][%d]请求地址:%s\n", uuid, num, url)// fmt.Printf("[%s][%d]本次发送:%v\n", uuid, num, param)result, resp, err := s.Post(url, param)if err != nil && s.retryNum < 5 {time.Sleep(time.Second * time.Duration(s.retryTime))// fmt.Printf("[%s][%d]请求返回错误:%v\n", uuid, num, err)s.retryNum++s.retryNum = s.retryNum * 2// 进行重发return s.RepeatPost(url, param)}return result, resp, err
}func (s *SendRequest) Get(url string, headers http.Header) ([]byte, *http.Response, error) {return s.send("GET", url, nil, headers)
}// func main() {
// 	req := NewSendRequest()// 	// 测试 POST 请求
// 	postURL := "http://example.com/api"
// 	postParam := url.Values{
// 		"key1": []string{"value1"},
// 		"key2": []string{"value2"},
// 	}
// 	postHeaders := map[string]string{
// 		"Content-Type": "application/x-www-form-urlencoded",
// 	}
// 	postResult, err := req.Post(postURL, postParam, postHeaders)
// 	if err != nil {
// 		fmt.Println("POST 请求错误:", err)
// 	} else {
// 		fmt.Println("POST 请求结果:", postResult)
// 	}// 	// 测试重复发送 POST 请求
// 	repeatUUID := "12345"
// 	repeatURL := "http://example.com/api"
// 	repeatParam := url.Values{
// 		"key1": []string{"value1"},
// 		"key2": []string{"value2"},
// 	}
// 	repeatTimeout := 0 * time.Second
// 	repeatNum := 1
// 	repeatHeaders := map[string]string{
// 		"Content-Type": "application/x-www-form-urlencoded",
// 	}
// 	req.RepeatPost(repeatUUID, repeatURL, repeatParam, repeatTimeout, repeatNum, repeatHeaders)// 	// 测试 GET 请求
// 	getURL := "http://example.com/api"
// 	getHeaders := map[string]string{
// 		"Content-Type": "application/x-www-form-urlencoded",
// 	}
// 	getResult, err := req.Get(getURL, getHeaders)
// 	if err != nil {
// 		fmt.Println("GET 请求错误:", err)
// 	} else {
// 		fmt.Println("GET 请求结果:", getResult)
// 	}
// }

使用代理请求

package mainimport ("log""xxx/utils"
)func main() {// 这个网站有很多代理ip,但是大部分都用不了会超时或者连接拒绝// https://geonode.com/free-proxy-list// 付费的三方https://ip.huashengdaili.com/sendRequest := utils.NewSendRequest(nil, "")sendRequest.SetProxy("socks4://169.239.49.118:5678")// https://api.ip.sb/ip// https://myip.topbody, _, err := sendRequest.Get("https://myip.top", nil)if err != nil {log.Fatal(err)}log.Println(string(body))
}

当然可以自己搭建一个socks5和http的代理服务器

自己搭建代码如下:

package mainimport ("io""log""net""net/http""os""github.com/armon/go-socks5"
)func handleRequest(w http.ResponseWriter, r *http.Request) {// 建立与后端服务器的连接destConn, err := net.Dial("tcp", r.Host)if err != nil {log.Println("Failed to connect to destination:", err)http.Error(w, "Failed to connect to destination", http.StatusInternalServerError)return}defer destConn.Close()// 将客户端的请求发送到后端服务器err = r.Write(destConn)if err != nil {log.Println("Failed to send request to destination:", err)http.Error(w, "Failed to send request to destination", http.StatusInternalServerError)return}// 将后端服务器的响应返回给客户端_, err = io.Copy(w, destConn)if err != nil {log.Println("Failed to send response to client:", err)http.Error(w, "Failed to send response to client", http.StatusInternalServerError)return}
}func main() {// 创建代理服务器处理程序proxyHandler := http.HandlerFunc(handleRequest)// 启动HTTPS代理服务器go func() {log.Println("proxy 8080")err := http.ListenAndServeTLS(":8080", "./pem/cert.pem", "./pem/key.pem", proxyHandler)if err != nil {log.Fatal("Failed to start proxy server:", err)}}()// 启动SOCKS5代理服务器socksConf := &socks5.Config{}socksServer, err := socks5.New(socksConf)if err != nil {log.Fatal("Failed to create SOCKS5 server:", err)}socksListener, err := net.Listen("tcp", ":1080")if err != nil {log.Fatal("Failed to start SOCKS5 server:", err)}log.Println("SOCKS5 proxy 1080")err = http.Serve(socksListener, socksServer)if err != nil {log.Fatal("Failed to start SOCKS5 server:", err)}
}

证书生成

1. openssl生成参考:https://cloud.tencent.com/developer/article/1548350
2. 在线生成:https://www.lddgo.net/encrypt/ssl

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/738730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全自动内衣洗衣机什么牌子好?热心推荐四款全能硬核的内衣洗衣机

内衣洗衣机这一产品是专为有特殊需求的人士所研发的&#xff0c;其的容量往往都比较小&#xff0c;并且体积也很小巧&#xff0c;安装都非常便捷&#xff0c;作为“家中第二台”补充式洗衣机被很多人推崇&#xff0c;可以作为贴身衣物的专用洗衣机&#xff0c;那么这种内衣洗衣…

Kutools For Excel | 新增 300+ 高级功能

Kutools For Excel 是一个便捷的 Excel 插件&#xff0c;具有 300 多种高级功能&#xff0c;可将各种复杂的任务简化为在 Excel 中的几次单击。 功能强大且用户友好的加载项将为 Excel 用户节省大量工作时间&#xff0c;并大大提高工作效率。支持 Excel 2021 / 2019 / 2016 / …

AIX上的MALLOCTYPE

您可以设置 AIX 中的 MALLOCTYPEwatson 环境变量&#xff0c;以用于 IBM JVM。对于大多数应用程序&#xff0c;因使用该变量而导致性能提升的可能性很低。 特别地&#xff0c;它将有益于所有在代码中大量使用 malloc 调用的应用程序。 Creating the archive (the shared objec…

【基础知识】DPO(Direct Preference Optimization)的原理以及公式是怎样的?

论文&#xff1a;Direct Preference Optimization: Your Language Model is Secretly a Reward Model 1.基本原理 DPO&#xff08;Direct Preference Optimization&#xff09;的核心思想是直接优化语言模型&#xff08;LM&#xff09;以符合人类偏好&#xff0c;而不是首先拟…

【Linux】调试工具 - gdb

目录 一、gdb概述&#xff1a; 二、list&#xff08;查看源文件代码&#xff09;&#xff1a; 三、run&#xff08;运行程序&#xff09;&#xff1a; ​四、断点相关操作&#xff1a; 1、查看断点&#xff1a; 2、在指定行设置断点&#xff1a; 3、在函数入口处设置断…

[计算机效率] 便笺的使用

2.4 便笺 便笺程序是一种方便用户记录、查看和编辑便签的简单应用程序。在Windows系统中&#xff0c;便笺通常作为系统自带的实用工具之一&#xff0c;可以帮助用户快速创建、编辑和组织便签&#xff0c;以便随时记录重要的信息、任务或提醒事项。 便笺程序通常具有以下特点&a…

阿里云企业2核4G5M服务器ECS u1性能测评

阿里云服务器ECS u1实例&#xff0c;2核4G&#xff0c;5M固定带宽&#xff0c;80G ESSD Entry盘优惠价格199元一年&#xff0c;性能很不错&#xff0c;CPU采用Intel Xeon Platinum可扩展处理器&#xff0c;购买限制条件为企业客户专享&#xff0c;实名认证信息是企业用户即可&a…

Metasploit(MSF)使用教程(以ms17_010永恒之蓝为例)

一.Metasploit简介&#xff1a; Metasploit就是一个漏洞框架。它的全称叫做The Metasploit Framework&#xff0c;简称MSF。是一个免费、可下载的框架&#xff0c;通过它可以很容易地获取、开发并对计算机软件漏洞实施攻击。它本身附带数2000多个已知软件漏洞的专业级漏洞攻击工…

如何运用惟客数据CDP客户数据平台构建好用户画像?

​惟客数据CDP是一个企业级客户数据资产平台&#xff0c;能够跨平台整合全域客户数据&#xff0c;统一客户身份&#xff0c;实时全景客户画像&#xff0c;基于大数据计算和挖分析提供深度客户洞察&#xff0c;实现精细化运营和精准营销。部署更轻更快&#xff0c;快速实现企业数…

API接口数据集接口pytorch api接口获取数据

API是应用程序的开发接口&#xff0c;在开发程序的时候&#xff0c;我们有些功能可能不需要从到到位去研发&#xff0c;我们可以拿现有的开发出来的功能模块来使用&#xff0c;而这个功能模块&#xff0c;就叫做库(libary)。比如说&#xff1a;要实现数据传输的安全&#xff0c…

10分钟读懂Diffusion:图解Diffusion扩散模型

数据派THU 本文通过图解的方式让大家快速了解 Diffusion 原理。 [ 导读 ]想必大家都听说过——图像领域大火的深度生成模型Diffusion Model&#xff0c;为了让大家快速了解 Diffusion 原理&#xff0c;这篇文章我们通过图解的方式。希望对你有所帮助&#xff0c;让你在学习和应…

3D Gaussian Splatting for Real-Time Radiance Field Rendering(慢慢啃,还是挺复杂的)

三个关键要素 从相机配准的过程中得到的稀疏点云开始&#xff0c;使用3D Gaussian表示场景; 3D Gaussian: 是连续体积辐射场能够防止不必要的空空间优化。对 3D Gaussion进行交叉优化和密度控制: 优化各向异性血方差对场景精确表示。使用快速可视感知渲染算法来进行快速的训练…

CVE-2024-27199 JetBrains TeamCity 身份验证绕过漏洞2

漏洞简介 TeamCity Web 服务器中发现了第二个身份验证绕过漏洞。这种身份验证旁路允许在没有身份验证的情况下访问有限数量的经过身份验证的端点。未经身份验证的攻击者可以利用此漏洞修改服务器上有限数量的系统设置&#xff0c;并泄露服务器上有限数量的敏感信息。 项目官网…

ORACLE PDB如何配置自启动

有两种方式实现完成&#xff0c;其中 oracle12.1只能使用触发器 oracle12.2可用ALTER pluggable DATABASE ALL save state; 高版本建议优先使用第二种模式 一、触发器模式 CREATE TRIGGER open_all_pdbsAFTER STARTUP ON DATABASE BEGINEXECUTE IMMEDIATE alter pluggable dat…

当HR问你:“什么事会让你有成就感”你该怎么回答?【文章底部添加进大学生就业交流群】

当HR问你“什么事会让你有成就感”时&#xff0c;你可以通过以下方式回答&#xff1a; 强调目标实现&#xff1a; 表达你在达成挑战性目标时感到的满足感。举例说明你在过去的工作或项目中如何设定并成功实现了目标。 强调对团队成功的贡献&#xff1a; 谈论你与团队合作取得成…

Caffeine--实现进程缓存

本地进程缓存特点 缓存在日常开发中起着至关重要的作用, 由于存储在内存中, 数据的读取速度非常快,能大量减少对数据库的访问,减少数据库的压力. 缓存分为两类: 分布式缓存, 例如Redis: 优点: 存储容量大, 可靠性更好, 可以在集群间共享缺点: 访问缓存存在网络开销场景: 缓存数…

c++: 引用能否替代指针? 详解引用与指针的区别.

文章目录 前言1. 引用和指针的最大区别:引用不能改变指向2. 引用和指针在底层上面是一样的3. 引用和指针在sizeof面前大小不同4. 有多级指针,没有多级引用5.引用是引用的实体,指针会向后偏移同一个类型的大小 总结 前言 新来的小伙伴如果不知道引用是什么?可以看我的上一篇文…

Python实战:Python中的数字与字符串:选择合适的类型

在Python编程中&#xff0c;数字和字符串是两种基本的数据类型&#xff0c;但它们在用途和特性上有所不同。本文将深入探讨Python中的数字&#xff08;整数、浮点数、复数&#xff09;和字符串&#xff0c;包括它们的定义、特点、使用场景以及如何选择合适的数据类型。我们将通…

el-table-column嵌套el-form-item不能进行校验问题解决

项目为vue3elementPlus开发的项目 业务要求&#xff1a;table表格展示数据&#xff0c;其中有一行是ip地址可展示可修改&#xff0c;此处要求增加自定义校验规则 先看一下效果&#xff1a; 此处先描述一下&#xff0c;问题出在了哪里&#xff0c;我将el-table的data,使用一个…

Java程序员常用网站(推荐)

文章目录 一、下载网站1 Jdk下载2 清华大学开源软件镜像站2.1 Mysql下载 3 常见工具3.1 typora markdown文档编辑器3.2 Apifox 软件测试工具3.3 GIT3.4 Maven3.5 PDF转word3.6 office3.7 xmind 思维导图3.8 draw.io 画图 4 Java 技术书籍大全 PDF5 Java 8 编程思想中文版6 GitH…