V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
EthanDon
V2EX  ›  程序员

Go 怎么实现 http 请求读到一定的字节数之后立刻返回?

  •  
  •   EthanDon · 2019-06-21 20:07:51 +08:00 · 3161 次点击
    这是一个创建于 1980 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在网上冲浪两天了也没发现方法

    第 1 条附言  ·  2019-06-24 11:28:13 +08:00
    已经结贴了,读取 respinse 的时候是流式读取,自己定义结构就 OK 了,感谢各位大佬
    34 条回复    2019-06-24 12:22:35 +08:00
    Vegetable
        1
    Vegetable  
       2019-06-21 20:12:25 +08:00
    http 是半双工的,这个和需求好像是矛盾的,读到一半断开应该是可以,返回的话还算是 http 吗?
    misaka19000
        2
    misaka19000  
       2019-06-21 20:17:55 +08:00 via Android
    自己解析豹纹呗
    ruoxie
        3
    ruoxie  
       2019-06-21 20:18:06 +08:00
    查一下 Range 请求头相关的
    blackcurrant
        4
    blackcurrant  
       2019-06-21 20:21:58 +08:00
    "网上冲浪" 好久没听到这个词了
    EthanDon
        5
    EthanDon  
    OP
       2019-06-21 20:23:53 +08:00
    @Vegetable 也是,返回之后并不知道是不是请求成功了,状态码是不是 200
    EthanDon
        6
    EthanDon  
    OP
       2019-06-21 20:24:38 +08:00
    @misaka19000 需求是还在传输阶段就段卡,解析报文应该得等到所有报文都到达了才能进行吧?
    EthanDon
        7
    EthanDon  
    OP
       2019-06-21 20:26:35 +08:00
    @ruoxie range 已经用上了,现在的需求时指定了 range 之后,发送请求,为了防止响应的报文过大长时间阻塞在这个 http 请求上,需要在读取一定的数据后就返回
    不知道 go 里可不可以在超时以后返回已经读到的数据
    guonaihong
        8
    guonaihong  
       2019-06-21 20:30:09 +08:00
    这个需求有点类似开发 API 网关,要限制流量的 limit 指令。
    你只要自己实现 Read 接口赋值给 r.Body。自己实现的接口加个计算器就行。
    misaka19000
        9
    misaka19000  
       2019-06-21 20:30:40 +08:00
    你这个需求可以用 nginx 实现,client_max_body_size
    blless
        10
    blless  
       2019-06-21 20:34:17 +08:00 via Android
    bufio 还是哪个库 可以创建一个指定大小的 reader,读到后检查一下是不是 EOF 应该可以吧
    loading
        11
    loading  
       2019-06-21 20:36:02 +08:00
    @blackcurrant “网上冲浪了两天”用时髦点的说法有两种:
    1.在网上浪了两天。
    2.滑水了两天。
    cabing
        12
    cabing  
       2019-06-21 20:39:19 +08:00
    为啥要读取一段字段就立即返回呢?
    loading
        13
    loading  
       2019-06-21 20:39:25 +08:00
    楼主的需求是怕阻塞太久,虽然计算发送字节后主动切断是可以,但是我认为你应该用计时器做,毕竟你关心的似乎是时长?
    EthanDon
        14
    EthanDon  
    OP
       2019-06-21 20:43:26 +08:00
    @cabing
    @loading 时长是一方面,另一方面关心网络情况,需要验证服务器能否在超时时间内返回足够多的数据
    EthanDon
        15
    EthanDon  
    OP
       2019-06-21 20:44:56 +08:00
    @guonaihong r 是 request 吗?兄台可否细说?多谢!
    EthanDon
        16
    EthanDon  
    OP
       2019-06-21 20:45:26 +08:00
    @misaka19000 项目是轻依赖哦,整个环境除了 go 没其他的了
    guonaihong
        17
    guonaihong  
       2019-06-21 20:47:01 +08:00
    @blless 用 bufio,又开辟了一个 buf,多了一层内存拷贝。如果只是关心个数,只用一个计数器就行。 比如定义如下结构
    ```go
    type maxBytesReader struct {
    w http.ResponseWriter
    r io.ReadCloser // underlying reader
    n int64 // max bytes remaining
    err error // sticky error
    }
    ```
    polebug
        18
    polebug  
       2019-06-21 20:47:44 +08:00
    你这得实时解析报文啊 还得计数 真的不会影响性能吗
    guonaihong
        19
    guonaihong  
       2019-06-21 20:48:28 +08:00
    @EthanDon r 是 http.Request。
    guonaihong
        20
    guonaihong  
       2019-06-21 20:51:13 +08:00
    @EthanDon 兄台有感觉了麻?
    loading
        21
    loading  
       2019-06-21 20:55:39 +08:00
    我给你浪了 10 分钟:
    aHR0cHM6Ly9jb2xvYnUuY29tLzIwMTYvMDcvMDEvdGhlLWNvbXBsZXRlLWd1aWRlLXRvLWdvbGFuZy1uZXQtaHR0cC10aW1lb3V0cy8=

    如何切断一个 http,都是在基础包的代码里面。

    如果你说的是 request,你应该知道如何浪出来吧。
    gamexg
        22
    gamexg  
       2019-06-21 20:56:48 +08:00
    ?
    http 标准库的 body 本身是流式实现,你需要多长的 body 就读取多长,读够后直接关闭即可。

    另外 http.Client 带超时控制,可能是你想要的。

    如果需要更底层的控制,可以自己建立 tcp 连接,然后 http.NewRequest 后直接 Write 到自己的 tcp 连接。读取时使用 http.ReadResponse 读取即可。http.ReadResponse 接收的是 bufio.Reader,意味着你可以用 io.LimitReader 封装 tcp 连接实现限制尺寸。
    gamexg
        23
    gamexg  
       2019-06-21 20:57:43 +08:00
    @gamexg #22 htt.Get 等函数只要接收到 http 响应头即可返回 ,body 等内容是你从 Body 读取时才从 tcp 连接读取的。
    Leigg
        24
    Leigg  
       2019-06-21 21:05:32 +08:00 via iPhone
    数据分段传啊
    guonaihong
        25
    guonaihong  
       2019-06-21 21:10:19 +08:00
    @EthanDon 这是 gin 里面 limit 模块代码, 可以参考下。https://github.com/gin-contrib/size

    本来准备写一个的,发现有现成的。
    Vegetable
        26
    Vegetable  
       2019-06-21 21:38:11 +08:00
    @EthanDon 傻了都,这不就是 nginx 的 413 吗?参照这个逻辑设计肯定行得通的.
    flynaj
        27
    flynaj  
       2019-06-22 09:22:05 +08:00 via Android
    HTTP 协议不成的话,你可以 socket 编程。自己处理数据包,只是工程有点大。
    EthanDon
        28
    EthanDon  
    OP
       2019-06-24 11:16:46 +08:00
    @guonaihong 周末去浪浪,我这就去了解一下
    EthanDon
        29
    EthanDon  
    OP
       2019-06-24 11:18:30 +08:00
    @Vegetable 主要是不能用 nginx。。。自己造轮子的话对 go 还不太熟悉。。。
    EthanDon
        30
    EthanDon  
    OP
       2019-06-24 11:25:20 +08:00
    @gamexg 啊明白了,我以为哪个 response 是读完才返回的,可以结贴了!感谢大佬
    EthanDon
        31
    EthanDon  
    OP
       2019-06-24 11:26:06 +08:00
    @guonaihong 我去康康
    @flynaj 感谢各位,结贴了
    EthanDon
        32
    EthanDon  
    OP
       2019-06-24 11:26:39 +08:00   ❤️ 1
    @loading 找到了解决方法,感谢
    EthanDon
        33
    EthanDon  
    OP
       2019-06-24 11:27:12 +08:00
    @loading 大佬浪的姿势比我好啊,请问一哈关键字和引擎是啥,我搜的都不知道是啥玩意
    loading
        34
    loading  
       2019-06-24 12:22:35 +08:00 via Android
    @EthanDon golang 的网络基础库,虽然我还没开始看,到时我知道请求能断,所以我搜索了几个关键字。
    golang net 断 关 这些,用 google。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   988 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:31 · PVG 04:31 · LAX 12:31 · JFK 15:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.