问题
处理请求返回内容的时候, 遇到 error malformed HTTP response "<html>"
异常信息
探究
根据目前的测试情况,得出的结论是:
- 在请求返回结果为
html
页面时,proxy 需要带上http://
前缀。 - 在请求返回结果为
api
接口时,proxy 需要去掉http://
前缀。
待后续多次验证。
经验证: 以上结论 错误。
请求网址 | 返回结果类型 | proxy格式 | proxy是否带http | 请求结果 |
---|---|---|---|---|
http://ip38.com/ |
html |
http://27.203.219.181:8060 |
是 | ok,已验证 |
http://ip38.com/ |
html |
27.203.219.181:8060 |
否 | 请求正常,代理未生效,已验证 |
https://www.cnblogs.com/ |
html |
http://27.203.219.181:8060 |
是 | error,malformed HTTP response "<html>" ,已验证 |
https://www.cnblogs.com/ |
html |
27.203.219.181:8060 |
否 | ok,已验证 |
https://p.3.cn/prices/mgets |
json |
http://27.203.219.181:8060 |
是 | error,malformed HTTP response "<html>" ,已验证 |
https://p.3.cn/prices/mgets |
json |
27.203.219.181:8060 |
否 | ok,已验证 |
即:
- 请求
http://ip38.com/
时,需要使用 proxy格式为http://27.203.219.181:8060
才能访问成功。 - 请求
https://www.cnblogs.com/
时,需要使用proxy格式为27.203.219.181:8060
才能访问成功。 - 请求
https://p.3.cn/prices/mgets
时,需要使用proxy格式为27.203.219.181:8060
才能访问成功。
我的一种解法
项目中在测试使用代理的代码段:
代码中的 req.XReq()
是对 imroc/req: a golang http request library for humans 的封装。
1 | // 使用了代理ip |
实现逻辑是:
当传入的代理ip格式为 http://27.203.219.181:8060
,先发起请求,如果请求报错,判断错误信息是否包含 malformed HTTP response
,如果包含,则认为是代理ip的格式错误,需要对代理ip处理。
通过 goto
语句,直接跳回到 for
循环之外,对代理ip做格式化处理,截取到 host:port
的格式再次去请求。
为了防止第二次请求时再遇到 malformed HTTP response
错误的话,又会 goto
到 for
循环之外,所以这里加一个标记 is_malformedHttp
,标明代理ip出现格式问题时是否被处理过。
后经测试验证,这种方法无效。
验证结果:
- 当代理格式为
["http://192.168.1.100:8080","192.168.1.120:8080"]
时,proxy1第一次请求异常,经“处理”后请求仍异常,proxy2第一次请求异常。请求结束。 - 当代理格式为
["192.168.1.100:8080","192.168.1.120:8080"]
时,proxy1第一次请求正常。请求结束。
猜测
为什么在代理Ip经处理后的请求,仍然会出错呢?
个人怀疑是 defer
导致的。
defer语句调用一个函数,这个函数执行会推迟,直到外围的函数返回,或者外围函数运行到最后,或者相应的goroutine panic.
在请求之后,需要 defer
去 close
请求。而 defer
又有延后性,也就导致了在 for
循环中的多次请求之间都是有关联的,第一次的请求对象并没有被关闭就继续进行了后续的请求,直到函数结束,请求才被关闭掉。
也就导致了,即使第二次请求时的代理ip去掉了 http://
,请求仍然会失败。
之后如何处理
- 先用
http://27.203.219.181:8060
的代理格式去请求,当遇到malformed HTTP response
错误时,直接抛出异常,等待下次请求。 - 在第二次请求时,将代理ip的格式更改为
27.203.219.181:8060
传入,再去执行请求操作。
相关
推荐
推荐两个请求类:
- req: imroc/req: a golang http request library for humans
- gorequest: parnurzeal/gorequest: GoRequest – Simplified HTTP client ( inspired by nodejs SuperAgent )
以上,仅做记录。由于暂未查询到问题原因,后续持续更新。