Range,If-Range,If-Match是HTTP中的几个头字段,其中Range和If-Range配合可以实现断点续传,If-Match也可以和Range配合,但底层逻辑确是不同。
Range: 按指定范围获取资源,范围越界报416。 If-Range: 断点续传恢复时,用If-Range携带上次获得的资源的etag或Last-Modified检查资源是否已发生变化,是则需要重新下载整个资源,否则取本次Range指定范围的资源。无论是否匹配都只会返回200。 If-Match: 如果资源未变动,则上传资源,否则报412。
btw: MDN上关于If-Match的描述有点小错误,即If-Match不匹配时,报412而不是416,更关键的是If-Match和Range虽然可以搭配使用,逻辑上不符合断点续传的要求,所以业务中,就不要使用Range+If-Match了。博主还提了一个PR,现在已经修正。
下面是一个实际的例子,包括了13个case。
其中使用了一个letter.txt文件作为资源文件。
[root@test01 conf]
abcdefghijklmnopqrstuvwxyz
server {
listen 80;
server_name test;
root html;
access_log logs/200_range_access.log main;
error_log logs/200_range_error.log debug;
location / {
#本例验证Range,If-Range,If-Match使用文件letter.txt
}
}
#测试实例
#case1:验证letter.txt可访问
#[root@test01 conf]# curl test/letter.txt
#abcdefghijklmnopqrstuvwxyz
#case2:取etag
#[root@test01 conf]# curl test/letter.txt -I
#HTTP/1.1 200 OK
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:00:38 GMT
#Content-Type: text/plain; charset=utf-8
#Content-Length: 27
#Last-Modified: Fri, 03 Sep 2021 02:13:49 GMT
#Connection: keep-alive
#ETag: "613184dd-1b"
#Accept-Ranges: bytes
#
#case3:If-Match匹配etag
#[root@test01 conf]# curl test/letter.txt -H 'If-Match: "613184dd-1b"' -I
#HTTP/1.1 200 OK
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:01:00 GMT
#Content-Type: text/plain; charset=utf-8
#Content-Length: 27
#Last-Modified: Fri, 03 Sep 2021 02:13:49 GMT
#Connection: keep-alive
#ETag: "613184dd-1b"
#Accept-Ranges: bytes
#
#case4:If-Match不匹配etag,报412
#[root@test01 conf]# curl test/letter.txt -H 'If-Match: "613184dd-1c"' -I
#HTTP/1.1 412 Precondition Failed
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:01:03 GMT
#Content-Type: text/html; charset=utf-8
#Content-Length: 173
#Connection: keep-alive
#
#case5:If-Match加Range正常case
#[root@test01 conf]# curl test/letter.txt -H 'If-Match: "613184dd-1b"' -H 'Range: bytes=0-5' -I
#HTTP/1.1 206 Partial Content
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:01:20 GMT
#Content-Type: text/plain; charset=utf-8
#Content-Length: 6
#Last-Modified: Fri, 03 Sep 2021 02:13:49 GMT
#Connection: keep-alive
#ETag: "613184dd-1b"
#Content-Range: bytes 0-5/27
#
#case6:If-Match加Range,Range越界,报416
#[root@test01 conf]# curl test/letter.txt -H 'If-Match: "613184dd-1b"' -H 'Range: bytes=33' -I
#HTTP/1.1 416 Requested Range Not Satisfiable
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:01:25 GMT
#Content-Type: text/html; charset=utf-8
#Content-Length: 197
#Connection: keep-alive
#Content-Range: bytes */27
#
#case7:If-Match加Range,etag不匹配且Range越界,报412,说明If-Match优先级高于Range
#[root@test01 conf]# curl test/letter.txt -H 'If-Match: "613184dd-1c"' -H 'Range: bytes=33' -I
#HTTP/1.1 412 Precondition Failed
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:01:30 GMT
#Content-Type: text/html; charset=utf-8
#Content-Length: 173
#Connection: keep-alive
#
#case8:If-Match加Range,交换If-Match和Range的次序,依然报412,说明和参数顺序无关,再次印证了If-Match优先级高于Range
#[root@test01 conf]# curl test/letter.txt -H 'Range: bytes=33' -H 'If-Match: "613184dd-1c"' -I
#HTTP/1.1 412 Precondition Failed
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:02:06 GMT
#Content-Type: text/html; charset=utf-8
#Content-Length: 173
#Connection: keep-alive
#case9:引入If-Range,所有参数正确
#[root@test01 conf]# curl test/letter.txt -H 'Range: bytes=0-5' -H 'If-Match: "613184dd-1b"' -H 'If-Range: "613184dd-1b"' -I
#HTTP/1.1 206 Partial Content
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:42:30 GMT
#Content-Type: text/plain; charset=utf-8
#Content-Length: 6
#Last-Modified: Fri, 03 Sep 2021 02:13:49 GMT
#Connection: keep-alive
#ETag: "613184dd-1b"
#Content-Range: bytes 0-5/27
#
#case10:If-Range不匹配,直接返回200,而不是412,符合业务逻辑,即断点续传应用质量,如果文件发生改变,则需全部重新下载
#[root@test01 conf]# curl test/letter.txt -H 'Range: bytes=0-5' -H 'If-Match: "613184dd-1b"' -H 'If-Range: "613184dd-1c"' -I
#HTTP/1.1 200 OK
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:42:37 GMT
#Content-Type: text/plain; charset=utf-8
#Content-Length: 27
#Last-Modified: Fri, 03 Sep 2021 02:13:49 GMT
#Connection: keep-alive
#ETag: "613184dd-1b"
#Accept-Ranges: bytes
#
#case11:If-Match和If-Range的etag不匹配,返回412,逻辑上If-Match优先
#[root@test01 conf]# curl test/letter.txt -H 'Range: bytes=0-5' -H 'If-Match: "613184dd-1c"' -H 'If-Range: "613184dd-1c"' -I
#HTTP/1.1 412 Precondition Failed
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:42:44 GMT
#Content-Type: text/html; charset=utf-8
#Content-Length: 173
#Connection: keep-alive
#
#case12:If-Match etag不匹配,返回412
#[root@test01 conf]# curl test/letter.txt -H 'Range: bytes=0-5' -H 'If-Match: "613184dd-1c"' -H 'If-Range: "613184dd-1b"' -I
#HTTP/1.1 412 Precondition Failed
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:42:49 GMT
#Content-Type: text/html; charset=utf-8
#Content-Length: 173
#Connection: keep-alive
#
#case13:Range越界,If-Match和If-Range etag不匹配,返回412,依然是If-Match优先
#[root@test01 conf]# curl test/letter.txt -H 'Range: bytes=33' -H 'If-Match: "613184dd-1c"' -H 'If-Range: "613184dd-1c"' -I
#HTTP/1.1 412 Precondition Failed
#Server: nginx/1.20.1
#Date: Wed, 06 Apr 2022 02:42:59 GMT
#Content-Type: text/html; charset=utf-8
#Content-Length: 173
#Connection: keep-alive
|