go net/http: 处理空文件的 range 请求

5us2dqdw  于 4个月前  发布在  Go
关注(0)|答案(3)|浏览(47)

你正在使用的Go版本是什么(go version)?

go版本 go1.16.3 darwin/amd64

这个问题在最新版本的发布中是否会重现?

你正在使用什么操作系统和处理器架构(go env)?

go env 输出

$ go env

GO111MODULE=""

GOARCH="amd64"

GOBIN=""

GOCACHE="/Users/matt/Library/Caches/go-build"

GOENV="/Users/matt/Library/Application Support/go/env"

GOEXE=""

GOFLAGS=""

GOHOSTARCH="amd64"

GOHOSTOS="darwin"

GOINSECURE=""

GOMODCACHE="/Users/matt/Code/go/pkg/mod"

GONOPROXY=""

GONOSUMDB=""

GOOS="darwin"

GOPATH="/Users/matt/Code/go"

GOPRIVATE=""

GOPROXY=" [https://proxy.golang.org,direct](https://proxy.golang.org,direct) "

GOROOT="/usr/local/go"

GOSUMDB="sum.golang.org"

GOTMPDIR=""

GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"

GOVCS=""

GOVERSION="go1.16.3"

GCCGO="gccgo"

AR="ar"

CC="clang"

CXX="clang++"

CGO_ENABLED="1"

GOMOD="/Users/matt/Code/go/skyd/go.mod"

CGO_CFLAGS="-g -O2"

CGO_CPPFLAGS=""

CGO_CXXFLAGS="-g -O2"

CGO_FFLAGS="-g -O2"

CGO_LDFLAGS="-g -O2"

PKG_CONFIG="pkg-config"

GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/f9/2yp855dn19s0cqcjwbrv_0900000gn/T/go-build2190681930=/tmp/go-build -gno-record-gcc-switches -fno-common"

你做了什么?

在我们的应用包中,我们向 HEADER 添加了一个范围请求,如下所示:

req, err := c.NewRequest("GET", resource, nil)
	if err != nil {
		return nil, errors.AddContext(err, "failed to construct GET request")
	}
	req.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", from, to))
	httpClient := http.Client{CheckRedirect: c.CheckRedirect}
        res, err := httpClient.Do(req)

当我们将测试扩展到包括零字节(即空文件)时,我们发现 httpClient.Do 方法的响应是 416 Requested Range Not Satisfiable。这是在使用 fromto 值为0的情况下。
我知道从技术上讲这是正确的,因为这个范围请求是在请求第一个字节,而空文件中不存在这个字节。但是,我在文档中找不到一种提交空文件范围请求的方法。
是否有可能更新标准库以提供关于如何为空文件提交范围请求的指导?或者你期望调用者自己做出这个判断,如果是一个空文件就不提交范围请求?

你期望看到什么?

应该有一种处理零字节(空)文件范围请求的标准方法。

你看到了什么?

416 Requested Range Not Satisfiable

nlejzf6q

nlejzf6q1#

What specific behavior do you want here?
From RFC 7433, Section 4.4:
The 416 (Range Not Satisfiable) status code indicates that none of the ranges in the request's Range header field (Section 3.1) overlap the current extent of the selected resource...
A request for "bytes=0-0" is a request for the first byte of a resource. If the resource is 0-length, the range [0,0] does not overlap the resource content and the server responds with a 416. That seems like a correct response.
RFC 7433, Section 4.4 does also state:
For byte ranges, failing to overlap the current extent means that the first-byte-pos of all of the byte-range-spec values were greater than the current length of the selected representation.
That could be read as stating that a request for [0,0] overlaps a 0-length representation, because the first-byte-pos (0) is not greater than the length (0). However, this interpretation would require responding with a 0-length 206 Partial Content response, which is not possible since the Content-Range header does not provide a way to encode a 0-length range. So I believe the interpretation of this sentence consistent with the rest of RFC 7433 is that a range fails to overlap if every first-byte-pos references a value past the end of the content.

4ngedf3f

4ngedf3f2#

你希望在这里看到什么具体的行为?

@neild 感谢你的回复
我同意你的观点。使用范围请求和处理0字节文件似乎是很常见的情况,所以我的主要问题是我们是否可以在Go库中添加文档来处理这种情况,或者为这个特殊情况设置一个特殊情况。
当我在研究这个问题时,我确实找到了一个项目问题,它讨论了使用1-0范围请求来表示0字节文件。SitePen/dstore#109(评论)
如果你觉得Go库不适合处理0字节文件的情况,那么我认为最好在文档中添加一些内容,这样下次有人搜索how to handle 0 byte file range requests in golang时,他们会看到文档说they don't :-),并且每个应用程序都可以处理这些请求。

8dtrkrch

8dtrkrch3#

这并不是一个Go语言的问题。无法为0长度的文件发出符合RFC 7433规范的请求范围。范围请求是请求非零长度字节范围。0长度的文件不包含任何字节。我认为在这种情况下,416 Range Not Satisfiable响应是正确的。还有其他正确的响应(例如,我们可以完全忽略0长度文件的Range头,并返回200响应),但我看不到这些其他可能性更好的理由。我认为对于请求超过文件末尾的数据,回应“对不起,文件没有那么大”并不令人惊讶。
根据RFC 7433,包含bytes=1-0的请求是明确无效的:
如果存在last-byte-pos值且小于first-byte-pos,则字节范围规范无效。

相关问题