为了账号安全,请及时绑定邮箱和手机立即绑定

使 go http 客户端与非标准 http 服务器一起工作

使 go http 客户端与非标准 http 服务器一起工作

Go
慕妹3242003 2021-11-22 10:37:16
Shoutcast 服务器基本上使用 http,但有一个重要区别:它们GET用ICY 200 OK代替 来响应请求HTTP/1.1 200 OK。Go 不会有它,并且正确地失败并显示错误malformed HTTP version "ICY"。但是,我想让事情顺利进行,并且想知道最好的方法是什么。到目前为止我的想法:使用自定义 http.Transport.Proxy 更改ICY为HTTP/1.1飞行中一个做同样事情的进程外代理重载http.ParseHTTPVersion(但 golang 没有函数重载)复制整个http包,只是为了修改 ParseHTTPVersion数字 1. 似乎最具吸引力,但我不知道如何尊重 http“范围”并实际修改给定 http 版本上的所有响应。这种事情http.Transport.Proxy能搞定吗?任何人都可以给我任何指示吗?
查看完整描述

1 回答

?
FFIVE

TA贡献1797条经验 获得超6个赞

我通过创建一个返回包装连接的自定义 Dial 函数来实现这一点。我的包装器拦截了连接上的第一次读取,并用 HTTP/1.1 替换了 ICY。不是超级健壮,但证明了这个概念:


package main


import (

    "fmt"

    "net"

    "net/http"

)


type IcyConnWrapper struct {

    net.Conn

    haveReadAny bool

}


func (i *IcyConnWrapper) Read(b []byte) (int, error) {

    if i.haveReadAny {

        return i.Conn.Read(b)

    }

    i.haveReadAny = true

    //bounds checking ommitted. There are a few ways this can go wrong.

    //always check array sizes and returned n.

    n, err := i.Conn.Read(b[:3])

    if err != nil {

        return n, err

    }

    if string(b[:3]) == "ICY" {

        //write Correct http response into buffer

        copy(b, []byte("HTTP/1.1"))

        return 8, nil

    }

    return n, nil

}


func main() {


    tr := &http.Transport{

        Dial: func(network, a string) (net.Conn, error) {

            realConn, err := net.Dial(network, a)

            if err != nil {

                return nil, err

            }

            return &IcyConnWrapper{Conn: realConn}, nil

        },

    }

    client := &http.Client{Transport: tr}

    http.DefaultClient = client

    resp, err := http.Get("http://178.33.230.189:8100") //random url I found on the internet

    fmt.Println(err)

    fmt.Println(resp.StatusCode)

}


查看完整回答
反对 回复 2021-11-22
  • 1 回答
  • 0 关注
  • 167 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信