@@ -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
@@ -77,30 +79,75 @@ const EASY_HOOK = Ref{Union{Function, Nothing}}(nothing)
7779# # Allow for a set of global hooks that can customize each download (via setting parameters on the
7880# # `Easy` object associated with a request
7981const HookKey = Int
80- current_key = 0
82+ CURRENT_KEY = 0
8183GlobalHookEntry = Tuple{HookKey, Function}
8284const GLOBAL_HOOK_LOCK = ReentrantLock ()
8385const GLOBAL_HOOKS = Array {GlobalHookEntry,1} (undef, 0 )
8486
8587# # Add hook
88+ """
89+ pushhook!(hook) -> key
90+
91+ hook :: Function
92+ key :: HookKey
93+ Add a hook to customize download parameters for all downloads.
94+
95+ The signature `hook` should be `(easy::Easy, info::Dict) -> Nothing``.
96+ Mulitple hooks can be added with repeated calls to `pushhook!`. Hooks are
97+ applied in the order they were added.
98+
99+ The returned `key` maybe used to remove a previously added `hook` cf. [deletehook!](@ref)
100+
101+ Examples:
102+ ```jl
103+ # define hook
104+ hook = (easy, info) -> begin
105+ # allow for long pauses during downloads (perhaps for malware scanning)
106+ setopt(easy, Downloads.Curl.CURLOPT_LOW_SPEED_LIMIT, 1 #= bytes =#)
107+ setopt(easy, Downloads.Curl.CURLOPT_LOW_SPEED_TIME , 200 #= seconds =#)
108+
109+ # other possibilities
110+ # set ca_roots
111+ # disable certificate verification
112+ # block or rewrite URLs
113+
114+ end
115+
116+ # add hook
117+ key = pushhook!(hook)
118+
119+ # would fail with default download parameters...
120+ download("https://httpbingo.julialang.org/delay/40", "test.txt")
121+
122+ # cleanup
123+ deletehook!(key)
124+ ```
125+ """
86126function pushhook! (hook:: Function ) :: HookKey
87- global current_key
127+ global CURRENT_KEY
88128 key = - 1
89129 lock (GLOBAL_HOOK_LOCK) do
90- key = current_key
130+ key = CURRENT_KEY
91131 push! (GLOBAL_HOOKS, (key, hook))
92- current_key += 1
132+ CURRENT_KEY += 1
93133 end
94- return key
134+ key
95135end
96136
137+ """
138+ deletehook!(key)
139+ key :: HookKey
140+
141+ Remove a hook previously added with [`pushhook!`](@ref).
142+ """
97143function deletehook! (key:: HookKey )
98144 keep = x -> x[1 ] != key
99145 lock (GLOBAL_HOOK_LOCK) do
100146 count (keep, GLOBAL_HOOKS) < length (GLOBAL_HOOKS) ||
101147 warn (" Downloads.jl: Hook key $(key) not found in global hooks" )
102148 filter! (keep, GLOBAL_HOOKS)
103149 end
150+ nothing
104151end
105152
106153function apply_global_hooks (easy:: Easy , info:: NamedTuple )
@@ -109,6 +156,7 @@ function apply_global_hooks(easy::Easy, info::NamedTuple)
109156 h (easy, info)
110157 end
111158 end
159+ nothing
112160end
113161
114162
0 commit comments