Skip to content

Commit 10640b4

Browse files
committed
update readme for client
1 parent de9c4c6 commit 10640b4

File tree

1 file changed

+122
-1
lines changed

1 file changed

+122
-1
lines changed

README.md

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,122 @@
1-
# OpenAPI.jl
1+
# OpenAPI
2+
3+
[![Build Status](https://github.com/tanmaykm/OpenAPI.jl/workflows/CI/badge.svg)](https://github.com/tanmaykm/OpenAPI.jl/actions?query=workflow%3ACI+branch%3Amaster)
4+
[![codecov.io](http://codecov.io/github/tanmaykm/OpenAPI.jl/coverage.svg?branch=master)](http://codecov.io/github/tanmaykm/OpenAPI.jl?branch=master)
5+
6+
This is the Julia library needed with code generated by the [OpenAPI generator](https://openapi-generator.tech/).
7+
8+
The goal of OpenAPI is to define a standard, language-agnostic interface to REST APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined via OpenAPI, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. Similar to what interfaces have done for lower-level programming, OpenAPI removes the guesswork in calling the service.
9+
10+
Check out [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) for additional information about the OpenAPI project, including additional libraries with support for other languages and more.
11+
12+
## How do I use this?
13+
14+
### Code Generation
15+
16+
Use [instructions](https://openapi-generator.tech/docs/generators) provided for the Julia OpenAPI code generator plugin to generate Julia code.
17+
18+
## Generated Code Structure
19+
20+
### Client APIs
21+
22+
Each client API set is generated into a file named `api_<apiname>.jl`. It is represented as a `struct` and the APIs under it are generated as methods. An API set can be constructed by providing the OpenAPI client instance that it can use for communication.
23+
24+
The required API parameters are generated as regular function arguments. Optional parameters are generated as keyword arguments. Method documentation is generated with description, parameter information and return value. Two variants of the API are generated. The first variant is suitable for calling synchronously and returns a single instance of the result struct.
25+
26+
```julia
27+
# example synchronous API that returns an Order instance
28+
getOrderById(api::StoreApi, orderId::Int64)
29+
```
30+
31+
The second variant is suitable for asynchronous calls to methods that return chunked transfer encoded responses, where in the API streams the response objects into an output channel.
32+
33+
```julia
34+
# example asynchronous API that streams matching Pet instances into response_stream
35+
findPetsByStatus(api::PetApi, response_stream::Channel, status::Vector{String})
36+
```
37+
38+
A client context holds common information to be used across APIs. It also holds a connection to the server and uses that across API calls.
39+
The client context needs to be passed as the first parameter of all API calls. It can be created as:
40+
41+
```julia
42+
Client(root::String;
43+
headers::Dict{String,String}=Dict{String,String}(),
44+
get_return_type::Function=(default,data)->default,
45+
timeout::Int=DEFAULT_TIMEOUT_SECS,
46+
long_polling_timeout::Int=DEFAULT_LONGPOLL_TIMEOUT_SECS,
47+
pre_request_hook::Function,
48+
)
49+
```
50+
51+
Where:
52+
53+
- `root`: the root URI where APIs are hosted (should not end with a `/`)
54+
- `headers`: any additional headers that need to be passed along with all API calls
55+
- `get_return_type`: optional method that can map a Julia type to a return type other than what is specified in the API specification by looking at the data (this is used only in special cases, for example when models are allowed to be dynamically loaded)
56+
- `timeout`: optional timeout to apply for server methods (default `OpenAPI.Clients.DEFAULT_TIMEOUT_SECS`)
57+
- `long_polling_timeout`: optional timeout to apply for long polling methods (default `OpenAPI.Clients.DEFAULT_LONGPOLL_TIMEOUT_SECS`)
58+
- `pre_request_hook`: user provided hook to modify the request before it is sent
59+
60+
The `pre_request_hook` must provide the following two implementations:
61+
- `pre_request_hook(ctx::OpenAPI.Clients.Ctx) -> ctx`
62+
- `pre_request_hook(resource_path::AbstractString, body::Any, headers::Dict{String,String}) -> (resource_path, body, headers)`
63+
64+
In case of any errors an instance of `ApiException` is thrown. It has the following fields:
65+
66+
- `status::Int`: HTTP status code
67+
- `reason::String`: Optional human readable string
68+
- `resp::Downloads.Response`: The HTTP Response for this call
69+
- `error::Union{Nothing,Downloads.RequestError}`: The HTTP error on request failure
70+
71+
An API call involves the following steps:
72+
- If a pre request hook is provided, it is invoked with an instance of `OpenAPI.Clients.Ctx` that has the request attributes. The hook method is expected to make any modifications it needs to the request attributes before the request is prepared, and return the modified context.
73+
- The URL to be invoked is prepared by replacing placeholders in the API URL template with the supplied function parameters.
74+
- If this is a POST request, serialize the instance of `APIModel` provided as the `body` parameter as a JSON document.
75+
- If a pre request hook is provided, it is invoked with the prepared resource path, body and request headers. The hook method is expected to modify and return back a tuple of resource path, body and headers which will be used to make the request.
76+
- Make the HTTP call to the API endpoint and collect the response.
77+
- Determine the response type / model, invoke the optional user specified mapping function if one was provided.
78+
- Convert (deserialize) the response data into the return type and return.
79+
- In case of any errors, throw an instance of `ApiException`
80+
81+
### Models
82+
83+
Each model from the specification is generated into a file named `model_<modelname>.jl`. It is represented as a `mutable struct` that is a subtype of the abstract type `APIModel`. Models have the following methods defined:
84+
85+
- constructor that takes keyword arguments to fill in values for all model properties.
86+
- [`propertynames`](https://docs.julialang.org/en/v1/base/base/#Base.propertynames)
87+
- [`hasproperty`](https://docs.julialang.org/en/v1/base/base/#Base.hasproperty)
88+
- [`getproperty`](https://docs.julialang.org/en/v1/base/base/#Base.getproperty)
89+
- [`setproperty!`](https://docs.julialang.org/en/v1/base/base/#Base.setproperty!)
90+
91+
In addition to these standard Julia methods, these convenience methods are also generated that help in checking value at a hierarchical path of the model.
92+
93+
- `function haspropertyat(o::T, path...) where {T<:APIModel}`
94+
- `function getpropertyat(o::T, path...) where {T<:APIModel}`
95+
96+
E.g:
97+
98+
```julia
99+
# access o.field.subfield1.subfield2
100+
if haspropertyat(o, "field", "subfield1", "subfield2")
101+
getpropertyat(o, "field", "subfield1", "subfield2")
102+
end
103+
104+
# access nested array elements, e.g. o.field2.subfield1[10].subfield2
105+
if haspropertyat(o, "field", "subfield1", 10, "subfield2")
106+
getpropertyat(o, "field", "subfield1", 10, "subfield2")
107+
end
108+
```
109+
110+
### Validations
111+
112+
Following validations are incorporated into models:
113+
114+
- maximum value: must be a numeric value less than or equal to a specified value
115+
- minimum value: must be a numeric value greater than or equal to a specified value
116+
- maximum length: must be a string value of length less than or equal to a specified value
117+
- minimum length: must be a string value of length greater than or equal to a specified value
118+
- maximum item count: must be a list value with number of items less than or equal to a specified value
119+
- minimum item count: must be a list value with number of items greater than or equal to a specified value
120+
- enum: value must be from a list of allowed values
121+
122+
Validations are imposed in the constructor and `setproperty!` methods of models.

0 commit comments

Comments
 (0)