这两天在开发项目的时候遇到了一个问题,请求了一个URL,它会302到另一个地址,本意上只是想检查这个URL是否会做3XX的redirect跳转,结果每次reqeust都会返回最后一跳的结果。后来就看了下源码,了解下请求跳转的机制

实现代码

看下实现的简单代码

func main() {
client := &http.Client{}
url := "http://www.qq.com"
reqest, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(err)
}
response, _ := client.Do(reqest)
fmt.Println(response.Status)
} curl http://www.qq.com
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>stgw/1.3.12.4_1.13.5</center>
</body>
</html>

我们知道在浏览器里面输入http://www.qq.com会302跳转到https://www.qq.com。我们使用curl可以看到使用302的跳转。

可是我只想获取第一跳的的response 的状态码。发现没法实现了,所以看了下源码。

http请求为什么可以做到多次redirect

看了下 client.Do 源码实现

607 err = c.checkRedirect(req, reqs)

代码的上下文,可以看出 req是将要请求的request,reqs已经请求过的request

主要看下checkRedirect

func (c *Client) checkRedirect(req *Request, via []*Request) error {
fn := c.CheckRedirect
if fn == nil {
fn = defaultCheckRedirect
}
return fn(req, via)
}

可以看到如果设置了checkRedirect就执行checkRedirect,如果没有设置就执行 defaultCheckRedirect。

再看下 defaultCheckRedirect

func defaultCheckRedirect(req *Request, via []*Request) error {
if len(via) >= 10 {
return errors.New("stopped after 10 redirects")
}
return nil
}

可以看到最多可以redirect 10次,如果大于10的跳转就抛出错误结束这次请求了。

大体上流程已经搞明白。只要设置checkRedirect返回error,理论上就能实现只请求一次的目的。

func main() {
client := &http.Client{}
url := "http://www.qq.com"
reqest, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(err)
}
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return fmt.Errorf("first response")
}
response, _ := client.Do(reqest)
fmt.Println(response.StatusCode)
} /private/var/folders/4h/lrsc4fyd12v9ctl31ggk5ckc0000gp/T/___go_build_main_go #gosetup
302

基本实现了。

其实,在CheckRedirect方法上面有一行说明,

ErrUseLastResponse can be returned by Client.CheckRedirect hooks to control how redirects are processed. If returned, the next request is not sent and the most recent response is returned with its body unclosed.

Client.CheckRedirect挂钩可以返回ErrUseLastResponse,以控制如何处理重定向。 如果返回,则不发送下一个请求,并且返回最近的响应且其主体未关闭。

可以看到返回 ErrUseLastResponse是官方的建议的设置

最终的代码实现应该是这样的。

```bash
func main() {
client := &http.Client{}
url := "http://www.qq.com"
reqest, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(err)
}
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
response, _ := client.Do(reqest)
fmt.Println(response.StatusCode)
}

golang开发:http请求redirect的问题的更多相关文章

  1. Golang开发支持平滑升级(优雅重启)的HTTP服务

    Golang开发支持平滑升级(优雅重启)的HTTP服务 - tabalt的博客 http://tabalt.net/blog/graceful-http-server-for-golang/ http ...

  2. golang开发:环境篇(五)实时加载工具gin的使用

    gin 工具是golang开发中非常有用且有效的工具,有效的提高了开发调试go程序的效率. 为什么要使用gin 我们知道golang是编译型语言,这就表示go程序的每次改动,如果需要查看改动结果都必须 ...

  3. 十分钟学会Golang开发gRPC服务

    gRPC是Google发起的一个开源RPC框架,使用HTTP/2传输协议,使用Protocol Buffers编码协议,相比RESTful框架的程序性能提高不少,而且当前流行的编程语言基本都已经支持. ...

  4. 使用golang 开发的 andriod应用

    最近在捣鼓一个东东,就是使用golang开发andriod应用.说起来简单操作起来还挺麻烦,中间又学习了很多东西.比如ubuntu,docker,angular,ionic,jquery mobile ...

  5. golang开发android环境搭建_window

    golang开发android环境搭建介绍 一 安装依赖软件: git:版本管理 go:  go开发环境(版本>=1.5),可直接下载window版的go安装包. android studio: ...

  6. Windows下visual studio code搭建golang开发环境

    Windows下visual studio code搭建golang开发环境 序幕 其实环境搭建没什么难的,但是遇到一些问题,主要是有些网站资源访问不了(如:golang.org),导致一些包无法安装 ...

  7. linux golang开发环境配置(离线方式)

    <获取开发工具>     到https://www.golangtc.com/download 下载安装包, 根据自己的系统选择合适的开发包,这里选择go.1.9.2.linux-amd6 ...

  8. miniblink+golang开发windows gui应用

    golang的优点自不必说了,这么好的语言怎么能缺少界面库呢?所以我使用miniblink开发了一个可以用html,css,js开发界面的浏览器,通过它你能为你的golang开发简单的界面.说白了其实 ...

  9. Linux下golang开发环境搭建

    对于golang开发来说,Windows下可以用vscode或者liteide都不错,但是Linux下的开发也就只有vim了,所以怎么搞笑的利用vim进行golang开发呢? 参考官方推荐的一个插件: ...

随机推荐

  1. BeautifulSoup解析页面

    beautiful soup是一个解析包,专门用来解析html语法的,lxml是一个解析器,用来分析以及定位内容的 .是class #是id import requests from bs4 impo ...

  2. Redis中有序列表(ZSet)相关命令

    redis语序集合和集合set是一样内部value为string类型的集合,有序不允许重复元素 但是,zset的每个元素有一个double类型的分数(score).redis正是靠这个分数对元素从小到 ...

  3. Java基础一篇过(一)反射

    一.反射是个啥 定义 : 在运行状态中动态获取的类的信息以及动态调用对象的方法,这种功能称为java语言的反射机制. 对于任意一个类,都能够知道这个类的所有属性和方法. 对于任意一个对象,都能够调用它 ...

  4. 堆的源码与应用:堆排序、优先队列、TopK问题

    1.堆 堆(Heap))是一种重要的数据结构,是实现优先队列(Priority Queues)首选的数据结构.由于堆有很多种变体,包括二项式堆.斐波那契堆等,但是这里只考虑最常见的就是二叉堆(以下简称 ...

  5. 手撸Mysql原生语句--多表

    在开始之前,我们需要建立表,做建表和数据的准备的工作. 1.建表 create table department( id int, name varchar(20) ); create table e ...

  6. Spring学习(十)--Spring的AOP

    1.Spring AOP拦截器 (1)设计原理 Spring AOP在通过JDK的Proxy或者CGLIB方式生成代理对象的时候,拦截器的相关信息就配置到代理对象中了. 1)如果使用JDK的Proxy ...

  7. 【数量技术宅 | Python爬虫系列分享】实时监控股市重大公告的Python爬虫

    实时监控股市重大公告的Python爬虫小技巧 精力有限的我们,如何更加有效率地监控信息? 很多时候特别是交易时,我们需要想办法监控一些信息,比如股市的公告.如果现有的软件没有办法实现我们的需求,那么就 ...

  8. 033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结

    033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结 本文知识点:运算符和表达式知识点总结 前面学习的几篇文都是运算符和表达式相关的知 ...

  9. 《C++primerplus》第12章练习题

    做一下倒数两题,都是在队列模拟的程序基础上做点修改测试. 5.找出平均等候时间为1分钟时,每小时到达的客户数为多少(试验时间不少于100小时). 指定队伍最大长度10人,模拟100小时.粗略估计答案在 ...

  10. 【题解】[JSOI2007]字符加密

    Link \(\text{Solution:}\) 后缀数组第一题祭-- 观察一下,这个是让求一个环形的原字符串的后缀,我们可以考虑一下断环为链. 对于\(aba\)我们扩展成\(abaaba,\)则 ...