Skip to content

Commit 24bb16c

Browse files
authored
more debug options (#23)
Added an option to enable detailed verbose logging of OpenAPI request and response
1 parent 3578dee commit 24bb16c

File tree

6 files changed

+112
-70
lines changed

6 files changed

+112
-70
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ keywords = ["Swagger", "OpenAPI", "REST"]
44
license = "MIT"
55
desc = "OpenAPI server and client helper for Julia"
66
authors = ["Tanmay Mohapatra <[email protected]>", "JuliaHub"]
7-
version = "0.1.7"
7+
version = "0.1.8"
88

99
[deps]
1010
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ Client(root::String;
153153
timeout::Int=DEFAULT_TIMEOUT_SECS,
154154
long_polling_timeout::Int=DEFAULT_LONGPOLL_TIMEOUT_SECS,
155155
pre_request_hook::Function,
156+
verbose::Union{Bool,Function}=false,
156157
)
157158
```
158159

@@ -164,11 +165,18 @@ Where:
164165
- `timeout`: optional timeout to apply for server methods (default `OpenAPI.Clients.DEFAULT_TIMEOUT_SECS`)
165166
- `long_polling_timeout`: optional timeout to apply for long polling methods (default `OpenAPI.Clients.DEFAULT_LONGPOLL_TIMEOUT_SECS`)
166167
- `pre_request_hook`: user provided hook to modify the request before it is sent
168+
- `verbose`: whether to enable verbose logging
167169

168170
The `pre_request_hook` must provide the following two implementations:
169171
- `pre_request_hook(ctx::OpenAPI.Clients.Ctx) -> ctx`
170172
- `pre_request_hook(resource_path::AbstractString, body::Any, headers::Dict{String,String}) -> (resource_path, body, headers)`
171173

174+
The `verbose` option can be one of:
175+
- `false`: the default, no verbose logging
176+
- `true`: enables curl verbose logging to stderr
177+
- a function that accepts two arguments - type and message (available on Julia version >= 1.7)
178+
- a default implementation of this that uses `@info` to log the arguments is provided as `OpenAPI.Clients.default_debug_hook`
179+
172180
In case of any errors an instance of `ApiException` is thrown. It has the following fields:
173181

174182
- `status::Int`: HTTP status code

src/client.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ function get_api_return_type(return_types::Dict{Regex,Type}, response_code::Inte
8686
# - otherwise we make it throw an ApiException
8787
return (200 <= response_code <=206) ? Nothing : nothing # first(return_types)[2]
8888
end
89+
90+
function default_debug_hook(type, message)
91+
@info("OpenAPI HTTP transport", type, message)
92+
end
93+
8994
struct Client
9095
root::String
9196
headers::Dict{String,String}
@@ -102,9 +107,14 @@ struct Client
102107
long_polling_timeout::Int=DEFAULT_LONGPOLL_TIMEOUT_SECS,
103108
timeout::Int=DEFAULT_TIMEOUT_SECS,
104109
pre_request_hook::Function=noop_pre_request_hook,
105-
verbose::Bool=false,
110+
verbose::Union{Bool,Function}=false,
106111
)
107-
clntoptions = Dict{Symbol,Any}(:throw=>false, :verbose=>verbose)
112+
clntoptions = Dict{Symbol,Any}(:throw=>false)
113+
if isa(verbose, Bool)
114+
clntoptions[:verbose] = verbose
115+
elseif isa(verbose, Function)
116+
clntoptions[:debug] = verbose
117+
end
108118
downloader = Downloads.Downloader()
109119
downloader.easy_hook = (easy, opts) -> begin
110120
Downloads.Curl.setopt(easy, LibCURL.CURLOPT_LOW_SPEED_TIME, long_polling_timeout)

test/client/allany/petstore_test_petapi.jl

Lines changed: 0 additions & 67 deletions
This file was deleted.

test/client/allany/runtests.jl

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module AllAnyTests
33
include(joinpath(@__DIR__, "AllAnyClient", "src", "AllAnyClient.jl"))
44
using .AllAnyClient
55
using Test
6+
using JSON
67
using OpenAPI
78
using OpenAPI.Clients
89
import OpenAPI.Clients: Client
@@ -50,4 +51,75 @@ function runtests()
5051
@test pet_equals(api_return, pet)
5152
end
5253
end
54+
55+
function test_debug()
56+
@testset "stderr verbose mode" begin
57+
@info("stderr verbose mode")
58+
client = Client(server; verbose=true)
59+
api = M.DefaultApi(client)
60+
61+
pipe = Pipe()
62+
redirect_stderr(pipe) do
63+
pet = M.AnyOfMappedPets(mapped_cat)
64+
api_return, http_resp = echo_anyof_mapped_pets_post(api, pet)
65+
@test pet_equals(api_return, pet)
66+
end
67+
out_str = String(readavailable(pipe))
68+
@test occursin("HTTP/1.1 200 OK", out_str)
69+
end
70+
@testset "debug log verbose mode" begin
71+
@info("debug log verbose mode")
72+
client = Client(server; verbose=OpenAPI.Clients.default_debug_hook)
73+
api = M.DefaultApi(client)
74+
75+
pipe = Pipe()
76+
redirect_stderr(pipe) do
77+
pet = M.AnyOfMappedPets(mapped_cat)
78+
api_return, http_resp = echo_anyof_mapped_pets_post(api, pet)
79+
@test pet_equals(api_return, pet)
80+
end
81+
out_str = String(readavailable(pipe))
82+
@test occursin("HTTP/1.1 200 OK", out_str)
83+
end
84+
@testset "custom verbose function" begin
85+
@info("custom verbose function")
86+
messages = Any[]
87+
client = Client(server; verbose=(type,message)->push!(messages, (type,message)))
88+
api = M.DefaultApi(client)
89+
90+
pet = M.AnyOfMappedPets(mapped_cat)
91+
api_return, http_resp = echo_anyof_mapped_pets_post(api, pet)
92+
@test pet_equals(api_return, pet)
93+
94+
data_out = filter(messages) do elem
95+
elem[1] == "DATA OUT"
96+
end
97+
@test !isempty(data_out)
98+
iob = IOBuffer()
99+
for (type, message) in data_out
100+
write(iob, message)
101+
end
102+
data_out_str = String(take!(iob))
103+
data_out_json = JSON.parse(data_out_str)
104+
@test data_out_json["pet_type"] == "cat"
105+
@test data_out_json["hunts"] == true
106+
@test data_out_json["age"] == 5
107+
108+
data_in = filter(messages) do elem
109+
elem[1] == "DATA IN"
110+
end
111+
@test !isempty(data_in)
112+
iob = IOBuffer()
113+
for (type, message) in data_in
114+
write(iob, message)
115+
end
116+
data_in_str = String(take!(iob))
117+
data_in_str = strip(split(data_in_str, "\n")[2])
118+
data_in_json = JSON.parse(data_in_str)
119+
@test data_in_json["pet_type"] == "cat"
120+
@test data_in_json["hunts"] == true
121+
@test data_in_json["age"] == 5
122+
end
123+
end
124+
53125
end # module AllAnyTests

test/runtests.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,23 @@ include("client/allany/runtests.jl")
5959
run_tests_with_servers && stop_server(8081, ret, out)
6060
end
6161
end
62+
run_tests_with_servers && sleep(20) # avoid port conflicts
63+
@testset "Debug and Verbose" begin
64+
ret = out = nothing
65+
servers_running = true
66+
67+
try
68+
if run_tests_with_servers
69+
ret, out = run_server(joinpath(@__DIR__, "server", "allany", "allany_server.jl"))
70+
servers_running &= wait_server(8081)
71+
if VERSION >= v"1.7"
72+
AllAnyTests.test_debug()
73+
end
74+
else
75+
servers_running = false
76+
end
77+
finally
78+
run_tests_with_servers && stop_server(8081, ret, out)
79+
end
80+
end
6281
end

0 commit comments

Comments
 (0)