RestClient v1.1 is just out, and don’t let the minor version bump fool you, it’s a pretty substantial release.
Features
F.1 Streaming responses
I’ve had a think about how to make it as easy as possible to support streamed responses, through methods like SSE and NDJSON (which OOTB support is provided for). I’ve landed on a convenient wrapper type: Stream{T} for a stream of T objects that uses a Channel internally and supports iteration.
This means all it takes to read responses from a streaming API is:
@jsondef struct Delta
type::String
text."delta.text"::Union{String, Nothing} = nothing
end
# take a prompt string and post it to /messages, to get a stream of Deltas
@endpoint chat(prompt::String) -> prompt -> :post("messages") -> Stream{Delta}
for msg in chat("send me messages")
println(msg.text)
end
If you want the full SSE frame data, you can just ask for a Stream{SSEvent{T}} and you’ll get SSEvent{T}s out of your iterator.
If you want to close a stream early, you can call close on the stream in another task.
F.2 HTTP form and multipart payloads
In addition to @jsondef and @xmldef, you can now define form and multipart payloads with @formdef and @multipartdef:
@formdef struct LoginInfo
username::String
password::String
rememberme."remember-me"::Bool = false
end
@jsondef struct UserInfo ... end
@endpoint login(auth::LoginInfo) -> auth -> :post("login") -> UserInfo
F.3 Authentication convenience
APIs that take authentication details often use basic, bearer, header, or query based authentication. Previously, RestClient required you to provide this in every endpoint manually, but no longer.
@globalconfig RequestConfig(...) auth=BearerAuth() # or,
@globalconfig RequestConfig(...) auth=(QueryAuth("api_key"), :required)
If you specify the authentication in @globalconfig, all @endpoints defined will use it by default (as always, this can be customised per-endpoint). To make public/authenticated API splits easy though, @endpoint now supports a :auth/:noauth/:authoption keyword:
@endpoint :noauth userinfo(...) -> ...
@endpoint :auth login(...) -> ...
Improvements
- Support for JSON.jl, while keeping the existing support for JSON3.jl
- More structured errors, with
MalformedRequest for requests that fail validation and ResponseErrors for unsuccessful calls
- Better rate limiting with an atomic deadline
- More thorough validation, as
validate may now return a whole list of issues
RequestConfig will try to avoid printing its secret key (if set) in the REPL, while still supporting repr round-tripping
julia> RequestConfig("https://api.example.com", key = "keepmesecret")
RequestConfig("https://api.example.com"; key = "*****", cache = true)
Fixes
- getxattr error detection on Linux
setexpiry erroring on non-unix systems
- handling of function keyword arguments in
@endpoint
Other changes
- We now take a bytes-first approach to data type interpretation over IO (the previous approach), which made streaming support a lot easier