Skip to content

Commit f2836c6

Browse files
Allow setting global hooks to modify Easy object
1 parent 0098e40 commit f2836c6

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

src/Downloads.jl

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ using ArgTools
2020
include("Curl/Curl.jl")
2121
using .Curl
2222

23-
export download, request, Downloader, Response, RequestError, default_downloader!
23+
export download, request, Downloader, Response, RequestError, default_downloader!, pushhook!, deletehook!
2424

2525
## public API types ##
2626

@@ -74,6 +74,44 @@ It is expected to be function taking two arguments: an `Easy` struct and an
7474
"""
7575
const EASY_HOOK = Ref{Union{Function, Nothing}}(nothing)
7676

77+
## Allow for a set of global hooks that can customize each download (via setting parameters on the
78+
## `Easy` object associated with a request
79+
const HookKey = Int
80+
current_key = 0
81+
GlobalHookEntry = Tuple{HookKey, Function}
82+
const GLOBAL_HOOK_LOCK = ReentrantLock()
83+
const GLOBAL_HOOKS = Array{GlobalHookEntry,1}(undef, 0)
84+
85+
## Add hook
86+
function pushhook!(hook::Function) :: HookKey
87+
global current_key
88+
key = -1
89+
lock(GLOBAL_HOOK_LOCK) do
90+
key = current_key
91+
push!(GLOBAL_HOOKS, (key, hook))
92+
current_key += 1
93+
end
94+
return key
95+
end
96+
97+
function deletehook!(key::HookKey)
98+
keep = x -> x[1] != key
99+
lock(GLOBAL_HOOK_LOCK) do
100+
count(keep, GLOBAL_HOOKS) < length(GLOBAL_HOOKS) ||
101+
warn("Downloads.jl: Hook key $(key) not found in global hooks")
102+
filter!(keep, GLOBAL_HOOKS)
103+
end
104+
end
105+
106+
function apply_global_hooks(easy::Easy, info::NamedTuple)
107+
lock(GLOBAL_HOOK_LOCK) do
108+
for (_,h) in GLOBAL_HOOKS
109+
h(easy, info)
110+
end
111+
end
112+
end
113+
114+
77115
"""
78116
struct Response
79117
proto :: String
@@ -367,6 +405,8 @@ function request(
367405
progress !== nothing && enable_progress(easy)
368406
set_ca_roots(downloader, easy)
369407
info = (url = url, method = method, headers = headers)
408+
409+
apply_global_hooks(easy, info)
370410
easy_hook(downloader, easy, info)
371411

372412
# do the request

test/runtests.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
include("setup.jl")
22

33
@testset "Downloads.jl" begin
4+
@testset "Global easy hooks" begin
5+
trip_wire = 0
6+
original_hook_count = length(Downloads.GLOBAL_HOOKS)
7+
url = "$server/get"
8+
hook = (easy, info) -> trip_wire += 1
9+
key1 = pushhook!(hook)
10+
_ = download_body(url)
11+
@test trip_wire == 1
12+
key2 = pushhook!(hook)
13+
_ = download_body(url)
14+
@test trip_wire == 3
15+
deletehook!(key1)
16+
_ = download_body(url)
17+
@test trip_wire == 4
18+
deletehook!(key2)
19+
_ = download_body(url)
20+
@test trip_wire == 4
21+
22+
@test length(Downloads.GLOBAL_HOOKS) == original_hook_count
23+
end
24+
#=
425
@testset "libcurl configuration" begin
526
julia = "$(VERSION.major).$(VERSION.minor)"
627
@test Curl.USER_AGENT == "curl/$(Curl.CURL_VERSION) julia/$julia"
@@ -586,6 +607,7 @@ include("setup.jl")
586607
@test Downloads.content_length(["Accept"=>"*/*",]) === nothing
587608
@test Downloads.content_length(["Accept"=>"*/*", "Content-Length"=>"100"]) == 100
588609
end
610+
=#
589611
end
590612

591613
Downloads.DOWNLOADER[] = nothing

0 commit comments

Comments
 (0)