@@ -7,6 +7,8 @@ More generally, the module exports functions and types that provide lower-level
77for file downloading:
88- [`download`](@ref) — download a file from a URL, erroring if it can't be downloaded
99- [`request`](@ref) — request a URL, returning a `Response` object indicating success
10+ - [`pushhook!`](@ref) — add a hook which allows for customizing downloading parameters
11+ - [`deletehook!`](@ref) — remove a previously added parameter customization hook
1012- [`Response`](@ref) — a type capturing the status and other metadata about a request
1113- [`RequestError`](@ref) — an error type thrown by `download` and `request` on error
1214- [`Downloader`](@ref) — an object encapsulating shared resources for downloading
@@ -20,7 +22,7 @@ using ArgTools
2022include (" Curl/Curl.jl" )
2123using . Curl
2224
23- export download, request, Downloader, Response, RequestError, pushhook!, deletehook!
25+ export download, request, pushhook!, deletehook!, Downloader, Response, RequestError
2426
2527# # public API types ##
2628
@@ -68,30 +70,75 @@ const EASY_HOOK = Ref{Union{Function, Nothing}}(nothing)
6870# # Allow for a set of global hooks that can customize each download (via setting parameters on the
6971# # `Easy` object associated with a request
7072const HookKey = Int
71- current_key = 0
73+ CURRENT_KEY = 0
7274GlobalHookEntry = Tuple{HookKey, Function}
7375const GLOBAL_HOOK_LOCK = ReentrantLock ()
7476const GLOBAL_HOOKS = Array {GlobalHookEntry,1} (undef, 0 )
7577
7678# # Add hook
79+ """
80+ pushhook!(hook) -> key
81+
82+ hook :: Function
83+ key :: HookKey
84+ Add a hook to customize download parameters for all downloads.
85+
86+ The signature `hook` should be `(easy::Easy, info::Dict) -> Nothing``.
87+ Mulitple hooks can be added with repeated calls to `pushhook!`. Hooks are
88+ applied in the order they were added.
89+
90+ The returned `key` maybe used to remove a previously added `hook` cf. [deletehook!](@ref)
91+
92+ Examples:
93+ ```jl
94+ # define hook
95+ hook = (easy, info) -> begin
96+ # allow for long pauses during downloads (perhaps for malware scanning)
97+ setopt(easy, Downloads.Curl.CURLOPT_LOW_SPEED_LIMIT, 1 #= bytes =#)
98+ setopt(easy, Downloads.Curl.CURLOPT_LOW_SPEED_TIME , 200 #= seconds =#)
99+
100+ # other possibilities
101+ # set ca_roots
102+ # disable certificate verification
103+ # block or rewrite URLs
104+
105+ end
106+
107+ # add hook
108+ key = pushhook!(hook)
109+
110+ # would fail with default download parameters...
111+ download("https://httpbingo.julialang.org/delay/40", "test.txt")
112+
113+ # cleanup
114+ deletehook!(key)
115+ ```
116+ """
77117function pushhook! (hook:: Function ) :: HookKey
78- global current_key
118+ global CURRENT_KEY
79119 key = - 1
80120 lock (GLOBAL_HOOK_LOCK) do
81- key = current_key
121+ key = CURRENT_KEY
82122 push! (GLOBAL_HOOKS, (key, hook))
83- current_key += 1
123+ CURRENT_KEY += 1
84124 end
85- return key
125+ key
86126end
87127
128+ """
129+ deletehook!(key)
130+ key :: HookKey
131+
132+ Remove a hook previously added with [`pushhook!`](@ref).
133+ """
88134function deletehook! (key:: HookKey )
89135 keep = x -> x[1 ] != key
90136 lock (GLOBAL_HOOK_LOCK) do
91137 count (keep, GLOBAL_HOOKS) < length (GLOBAL_HOOKS) ||
92138 warn (" Downloads.jl: Hook key $(key) not found in global hooks" )
93139 filter! (keep, GLOBAL_HOOKS)
94140 end
141+ nothing
95142end
96143
97144function apply_global_hooks (easy:: Easy , info:: NamedTuple )
@@ -100,6 +147,7 @@ function apply_global_hooks(easy::Easy, info::NamedTuple)
100147 h (easy, info)
101148 end
102149 end
150+ nothing
103151end
104152
105153
0 commit comments