Go中遇到http code 206和302的获取数据的解决方案

简介: 文章提供了解决Go语言中处理HTTP状态码206(部分内容)和302(重定向)的方案,包括如何获取部分数据和真实请求地址的方法,以便程序员能快速完成工作,享受七夕时光。

http code 206含义是什么

一句话,http code 206标识请求已成功被服务器接收、理解、并接受,服务端只成功处理或返回了部分数据(Partial Content)。

为什么会出现http code 206

第一种情况

客户端请求头发送了部分请求的标识,且服务端支持Range数据。
客户端表明自己只需要目标URL上的部分资源的时候,可以带header里面指定Range字段来表明要获取哪一部分数据,如下面的例子:
req
上例中请求Header Range指明了要获取0-数据,即从0开始的全部数据。

Range头域可以请求实体的一个或者多个子范围,Range的值为0表示第一个字节,也就是Range计算字节数是从0开始的:
表示头500个字节:Range: bytes=0-499
表示第二个500字节:Range: bytes=500-999
表示最后500个字节:Range: bytes=-500
表示500字节以后的范围:Range: bytes=500-
第一个和最后一个字节:Range: bytes=0-0,-1
也可以同时指定几个范围:Range: bytes=500-600,601-999

上例中响应Header Content-Range指明了返回了2027665byte中的0-1048575的部分,也就是说还有后面的一部分没有返回回来,需要客户端进行第二次请求,并将Range写成1048576-2027665即可最终获取到全部数据。由此可以看出206 code可以很好的实现断点续传。

The Content-Range response HTTP header indicates where in a full body message a partial message belongs.

第二种情况

此种情况在爬取别人家的网站时更容易遇到,他们的服务端并不一定支持206 code而是当发现你是外部的非法调用时只给你在业务逻辑上返回了部分数据(比如完成应该返回10条数据,但是只给你返回5条),并且将响应码故意设置成了206。例如下面的例子:

➜  ~ curl -I https://dappradar.com/v2/api/dapps?params=UkdGd2NGSmhaR0Z5Y0dGblpUMHhKbk5uY205MWNEMXRZWGdtWTNWeWNtVnVZM2s5VlZORUptWmxZWFIxY21Wa1BURW1jbUZ1WjJVOWJXOXVkR2dtYzI5eWREMTFjMlZ5Sm05eVpHVnlQV1JsYzJNbWJHbHRhWFE5TWpZPQ==
HTTP/2 206
date: Thu, 04 Aug 2022 09:36:28 GMT
content-type: application/json
cache-control: private, must-revalidate
cache-control: no-cache
pragma: no-cache
expires: -1
x-cache-status: EXPIRED
x-cache-status: EXPIRED
x-frame-options: SAMEORIGIN
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 73564f0f483a3c34-HKG

或者IDE调试
206
可见上面的命令虽然返回206 code,当时并没有出现Content-Range字段。主要是因为这个请求是非法的请求,服务端给强制将本来是200的code设置为了206

如何解决http code 206只返回部分内容的问题

第一种情况的解决

从上面的原理已经看的比较明白了,就是直接按照byte的位置逐次发送请求即可,此时服务端也回返回对应byte返回的数据。这的注意的是每次不要超过服务端最多支持返回的bytes.

第二种情况的解决

这种情况解决方案就是,将自己的请求修改成合法的请求后再次调用就直接返回全部数据,且返回code变成了200. 例如针对上面的爬虫问题,经过尝试发现是因为在请求的Header缺少了cookie字段,添加上之后就可以正确的返回全部数据了。
在这里插入图片描述
上面的请求加上cookie后就正确的返回了全部数据,并且变成了code 200。

http client调用返回了code 302之该如何获取到真实的请求地址

http code 302含义是什么

302状态码表示重定向,浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B。

http code 302与301区别

301是永久重定向,而302是临时重定向。301适合做永久重定向; 302适合做临时的跳转。
301的定义:301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。
302的定义:302 Found 请求的资源现在临时从不同的URI响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。

服务器端跳转就是指地址栏内容不变(客户端浏览器的地址栏不会显示目标地址的URL),客户端请求到达以后,服务器发现当前资源给不出回应,在服务器内部请求另一个资源的跳转。所以跳转与否客户端不知道,属于一次请求。
客户端跳转是指地址栏内容发生改变,客户端再根据服务器端给的响应中的URL再向服务器发送请求,所以是两次请求。客户端请求到达服务端,服务端返回一个 “去访问其他链接” 的回应。

如何获取http code 302真实的跳转地址

302重定向(redirect),那么针对这种方式,go语言默认自动执行redirect的,所以没办法使用get请求获取真实地址对于第一条描述的,在302重定向的时候,真实地址在response的location中。
go语言中,默认是支持10层redirect,所以,除非跳出,否则会redirect 到第10层才退出,然而也是可以自定义的

方法一是通过GET来获取真正的Url
func ParseRealUrl(originUrl string) string {

    client := &http.Client{
        Timeout:       15 * time.Second,
        CheckRedirect: checkRedirect,
    }
    req, err1 := http.NewRequest("GET", originUrl, nil)
    req.Header.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36")
    if err1 != nil {
        log.Sugar().Errorf("NewRequest err:%#v", err1.Error())
        return ""
    }
    resp, err2 := client.Do(req)
    //注意⚠️这里不能err2 != nil而直接返回,这里就是checkRedirect通过返回错误进行的拦截
    if err2 != nil {
        log.Sugar().Errorf("Do err:%#v", err2.Error())
    }
    respUrl, err3 := resp.Location()
    if err3 != nil {
        log.Sugar().Errorf("Location err:%#v", err3.Error())
        return ""
    }
    return respUrl.String()
}

func checkRedirect(req *http.Request, via []*http.Request) error {
    if len(via) >= 1 {
        return fmt.Errorf("checkRedirect len(via) >= 1")
    }
    return nil
}

创建client的时候,指定CheckRedirect为自己重写的myCheckRedirect方法,指定“len(via) >= 1”,即第一次redirect就停止,就可以获取到真实的URL了。

方法二是通过HEAD来获取真正的Url

func ParseRealUrl(originUrl string) string {

    client := &http.Client{
        Timeout:       15 * time.Second,
        CheckRedirect: checkRedirect,
    }
    req, err1 := http.NewRequest("HEAD", originUrl, nil)
    req.Header.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36")
    if err1 != nil {
        log.Sugar().Errorf("NewRequest err:%#v", err1.Error())
        return ""
    }
    resp, err2 := client.Do(req)
    if err2 != nil {
        log.Sugar().Infof("Do err:%#v", err2.Error())
    }
    return resp.Header.Get("Location")
}

func checkRedirect(req *http.Request, via []*http.Request) error {
    if len(via) >= 1 {
        return fmt.Errorf("checkRedirect len(via) >= 1")
    }
    return nil
}

浪漫🌹提醒:翻过技术这座山,你可以与TA浪起来了~

参考

HTTP 206 获取文件部分内容和范围请求
如何处理http返回类型为206的数据
断点续传服务端处理(http206)
HTTP状态码206
面试连环炮系列(十四): HTTP状态码302的跳转逻辑
go自定义http请求,捕获302重定向

相关文章
|
5月前
|
缓存 监控 负载均衡
HTTP代理配置中的常见错误及其解决方案
随着互联网发展,使用HTTP动态代理IP的需求日益增加。配置HTTP代理时常见问题及解决方法包括:1) 代理服务器无法连接:检查网络、防火墙和代理服务状态;2) 认证失败:确认凭据和配置;3) 请求超时:增加超时时间、检查后端服务和网络延迟;4) 缓存问题:清理缓存、设置缓存控制或禁用缓存;5) SSL/TLS问题:正确配置证书并确保客户端信任;6) 访问控制问题:检查ACL和日志;7) 性能问题:监控资源、负载均衡和优化配置;8) 日志记录与分析问题:启用详细日志、设置轮换策略和使用分析工具。通过解决这些问题,可以更有效地管理HTTP代理。
707 13
|
2月前
|
存储 C++
UE5 C++:自定义Http节点获取Header数据
综上,通过为UE5创建一个自定义HTTP请求类并覆盖GetResult方法,就能成功地从HTTP响应的Header数据中提取信息。在项目中使用自定义类,不仅可以方便地访问响应头数据,也可随时使用这些信息。希望这种方法可以为你的开发过程带来便利和效益。
110 35
|
2月前
|
网络架构
CondaHTTPError HTTP 000 CONNECTION FAILED错误解决方案
以上就是解决"CondaHTTPError: HTTP 000 CONNECTION FAILED"错误的一些方法。希望这些方法能够帮助你解决问题。如果以上方法都无法解决你的问题,你可能需要寻求专业的技术支持。
150 23
|
1月前
|
存储 数据库 Python
使用HTTP POST协议将本地压缩数据发送到服务器
总的来说,使用HTTP POST协议将本地压缩数据发送到服务器是一个涉及多个步骤的过程,包括创建压缩文件,设置HTTP客户端,发送POST请求,以及服务器端的处理。虽然这个过程可能看起来复杂,但一旦你理解了每个步骤,就会变得相对简单。
98 19
|
4月前
|
测试技术 Go API
Go 切片导致 rand.Shuffle 产生重复数据的原因与解决方案
在 Go 语言开发中,使用切片时由于其底层数据共享特性,可能会引发意想不到的 Bug。本文分析了 `rand.Shuffle` 后切片数据重复的问题,指出原因在于切片是引用类型,直接赋值会导致底层数组共享,进而影响原始数据。解决方案是使用 `append` 进行数据拷贝,确保独立副本,避免 `rand.Shuffle` 影响原始数据。总结强调了切片作为引用类型的特性及正确处理方法,确保代码稳定性和正确性。
151 82
|
2月前
|
安全 网络安全 定位技术
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
101 22
|
7月前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
134 13
|
7月前
|
消息中间件 测试技术
通过轻量消息队列(原MNS)主题HTTP订阅+ARMS实现自定义数据多渠道告警
轻量消息队列(原MNS)以其简单队列模型、轻量化协议及按量后付费模式,成为阿里云产品间消息传输首选。本文通过创建主题、订阅、配置告警集成等步骤,展示了该产品在实际应用中的部分功能,确保消息的可靠传输。
149 2
|
9月前
|
存储 JSON Go
在Gin框架中优雅地处理HTTP请求体中的JSON数据
在Gin框架中优雅地处理HTTP请求体中的JSON数据
|
9月前
|
JSON JavaScript 前端开发
Haskell中的数据交换:通过http-conduit发送JSON请求
Haskell中的数据交换:通过http-conduit发送JSON请求