不久前用go写了个http client,去模拟某网站(*.com)的登录操作。网站的登录逻辑:1.验证登录账号和密码;2.下发token。此token通过cookie下发;3.redirect到主页(/)。主页对token进行校验,渲染、展示页面信息。简单调用http.DefaultClient.Do(request),并未获取到预期的response,问题究竟出在了什么地方。

net/http.Client 默认自动处理redirect

我们跟踪一下库代码,看一下详细的逻辑。通过函数名,为我们获得一个初步印象:对于“GET”、“HEAD”、“POST”、“PUT”请求,将进行自动重定向。至于“GET”和“HEAD”对于哪些status code进行重定向、“POST”和“PUT”方法又响应哪些status code的重定向呢?关键就在于doFollowingRedirects的第二个入参:shouldRedirectGet和shouldRedirectPost函数。

将case中的常量翻译一下,就是“HEAD”和“GET”方法,响应301、302、303和307;“POST”和“PUT”方法响应302和303。意味着redirect默认是自发执行的,为何登录跳转失败呢?问题出在了cookie上。默认重定向时,并不会保存上次response的cookie,自然不会携带相应的cookie去发起redirect后的请求。

redirect 携带cookie在http.Client中有一个Jar字段,用于存储(内存)cookies。

注释写得很清楚,如果此字段为空,client发起请求时,将不携带cookies且response返回的cookies将被忽略。CookieJar的定义位于net/http的jar.go中,是一个interface。

所谓CookieJar,直白点,就是一个cookie的存储,很自然提供两个方法:SetCookies和Cookies,分别用于set和get操作。net/http/cookiejar中给出了一个CookieJar的实现。

显然Jar中真正用来存储cookies的就是entries这一成员变量了,为一个双map结构。map的第一个key为域名后缀,按照pList(PublicSuffixList)指定的规则来获取;第二个key为cookie name、domain和path拼接而成的一个string。pList可以为空。

无须继续往下,我们已经知晓只要为client设置Jar字段,即可实现redirect的时候携带相应cookie的目的。

自此,问题得以解答。后面再罗嗦一点相关的东西。

jar 的 cookie 匹配规则

实例代码中,通过cookiejar.New(nil)初始化一个cookie jar,即Jar.pList为nil,使用默认的cookie匹配规则。Jar数据结构的介绍中,说明了pList将影响entries map的第一个key,具体的实现为jarKey这个函数。

PublicSuffixList是一个interface,当Jar中为指定此字段时,将采用默认的匹配规则:""作为key(假如域名为,key则为);否则将使用PublicSuffixList的实现类的规则来挑选key,中提供了一种实现,这里不再深究,感兴趣的同学,自行前去观看。

禁止 redirect如果不希望client代替我们做redirect,有什么办法呢?Client数据结构中设计了一个CheckRedirect的字段,此字段是一个函数引用。

从注释中,我们很容易获知禁止redirect的解决方法:CheckRedirect函数简单返回一个http.ErrUseLastResponse即可。这个埋点(CheckRedirect调用)发生在什么位置呢?调用链:http.Do -> c.doFollowingRedirect -> c.checkRedirect。

checkRedirect位于一个for循环中,循环次数由后端redirect的次数和最大允许的递归重试(默认10)次数共同决定。显然,当checkRedirect返回一个http.ErrUseLastResponse的错误后,redirect的循环正常退出。

如何禁止redirect回答完毕。checkRedirect函数,浅显易懂,就不再多介绍。贴出源代码,大家一起再来感受和膜拜一下库作者令人拍案叫绝的设计能力和注释的书写能力!

Go -- client 302 自动转 200 问题 cookie存储 模拟登陆问题的更多相关文章

  1. 爬虫之 cookie , 验证码,模拟登陆,线程

    需求文档的定制 糗事百科的段子内容和作者(xpath的管道符)名称进行爬取,然后存储到mysql中or文本 http://sc.chinaz.com/jianli/free.html爬取简历模板 HT ...

  2. js读写Cookie问题(Cookie存储时长、Cookie存储域)汇总

    在采集网站用户行为数据/使用js对用户行为做交互时,经常会使用到Cookie,了解Js Cookie的读写,以及一些细节,非常重要.   什么是Cookie 所谓Cookie,只是一条极为短小的信息, ...

  3. 使用OKHttp模拟登陆知乎,兼谈OKHttp中Cookie的使用!

    本文主要是想和大家探讨技术,让大家学会Cookie的使用,切勿做违法之事! 很多Android初学者在刚开始学习的时候,或多或少都想自己搞个应用出来,把自己学的十八般武艺全都用在这个APP上,其实这个 ...

  4. cookie : 存储数据

    cookie : 存储数据,当用户访问了某个网站(网页)的时候,我们就可以通过cookie来像访问者电脑上存储数据 1.不同的浏览器存放的cookie位置不一样,也是不能通用的 2.cookie的存储 ...

  5. python 模拟登陆,请求包含cookie信息

    需求: 1.通过GET方法,访问URL地址一,传入cookie参数 2.根据地址一返回的uuid,通过POST方法,传入cooki参数 实现思路: 1.理解http的GET和POST差别 (网上有很多 ...

  6. SetCookies, cookie规范注册表和cookie存储将会优先于设置在HTTP客户端级别中默认的那些

    遇到下面问题解决方法: Hey? 404 抱歉,你输入的网址可能不正确,或者该网页不存在. 7 秒后返回首页 使用独立的本地执行上下文来实现对每个用户(或每个线程)状态的管理. 定义在本地内容中的co ...

  7. 通过js来设置cookie和读取cookie,实现登陆时记住密码的功能

    function setCookie(){ //设置cookie var loginCode = $("#login_code").val(); //获取用户名信息 var pwd ...

  8. Memcache+cookie实现模拟session

    上一片讲到Memcached在Windows上的安装,和用Telnet工具进行命令操作,在稍微了解了原理之后,我也就开始尝试着用程序来对Memcached进行操作.这一篇分为两个部分,第一部分是用.n ...

  9. selenium3.7+ python3 添加cookie模拟登陆

    一.背景介绍 最近做一个爬虫项目,用selenium调用浏览器去获取渲染后的源码,但是每次登陆都需要手机验证,这真的是头痛啊,这种验证方式不要想着去破解,还是老老实实用手机收验证码去吧!反正我是不知道 ...

随机推荐

  1. 谈一谈做iOS播放器库开发所涉及的知识点

    在自己研究生毕业的时候,想着能找上一份做视频编解码的工作,可惜没有如愿,最后到了一家iOS游戏渠道公司去做游戏支付业务的SDK开发,我的iOS正式开发生涯就这么开始了. 在那家iOS游戏渠道没做上一年 ...

  2. Delphi INI 文件读写

    delphi中,配置文件的相关操作. () INI文件的结构: ;这是关于INI文件的注释部分 [节点] 关键字=值 ... INI文件允许有多个节点,每个节点又允许有多个关键字, “=”后面是该关键 ...

  3. Oracle 多表插入

    多表插入 作用:一条INSERT语句可以完成向多张表的插入任务(Multitable insert).有两种形式:insert all与insert first,准备测试环境:1.创建表T并初始化测试 ...

  4. 微信小程序 时间戳 转化为 日期格式

    util.js  : function transTime(unixtime) { var dateTime = new Date(parseInt(unixtime) * 1000) var yea ...

  5. redis实现的简单令牌桶

    这里给出的令牌桶是以redis单节点或者集群为中间件. 不过, 这里的实现比较简单, 主要提供两个函数, 一个用于消费令牌, 一个用于添加令牌. 这里, 消费令牌和添加令牌都是通过lua来保证原子性. ...

  6. H3C 802.11n

  7. jQuery和bootstrap

    1. jQuery学习,搜索开发者网络: js学习: https://www.apeland.con/web/20/568 https://www.apeland.con/web/21 vue饿了么 ...

  8. Codeforces D. Color the Fence(贪心)

    题目描述: D. Color the Fence time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  9. 【Java】Unicode & UTF-8 & UTF-16 & UTF-32

    Unicode Unicode(统一码.万国码.单一码)是计算机科学领域里的一项业界标准,包括字符集.编码方案等.Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设 ...

  10. px em 和rem之间的区别

    背景: px:像素是相对于显示器屏幕分辨率而言的相对长度单位.pc端使用px倒也无所谓,可是在移动端,因为手机分辨率种类颇多,不可能一个个去适配,这时px就显得非常无力,所以就要考虑em和rem. e ...