Golang net/http标准库常用方法(三)
大家好,针对Go语言 net/http 标准库,将梳理的相关知识点分享给大家~~
围绕 net/http 标准库相关知识点还有许多章节,请大家多多关注。
文章中代码案例只有关键片段,完整代码请查看github仓库:https://github.com/hltfaith/go-example/tree/main/net-http
本章节案例,请大家以 go1.16+ 版本以上进行参考。
net/http标准库系列文章
- Golang net/http标准库常用请求方法(一)
- Golang net/http标准库常用方法(二)
- Golang net/http标准库常用方法(三)
本节内容
- ProxyFromEnvironment() 函数
- ProxyURL() 函数
- Serve() 函数
- ServeContent() 函数
- DetectContentType() 函数
- MaxBytesReader() 函数
ProxyFromEnvironment()
ProxyFromEnvironment()函数,用于读取所在环境的环境变量返回代理地址。比如环境变量HTTP_PROXY、HTTPS_PROXY和NO_PROXY,如果在 NO_PROXY 排除的地址则不进行代理。
代理地址格式可以是完整的URL,也可以是host[:port]。支持 HTTP、HTTPS、SOCKS5代理。
如果环境中未定义代理,或者NO_PROXY定义的给定请求不应使用代理,则返回nil URL和nil错误。如果 req.URL.Host 地址为 localhost 加或没加端口,都会返回 nil 错误。
函数原型
func ProxyFromEnvironment(req *Request) (*url.URL, error)
函数使用
proxyfromenvironment.go
func main() {os.Setenv("HTTP_PROXY", "http://127.0.0.1:12345")req, err := http.NewRequest("GET", "http://example.com", nil)if err != nil {panic(err)}url, err := http.ProxyFromEnvironment(req)if err != nil {panic(err)}fmt.Println(url)
}
案例中 http.ProxyFromEnvironment(req) 仅会把读取环境变量 HTTP_PROXY 的代理地址,在我们使用 http.NewRequest() 请求时,不会使用代理请求。
下面通过 ProxyURL() 函数案例,发起代理请求。
ProxyURL()
ProxyURL() 作用是返回一个代理函数主要用于在 Transport{} 类型中,其参数是代理地址。
函数原型
func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error)
举例:使用代理发送 HTTP 请求。
proxyurl.go
func main() {url, err := url.Parse("http://188.68.176.2:8080")if err != nil {panic(err)}client := http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(url),TLSClientConfig: &tls.Config{InsecureSkipVerify: true},},}res, err := client.Get("http://baidu.com")if err != nil {panic(err)}b, _ := httputil.DumpRequest(res.Request, false)fmt.Println(string(b))
}
上述例子中, 将代理函数ProxyURL(url)通过Transport{}类型封装好后,向目标服务发送GET请求。
Client{}、Transport{}类型后续文章将详细讲解。
注:代理地址,可以参考 https://www.kuaidaili.com/free/fps/ 用于测试使用。
上面案例,也可以将 http.ProxyURL() 函数改成 ProxyFromEnvironment() 用环境变量的方式。
proxyurl2.go
func main() {url, err := url.Parse("http://google.com")if err != nil {panic(err)}os.Setenv("HTTP_PROXY", "http://127.0.0.1:7890")client := http.Client{Transport: &http.Transport{Proxy: http.ProxyFromEnvironment,TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 跳过https},}req := http.Request{Method: "GET",URL: url,Header: map[string][]string{"Proxy-Connection": {"keep-alive"},},}res, err := client.Do(&req)if err != nil {panic(err)}defer res.Body.Close()
}
这里是通过我本地环境的代理VPN所监听的端口 http://127.0.0.1:7890
下面我通过抓包,大家可以看到执行代理请求的时候源端口 50130是我们请求端,访问的谷歌网站目的端已经变成了 http://127.0.0.1:7890 地址也是我们的代理端,后面的响应也是由代理端给我们请求回应数据包。

Serve()
Serve() 函数,接收监听 HTTP 连接请求,为每个连接创建一个新goroutine。goroutine读取请求,然后调用处理程序来回复它们。
官方建议 handler 为 nil类型, 则默认使用 DefaultServerMux 全局锁机制。 (可以参考上篇文章中有所介绍)
只有当 Listener 返回tls的时候,才支持HTTP/2协议。
Serve() 函数返回非 nil 的报错。
函数原型
func Serve(l net.Listener, handler Handler) error
Serve()函数实际上是调用的 Server{} 类型中封装的一个方法。
func Serve(l net.Listener, handler Handler) error {srv := &Server{Handler: handler}return srv.Serve(l)
}
例如,上篇文章中介绍的 ListenAndServe()、ListenAndServeTLS() 方法它们最终执行都是 Server{}类型中的 Serve() 方法。
函数使用
serve.go
func main() {ln, err := net.Listen("tcp", ":8080")if err != nil {panic(err)}http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {io.WriteString(w, "帽儿山的枪手!\n")})log.Panicln(http.Serve(ln, nil))
}
ServeContent()
ServeContent() 函数,使用ReadSeeker所读取的内容回复给用户请求。
ServeContent比io.Copy更好的是,他能够合适的处理一批请求,设置MIME类型,并且能够处理文件是否修改的请求。
如果响应的内容类型头没有设置,该函数首先会尝试从文件的文件扩展名推断文件类型。 如果推断不出来,则会读取文件的第一个块并传送给DetectContentType来检测类型。
文件名称也可以不使用。 如果文字名称为空,则服务器不会传送给响应。 如果修改时间不为0,ServeContent会把它放在服务器响应的Last-Modified头里面。 如果客户端请求中包含了If-Modified-Since头,ServeContent会使用modtime来判断是否把内容传给客户端。
content的Seek方法必须能够工作。 ServeContent通过定位到文件结尾来确定文件大小。 *os.File中实现了io.ReadSeeker接口。
函数原型
func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker)
- 参数
w服务器响应 - 参数
req客户端请求 - 参数
name文件名称 - 参数
modtime文件的修改时间 - 参数
content文件的内容,必须实现io.ReadSeeker这个接口中的方法
下面案例使用 ServeContent() 函数实现文件下载功能。
servecontent.go
func main() {http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {file := "servecontent.go"fileBytes, err := ioutil.ReadFile(file)if err != nil {panic(err)}mime := http.DetectContentType(fileBytes)fileSize := len(string(fileBytes))w.Header().Set("Content-Type", mime)w.Header().Set("Content-Disposition", "attachment; filename="+file)w.Header().Set("Content-Length", strconv.Itoa(fileSize))http.ServeContent(w, r, file, time.Now(), bytes.NewReader(fileBytes))})log.Fatal(http.ListenAndServe(":8080", nil))
}
首先通过 DetectContentType()函数获取了文件的 MIME 类型,然后将文件转换为 Byte 类型传入 ServeContent() 函数中实现下载功能。
结合上篇文章中介绍的 ServeFile()函数它实现起来更简洁仅需要一行代码实现文件下载,但前提需要知道文件上下文路径。
ServeContent() 函数更适用于当你只能拿到 byte[] 数据时,可以优先使用它。
DetectContentType()
DetectContentType() 该函数实现了一个算法,用来检测指定的数据是否符合该标准http://mimesniff.spec.whatwg.org 。
最多需要数据的前512个字节,DetectContentType()会返回一个有效的MIME类型。 如果它不能够识别数据,将会返回"application/octet-stream"。
函数原型
func DetectContentType(data []byte) string
函数使用
func main() {// image/pngfmt.Println(http.DetectContentType([]byte("\x89PNG\x0D\x0A\x1A\x0A")))// image/jpegfmt.Println(http.DetectContentType([]byte("\xFF\xD8\xFF")))
}
注:一些类型的识别,可以参考go源码测试用例。
MaxBytesReader()
MaxBytesReader() 函数,用来保护服务器端,以避免客户端偶然或者恶意发送的长数据请求导致的服务端资源的浪费。
MaxBytesReader()跟io.LimitReader函数很像。但是它被设计来设置接收的请求体的最大大小。 跟io.LimitReader不同MaxBytesReader()的返回值是一个ReadCloser,当读取超过限制时会返回non-nil错误。 并且当它调用关闭方法的时候会把潜在的读取者(函数/进程)也关闭掉。
函数原型
func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser
- 参数
w服务器响应 - 参数
r可以指向 req.Body - 参数
n限制大小
案例,限制客户端上传数据为10个字节。
maxbytesreader.go
func main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {r.Body = http.MaxBytesReader(w, r.Body, 10)_, err := io.Copy(ioutil.Discard, r.Body)if err != nil {panic(err)}io.WriteString(w, "200\n")})log.Fatal(http.ListenAndServe(":8080", nil))
}
下面我们通过 curl 命令模拟客户端请求, 其中body内容已经超出了10个字节
root@hc:~# curl --location --request POST 'http://127.0.0.1:8080' \
--header 'Content-Type: application/json' \
--data-raw '{"t": "1234567890"
}'
请求完成后,看到服务端已经提示 请求Body过大。

技术文章持续更新,请大家多多关注呀~~
搜索微信公众号,关注我【 帽儿山的枪手 】
相关文章:
Golang net/http标准库常用方法(三)
大家好,针对Go语言 net/http 标准库,将梳理的相关知识点分享给大家~~ 围绕 net/http 标准库相关知识点还有许多章节,请大家多多关注。 文章中代码案例只有关键片段,完整代码请查看github仓库:https://github.com/hltfa…...
24校招总结
个人背景 本科:三本通信专业 硕士:B区双非计算机硕 今年2月签了东南沿海二线城市某公司C游戏服务端开发 我同学大部分都是去电网,大专老师,气象局事业编……就我这个是纯牛马了。 离收到Offer3个月了,前段时间参加…...
PHP APCu缓存使用与避坑
APCu 极简概括: PHP 的开源内存缓存扩展,类比Redis,但是一般都用Redis,所以APCu用的很少。官方文档:https://www.php.net/manual/zh/apcu.configuration.php解决问题:类比Redis做缓存组件,提升…...
mybatis xml
delete from t_enterprise_output_value where output_id IN #{outputId} 批量插入 功能:单个或批量插入数据,若数据已存在,则忽略 <insert id"saveBatchIgnoreInto" parameterType"java.util.List">insert igno…...
“不是我兄弟”!刘强东内部“狼性训话”流出!
今天,京东创始人刘强东5月24日的线上讲话流出。 在这次线上讲话中,刘强东首先宣布为全体采销员工涨薪20%—100%,随后进行了一番“狼性训话”。往期报道可戳:刘强东怒了:“不是我兄弟”! 刘强东在讲话中指…...
函数调用时长的关键点:揭秘参数位置的秘密
新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、默认参数的秘密 示例代码 二、关键字参数与位置参数的舞蹈 示例代码 总结 一、默认参…...
【数据分析面试】54.员工信息(HR)数据库搭建
题目 由于发展需求,进一步提高公司人员统筹管理的能力,公司决定要重新升级人力数据管理系统。 现在,你的任务是为公司重新设计和搭建一个员工信息数据库。 提示:考虑HR管理系统的功能,比如人员信息、入职时间、离职…...
通过JavaScript本地存储数据
文章目录 本地存储本地存储分类 - localStorage本地存储分类 - sessionStorage存储复杂数据类型解决方法 本地存储 数据存储在用户浏览器中设置、读取方便、甚至页面刷新都不丢失数据容量较大,sessionStorage和localStorage约5M左右 本地存储分类 - localStorage …...
CTF-web-攻防世界-3
1、inget (1)、进入网站,提示传入id值 (2)、用一些闭合方式,返回都一样。 (3)、尝试万能密码。获得flag 2、mfw (1)、页面没有什么特殊的异常,使用dirsearch进行目录扫描,有一些.git文件。看样子是.git文件泄露。 使用githa…...
【附代码案例】深入理解 PyTorch 张量:叶子张量与非叶子张量
在 PyTorch 中,张量是构建神经网络模型的基本元素。了解张量的属性和行为对于深入理解模型的运行机制至关重要。本文将介绍 PyTorch 中的两种重要张量类型:叶子张量和非叶子张量,并探讨它们在反向传播过程中的行为差异。 叶子张量与非叶子张…...
TypeScript 学习笔记(七):TypeScript 与后端框架的结合应用
1. 引言 在前几篇学习笔记中,我们已经探讨了 TypeScript 的基础知识和在前端框架(如 Angular 和 React)中的应用。本篇将重点介绍 TypeScript 在后端开发中的应用,特别是如何与 Node.js 和 Express 结合使用,以构建强类型、可维护的后端应用。 2. TypeScript 与 Node.js…...
Linux基础知识点总结!超详细
Linux 的学习对于一个IT工程师的重要性是不言而喻的,学好它是工程师必备修养之一。 Linux 基础 操作系统 操作系统Operating System简称OS,是软件的一部分,它是硬件基础上的第一层软件,是硬件和其它软件沟通的桥梁。 操作系统…...
中小学校活动怎样投稿给媒体报道宣传?
身为一名学校老师,同时承担起单位活动向媒体投稿的宣传重任,我深知每一次校园活动背后的故事,都承载着师生们的辛勤汗水与教育的无限可能。起初,我满怀着对教育的热情,希望通过文字传递校园的温暖与光芒,却在投稿的道路上遇到了前所未有的挑战。 最初,我选择了最传统的路径——…...
Python代码:十七、生成列表
1、题目 描述: 一串连续的数据用什么记录最合适,牛牛认为在Python中非列表(list)莫属了。现输入牛牛朋友们的名字,请使用list函数与split函数将它们封装成列表,再整个输出列表。 输入描述: …...
C++ 程序的基本要素
一 标识符 程序中变量、类型、函数和标号的名称称标识符。 a,b,name,int,char,main,void等。 系统已有的标识符称为关键字。 常见关键字 using,namespace,void,return; int,float,double,char,bool,signed,unsignex, long,short,const,true,false,sizeof if,else,for,do,whil…...
藏汉翻译工具有哪些?这三款工具简单好用
藏汉翻译工具有哪些?在全球化日益加剧的今天,语言交流成为连接不同文化、促进民族间沟通与理解的重要桥梁。藏汉翻译工具作为推动藏汉文化交流的得力助手,其在促进民族团结、增进相互理解方面的作用愈发凸显。本文将为您盘点市面上主流的藏汉…...
three.js官方案例webgl_loader_fbx.html学习
目录 1.1 添加库引入 1.2 添加必要的组件scene,camera,webrenderer等 1.3 模型加载 1.4 半球光 1.5 动画 1.6 换个自己的fbx模型 1.7 fbx模型和fbx动画关联 1.7 html脚本全部如下 1.8 fbx.js全部脚本如下 1.1 添加库引入 import * as THREE from three; import Stats …...
51单片机-实机演示(单多个数码管)
仿真链接: http://t.csdnimg.cn/QAPhx 目录 一.引脚位置 二.多个显示 三 扩展 一.引脚位置 注意P00 - >A ; 这个多个的在左边,右边的A到B是控制最右边那个单个的. 接下来上显示单个的代码 #include <reg52.h> #include <intrins.h> #define u…...
Pytorch深度学习实践笔记10(b站刘二大人)
🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:pytorch深度学习 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就是极致重复! 《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibi…...
QT5.15.2及以上版本安装
更新时间:2024-05-20 安装qt5.15以上版本 系统:ubuntu20.04.06 本文安装:linux-5.15.2 下载安装 # 安装编译套件g sudo apt-get install build-essential #安装OpenGL sudo apt-get install libgl1-mesa-dev# 下载qt安装器 https://downl…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
