1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
defmodule AttachmentRangesTest do
use CouchTestCase
@moduletag :attachments
@moduletag kind: :single_node
@moduledoc """
Test CouchDB attachment range requests
This is a port of the attachment_ranges.js suite
"""
@tag :with_db
test "manages attachment range requests successfully", context do
db_name = context[:db_name]
bin_att_doc = %{
_id: "bin_doc",
_attachments: %{
"foo.txt": %{
content_type: "application/octet-stream",
data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
}
}
}
create_doc(db_name, bin_att_doc)
# Fetching the whole entity is a 206
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=0-28"]
)
assert(resp.status_code == 206)
assert resp.body == "This is a base64 encoded text"
assert resp.headers["Content-Range"] == "bytes 0-28/29"
assert resp.headers["Content-Length"] == "29"
# Fetch the whole entity without an end offset is a 200
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=0-"]
)
assert(resp.status_code == 200)
assert resp.body == "This is a base64 encoded text"
assert resp.headers["Content-Range"] == nil
assert resp.headers["Content-Length"] == "29"
# Even if you ask multiple times.
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=0-,0-,0-"]
)
assert(resp.status_code == 200)
# Badly formed range header is a 200
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes:0-"]
)
assert(resp.status_code == 200)
# Fetch the end of an entity without an end offset is a 206
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=2-"]
)
assert(resp.status_code == 206)
assert resp.body == "is is a base64 encoded text"
assert resp.headers["Content-Range"] == "bytes 2-28/29"
assert resp.headers["Content-Length"] == "27"
# Fetch first part of entity is a 206
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=0-3"]
)
assert(resp.status_code == 206)
assert resp.body == "This"
assert resp.headers["Content-Range"] == "bytes 0-3/29"
assert resp.headers["Content-Length"] == "4"
# Fetch middle of entity is also a 206
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=10-15"]
)
assert(resp.status_code == 206)
assert resp.body == "base64"
assert resp.headers["Content-Range"] == "bytes 10-15/29"
assert resp.headers["Content-Length"] == "6"
# Fetch end of entity is also a 206
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=-3"]
)
assert(resp.status_code == 206)
assert resp.body == "ext"
assert resp.headers["Content-Range"] == "bytes 26-28/29"
assert resp.headers["Content-Length"] == "3"
# backward range is 416
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=5-3"]
)
assert(resp.status_code == 416)
# range completely outside of entity is 416
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=300-310"]
)
assert(resp.status_code == 416)
# We ignore a Range header with too many ranges
resp =
Couch.get(
"/#{db_name}/bin_doc/foo.txt",
headers: [Range: "bytes=0-1,0-1,0-1,0-1,0-1,0-1,0-1,0-1,0-1,0-1"]
)
assert(resp.status_code == 200)
end
end
|