当前位置: 首页 > news >正文

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_PROXYHTTPS_PROXYNO_PROXY,如果在 NO_PROXY 排除的地址则不进行代理。
代理地址格式可以是完整的URL,也可以是host[:port]。支持 HTTPHTTPSSOCKS5代理。
如果环境中未定义代理,或者NO_PROXY定义的给定请求不应使用代理,则返回nil URLnil错误。如果 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 连接请求,为每个连接创建一个新goroutinegoroutine读取请求,然后调用处理程序来回复它们。
官方建议 handlernil类型, 则默认使用 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所读取的内容回复给用户请求。

ServeContentio.Copy更好的是,他能够合适的处理一批请求,设置MIME类型,并且能够处理文件是否修改的请求。

如果响应的内容类型头没有设置,该函数首先会尝试从文件的文件扩展名推断文件类型。 如果推断不出来,则会读取文件的第一个块并传送给DetectContentType来检测类型。

文件名称也可以不使用。 如果文字名称为空,则服务器不会传送给响应。 如果修改时间不为0,ServeContent会把它放在服务器响应的Last-Modified头里面。 如果客户端请求中包含了If-Modified-Since头,ServeContent会使用modtime来判断是否把内容传给客户端。
contentSeek方法必须能够工作。 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} 批量插入 功能&#xff1a;单个或批量插入数据&#xff0c;若数据已存在&#xff0c;则忽略 <insert id"saveBatchIgnoreInto" parameterType"java.util.List">insert igno…...

“不是我兄弟”!刘强东内部“狼性训话”流出!

今天&#xff0c;京东创始人刘强东5月24日的线上讲话流出。 在这次线上讲话中&#xff0c;刘强东首先宣布为全体采销员工涨薪20%—100%&#xff0c;随后进行了一番“狼性训话”。往期报道可戳&#xff1a;刘强东怒了&#xff1a;“不是我兄弟”&#xff01; 刘强东在讲话中指…...

函数调用时长的关键点:揭秘参数位置的秘密

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、默认参数的秘密 示例代码 二、关键字参数与位置参数的舞蹈 示例代码 总结 一、默认参…...

【数据分析面试】54.员工信息(HR)数据库搭建

题目 由于发展需求&#xff0c;进一步提高公司人员统筹管理的能力&#xff0c;公司决定要重新升级人力数据管理系统。 现在&#xff0c;你的任务是为公司重新设计和搭建一个员工信息数据库。 提示&#xff1a;考虑HR管理系统的功能&#xff0c;比如人员信息、入职时间、离职…...

通过JavaScript本地存储数据

文章目录 本地存储本地存储分类 - localStorage本地存储分类 - sessionStorage存储复杂数据类型解决方法 本地存储 数据存储在用户浏览器中设置、读取方便、甚至页面刷新都不丢失数据容量较大&#xff0c;sessionStorage和localStorage约5M左右 本地存储分类 - localStorage …...

CTF-web-攻防世界-3

1、inget (1)、进入网站&#xff0c;提示传入id值 (2)、用一些闭合方式&#xff0c;返回都一样。 (3)、尝试万能密码。获得flag 2、mfw (1)、页面没有什么特殊的异常&#xff0c;使用dirsearch进行目录扫描&#xff0c;有一些.git文件。看样子是.git文件泄露。 使用githa…...

【附代码案例】深入理解 PyTorch 张量:叶子张量与非叶子张量

在 PyTorch 中&#xff0c;张量是构建神经网络模型的基本元素。了解张量的属性和行为对于深入理解模型的运行机制至关重要。本文将介绍 PyTorch 中的两种重要张量类型&#xff1a;叶子张量和非叶子张量&#xff0c;并探讨它们在反向传播过程中的行为差异。 叶子张量与非叶子张…...

TypeScript 学习笔记(七):TypeScript 与后端框架的结合应用

1. 引言 在前几篇学习笔记中,我们已经探讨了 TypeScript 的基础知识和在前端框架(如 Angular 和 React)中的应用。本篇将重点介绍 TypeScript 在后端开发中的应用,特别是如何与 Node.js 和 Express 结合使用,以构建强类型、可维护的后端应用。 2. TypeScript 与 Node.js…...

Linux基础知识点总结!超详细

Linux 的学习对于一个IT工程师的重要性是不言而喻的&#xff0c;学好它是工程师必备修养之一。 Linux 基础 操作系统 操作系统Operating System简称OS&#xff0c;是软件的一部分&#xff0c;它是硬件基础上的第一层软件&#xff0c;是硬件和其它软件沟通的桥梁。 操作系统…...

中小学校活动怎样投稿给媒体报道宣传?

身为一名学校老师,同时承担起单位活动向媒体投稿的宣传重任,我深知每一次校园活动背后的故事,都承载着师生们的辛勤汗水与教育的无限可能。起初,我满怀着对教育的热情,希望通过文字传递校园的温暖与光芒,却在投稿的道路上遇到了前所未有的挑战。 最初,我选择了最传统的路径——…...

Python代码:十七、生成列表

1、题目 描述&#xff1a; 一串连续的数据用什么记录最合适&#xff0c;牛牛认为在Python中非列表&#xff08;list&#xff09;莫属了。现输入牛牛朋友们的名字&#xff0c;请使用list函数与split函数将它们封装成列表&#xff0c;再整个输出列表。 输入描述&#xff1a; …...

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…...

藏汉翻译工具有哪些?这三款工具简单好用

藏汉翻译工具有哪些&#xff1f;在全球化日益加剧的今天&#xff0c;语言交流成为连接不同文化、促进民族间沟通与理解的重要桥梁。藏汉翻译工具作为推动藏汉文化交流的得力助手&#xff0c;其在促进民族团结、增进相互理解方面的作用愈发凸显。本文将为您盘点市面上主流的藏汉…...

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单片机-实机演示(单多个数码管)

仿真链接&#xff1a; http://t.csdnimg.cn/QAPhx 目录 一.引脚位置 二.多个显示 三 扩展 一.引脚位置 注意P00 - >A ; 这个多个的在左边,右边的A到B是控制最右边那个单个的. 接下来上显示单个的代码 #include <reg52.h> #include <intrins.h> #define u…...

Pytorch深度学习实践笔记10(b站刘二大人)

&#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;pytorch深度学习 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就是极致重复! 《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibi…...

QT5.15.2及以上版本安装

更新时间&#xff1a;2024-05-20 安装qt5.15以上版本 系统&#xff1a;ubuntu20.04.06 本文安装&#xff1a;linux-5.15.2 下载安装 # 安装编译套件g sudo apt-get install build-essential #安装OpenGL sudo apt-get install libgl1-mesa-dev# 下载qt安装器 https://downl…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...