Skip to content

Commit a30270e

Browse files
Add documentation.
1 parent f2836c6 commit a30270e

File tree

3 files changed

+123
-28
lines changed

3 files changed

+123
-28
lines changed

README.md

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ Julia 1.3 through 1.5 as well.
1414

1515
## API
1616

17-
The public API of `Downloads` consists of three functions and three types:
17+
The public API of `Downloads` consists of the following functions and types:
1818

1919
- `download` — download a file from a URL, erroring if it can't be downloaded
2020
- `request` — request a URL, returning a `Response` object indicating success
2121
- `default_downloader!` - set the default `Downloader` object
22+
- `pushhook!` — add a hook which allows for customizing downloading parameters
23+
- `deletehook!` — remove a previously added parameter customization hook
2224
- `Response` — a type capturing the status and other metadata about a request
2325
- `RequestError` — an error type thrown by `download` and `request` on error
2426
- `Downloader` — an object encapsulating shared resources for downloading
@@ -141,6 +143,52 @@ with getting a response at all, then a `RequestError` is thrown or returned.
141143
Set the default `Downloader`. If no argument is provided, resets the default downloader
142144
so that a fresh one is created the next time the default downloader is needed.
143145

146+
### pushhook!
147+
```jl
148+
pushhook!(hook) -> key
149+
```
150+
- `hook :: Function`
151+
- `key :: HookKey`
152+
153+
Add a hook to customize download parameters for all downloads.
154+
155+
The signature `hook` should be `(easy::Easy, info::Dict) -> Nothing`.
156+
Multiple hooks can be added with repeated calls to `pushhook!`. Hooks are
157+
applied in the order they were added.
158+
159+
The returned `key` maybe used to remove a previously added `hook` cf. `deletehook!`
160+
161+
Examples:
162+
```jl
163+
# define hook
164+
hook = (easy, info) -> begin
165+
# allow for long pauses during downloads
166+
# (perhaps for malware scanning)
167+
setopt(easy, Downloads.Curl.CURLOPT_LOW_SPEED_LIMIT, 1 #= bytes =#)
168+
setopt(easy, Downloads.Curl.CURLOPT_LOW_SPEED_TIME , 200 #= seconds =#)
169+
# other possibilities
170+
# set ca_roots
171+
# disable certificate verification
172+
# block or rewrite URLs
173+
end
174+
175+
# add hook
176+
key = pushhook!(hook)
177+
178+
# would fail with default download parameters...
179+
download("https://httpbingo.julialang.org/delay/40", "test.txt")
180+
181+
# cleanup
182+
deletehook!(key)
183+
```
184+
185+
### deletehook!
186+
```jl
187+
deletehook!(key)
188+
```
189+
- `key :: HookKey`
190+
191+
Remove a hook previously added with `pushhook!.
144192
### Response
145193

146194
```jl

src/Downloads.jl

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ More generally, the module exports functions and types that provide lower-level
77
for 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
7981
const HookKey = Int
80-
current_key = 0
82+
CURRENT_KEY = 0
8183
GlobalHookEntry = Tuple{HookKey, Function}
8284
const GLOBAL_HOOK_LOCK = ReentrantLock()
8385
const 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+
"""
86126
function 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
95135
end
96136

137+
"""
138+
deletehook!(key)
139+
key :: HookKey
140+
141+
Remove a hook previously added with [`pushhook!`](@ref).
142+
"""
97143
function 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
104151
end
105152

106153
function 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
112160
end
113161

114162

test/runtests.jl

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,6 @@
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-
#=
254
@testset "libcurl configuration" begin
265
julia = "$(VERSION.major).$(VERSION.minor)"
276
@test Curl.USER_AGENT == "curl/$(Curl.CURL_VERSION) julia/$julia"
@@ -607,7 +586,27 @@ include("setup.jl")
607586
@test Downloads.content_length(["Accept"=>"*/*",]) === nothing
608587
@test Downloads.content_length(["Accept"=>"*/*", "Content-Length"=>"100"]) == 100
609588
end
610-
=#
589+
590+
@testset "Global easy hooks" begin
591+
trip_wire = 0
592+
original_hook_count = length(Downloads.GLOBAL_HOOKS)
593+
url = "$server/get"
594+
hook = (easy, info) -> trip_wire += 1
595+
key1 = pushhook!(hook)
596+
_ = download_body(url)
597+
@test trip_wire == 1
598+
key2 = pushhook!(hook)
599+
_ = download_body(url)
600+
@test trip_wire == 3
601+
deletehook!(key1)
602+
_ = download_body(url)
603+
@test trip_wire == 4
604+
deletehook!(key2)
605+
_ = download_body(url)
606+
@test trip_wire == 4
607+
608+
@test length(Downloads.GLOBAL_HOOKS) == original_hook_count
609+
end
611610
end
612611

613612
Downloads.DOWNLOADER[] = nothing

0 commit comments

Comments
 (0)