Skip to content

Commit d932969

Browse files
omit chunks on client HTTP error (like 404, 403,...) (#134)
* omit chunk on client HTTP error * Allow non-404 errors only if user sets it * Add a doc string * add a test case --------- Co-authored-by: Fabian Gans <[email protected]>
1 parent cbcaead commit d932969

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

src/Storage/http.jl

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,24 @@ python package. In case you experience performance options, one can try to use
1212
"""
1313
struct HTTPStore <: AbstractStore
1414
url::String
15+
allowed_codes::Set{Int}
1516
end
17+
HTTPStore(url) = HTTPStore(url,Set((404,)))
1618

1719
function Base.getindex(s::HTTPStore, k::String)
1820
r = HTTP.request("GET",string(s.url,"/",k),status_exception = false,socket_type_tls=OpenSSL.SSLStream)
1921
if r.status >= 300
20-
if r.status == 404
22+
if r.status in s.allowed_codes
2123
nothing
2224
else
23-
error("Error connecting to $(s.url) :", String(r.body))
25+
err_msg =
26+
"""Received error code $(r.status) when connecting to $(s.url) with message $(String(r.body)).
27+
This might be an actual error or an indication that the server returns a different error code
28+
than 404 for missing chunks. In the later case you can run
29+
`Zarr.missing_chunk_return_code!(a.storage,$(r.status))` where a is your Zarr array or group to
30+
fix the issue.
31+
"""
32+
throw(ErrorException(err_msg))
2433
end
2534
else
2635
r.body
@@ -32,11 +41,28 @@ push!(storageregexlist,r"^https://"=>HTTPStore)
3241
push!(storageregexlist,r"^http://"=>HTTPStore)
3342
storefromstring(::Type{<:HTTPStore}, s,_) = ConsolidatedStore(HTTPStore(s),""),""
3443

44+
"""
45+
missing_chunk_return_code!(s::HTTPStore, code::Union{Int,AbstractVector{Int}})
46+
47+
Extends the list of HTTP return codes that signals that a certain key in a HTTPStore is not available. Most data providers
48+
return code 404 for missing elements, but some may use different return codes like 403. This function can be used
49+
to add return codes that signal missing chunks.
50+
51+
### Example
52+
53+
````julia
54+
a = zopen("https://path/to/remote/array")
55+
missing_chunk_return_code!(a.storage, 403)
56+
````
57+
"""
58+
missing_chunk_return_code!(s::ConsolidatedStore,code) = missing_chunk_return_code!(s.parent,code)
59+
missing_chunk_return_code!(s::HTTPStore, code::Integer) = push!(s.allowed_codes,code)
60+
missing_chunk_return_code!(s::HTTPStore, codes::AbstractVector{<:Integer}) = foreach(c->push!(s.allowed_codes,c),codes)
3561
store_read_strategy(::HTTPStore) = ConcurrentRead(concurrent_io_tasks[])
3662

3763

3864
## This is a server implementation for Zarr datasets
39-
function zarr_req_handler(s::AbstractStore, p)
65+
function zarr_req_handler(s::AbstractStore, p, notfound = 404)
4066
if s[p,".zmetadata"] === nothing
4167
consolidate_metadata(s)
4268
end
@@ -47,12 +73,12 @@ function zarr_req_handler(s::AbstractStore, p)
4773
r = s[p,k]
4874
try
4975
if r === nothing
50-
return HTTP.Response(404, "Error: Key $k not found")
76+
return HTTP.Response(notfound, "Error: Key $k not found")
5177
else
5278
return HTTP.Response(200, r)
5379
end
5480
catch e
55-
return HTTP.Response(404, "Error: $e")
81+
return HTTP.Response(notfound, "Error: $e")
5682
end
5783
end
5884
end

test/storage.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,16 @@ end
146146
@test g2["a1"].attrs == Dict("arratt"=>2.5)
147147
@test g2["a1"][:,:] == reshape(1:200,10,20)
148148
close(server)
149+
#Test server that returns 403 instead of 404 for missing chunks
150+
server = Sockets.listen(0)
151+
ip,port = getsockname(server)
152+
s = Zarr.DictStore()
153+
g = zgroup(s, attrs = Dict("groupatt"=>5))
154+
a = zcreate(Int,g,"a",10,20,chunks=(5,5),attrs=Dict("arratt"=>2.5),fill_value = -1)
155+
@async HTTP.serve(Zarr.zarr_req_handler(s,g.path,403),ip,port,server=server)
156+
g3 = zopen("http://$ip:$port")
157+
@test_throws "Received error code 403" g3["a"][:,:]
158+
Zarr.missing_chunk_return_code!(g3.storage,403)
159+
@test all(==(-1),g3["a"][:,:])
160+
close(server)
149161
end

0 commit comments

Comments
 (0)