限制从 HTTP 响应读取的字节数

dmz*_*rsk 3 http go

我需要读取用户提供的 URL 的响应

我不希望他们通过大文件的链接使我的服务器超载。

我想最多读取 N 个字节,如果还有更多字节要读取,则返回错误。

我可以读取 N 个字节,但是我如何检测该文件不完整(假设远程文件正好是 N 个字节长的极端情况)?

icz*_*cza 7

net/http除了彼得的回答之外,软件包中还有一个现成的解决方案http.MaxBytesReader()::

func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser
Run Code Online (Sandbox Code Playgroud)

MaxBytesReader 与 io.LimitReader 类似,但旨在限制传入请求正文的大小。与 io.LimitReader 相比,MaxBytesReader 的结果是 ReadCloser,对于超出限制的 Read 返回非 EOF 错误,并在调用其 Close 方法时关闭底层读取器。

最初它是为了限制传入请求主体的大小而“设计”的,但它也可以用于限制传入响应主体。为此,只需传递nil参数即可ResponseWriter

使用它的示例:

{
    body := ioutil.NopCloser(bytes.NewBuffer([]byte{0, 1, 2, 3, 4}))
    r := http.MaxBytesReader(nil, body, 4)
    buf, err := ioutil.ReadAll(r)
    fmt.Println("When body is large:", buf, err)
}

{
    body := ioutil.NopCloser(bytes.NewBuffer([]byte{0, 1, 2, 3, 4}))
    r := http.MaxBytesReader(nil, body, 5)
    buf, err := ioutil.ReadAll(r)
    fmt.Println("When body is exact (OK):", buf, err)
}

{
    body := ioutil.NopCloser(bytes.NewBuffer([]byte{0, 1, 2, 3, 4}))
    r := http.MaxBytesReader(nil, body, 6)
    buf, err := ioutil.ReadAll(r)
    fmt.Println("When body is small (OK):", buf, err)
}
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上尝试):

When body is large: [0 1 2 3] http: request body too large
When body is exact (OK): [0 1 2 3 4] <nil>
When body is small (OK): [0 1 2 3 4] <nil>
Run Code Online (Sandbox Code Playgroud)