这两天在开发项目的时候遇到了一个问题,请求了一个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. 容器云平台No.6~企业级分布式存储Ceph

    简介 ceph作为一个统一的分布式存储系统,提供了高性能,高可用性,高扩展性.ceph的统一体现在其可以提供文件系统.块存储.对象存储,在云环境中,通常采用ceph作为后端存储来保证数据的高可用性. ...

  2. PYG2010-02-精装友情通讯录再分析

  3. 面试可能遇到的关联式容器(map、set等)相关问题

    >>>. map与set的区别是什么,各有哪些优势?   map中存储的数据是以键值对(key - value)形式并且通过排序(比较key,默认以 '<' 方式排序)存在的( ...

  4. java进阶(23)--List接口

    一.基本概念 1.有序可重复 2.有下标 3.包含ArraList.LinkedList.Vector   二.List中特有的方法 且常用 (以下军均为数组通用方法) 1.void add(int ...

  5. HAProxy安装配置

    概念 HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案. HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要 ...

  6. Python-TypeError: object() takes no parameters

    Error: TypeError: object() takes no parameters Where? 使用自定义类的时候,实例类的时候传递参数,提示这个错误 Why? 因为类实例的时候,并不需要 ...

  7. 069 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 01 综合案例-数组移位-案例需求

    069 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 01 综合案例-数组移位-案例需求 本文知识点:综合案例-数组移位-案例需求 说明:因为时间紧张,本人写博客 ...

  8. MATLAB textread函数

    实际应用中经常要读取txt文件,这个时候就需要用到强大的textread函数.它的基本语法是:[A,B,C,...] = textread(filename,format)[A,B,C,...] = ...

  9. 【基础】dp系列1

    序列双段最大子段和问题 (也许很水但蒟蒻刚刚学dp就来记录一下) 题目链接 题意就是求序列中的任意两段的最大子段和最大. 我们先预处理出来前缀和,方便求最大子段和. 对于每一个i都求一遍1到i的最大子 ...

  10. CentOS7 下 swap 分区的创建、删除及相关配置

    一般我们在购买云服务器(例如:阿里云ECS.腾讯云服务器)的时候,选择 CentOS 7 系统之后,登录系统,发现 swap 大小为 0(即没有分配). 如果我们想在该 服务器上安装 Oracle 数 ...