Skip to content

Commit 46e79a8

Browse files
Add documentation.
1 parent a1d80a7 commit 46e79a8

File tree

3 files changed

+124
-29
lines changed

3 files changed

+124
-29
lines changed

README.md

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

1515
## API
1616

17-
The public API of `Downloads` consists of two functions and three types:
17+
The public API of `Downloads` consists of four functions and three 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
21+
- `pushhook!` — add a hook which allows for customizing downloading parameters
22+
- `deletehook!` — remove a previously added parameter customization hook
2123
- `Response` — a type capturing the status and other metadata about a request
2224
- `RequestError` — an error type thrown by `download` and `request` on error
2325
- `Downloader` — an object encapsulating shared resources for downloading
@@ -128,6 +130,52 @@ be downloaded (indicated by non-2xx status code), `request` returns a `Response`
128130
object no matter what the status code of the response is. If there is an error
129131
with getting a response at all, then a `RequestError` is thrown or returned.
130132

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

133181
```jl

src/Downloads.jl

Lines changed: 54 additions & 6 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
@@ -20,7 +22,7 @@ using ArgTools
2022
include("Curl/Curl.jl")
2123
using .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
7072
const HookKey = Int
71-
current_key = 0
73+
CURRENT_KEY = 0
7274
GlobalHookEntry = Tuple{HookKey, Function}
7375
const GLOBAL_HOOK_LOCK = ReentrantLock()
7476
const 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+
"""
77117
function 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
86126
end
87127

128+
"""
129+
deletehook!(key)
130+
key :: HookKey
131+
132+
Remove a hook previously added with [`pushhook!`](@ref).
133+
"""
88134
function 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
95142
end
96143

97144
function 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
103151
end
104152

105153

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"
@@ -581,7 +560,27 @@ include("setup.jl")
581560
@test Downloads.content_length(["Accept"=>"*/*",]) === nothing
582561
@test Downloads.content_length(["Accept"=>"*/*", "Content-Length"=>"100"]) == 100
583562
end
584-
=#
563+
564+
@testset "Global easy hooks" begin
565+
trip_wire = 0
566+
original_hook_count = length(Downloads.GLOBAL_HOOKS)
567+
url = "$server/get"
568+
hook = (easy, info) -> trip_wire += 1
569+
key1 = pushhook!(hook)
570+
_ = download_body(url)
571+
@test trip_wire == 1
572+
key2 = pushhook!(hook)
573+
_ = download_body(url)
574+
@test trip_wire == 3
575+
deletehook!(key1)
576+
_ = download_body(url)
577+
@test trip_wire == 4
578+
deletehook!(key2)
579+
_ = download_body(url)
580+
@test trip_wire == 4
581+
582+
@test length(Downloads.GLOBAL_HOOKS) == original_hook_count
583+
end
585584
end
586585

587586
Downloads.DOWNLOADER[] = nothing

0 commit comments

Comments
 (0)