| Did you know ... | Search Documentation: |
| Pack logtalk -- logtalk-3.101.0/docs/handbook/_sources/libraries/open_api.rst.txt |
.. _library_open_api:
open_api
The open_api library provides a first-pass implementation for
deriving, parsing, generating, and structurally validating OpenAPI 3.1.0
documents. It builds on top of the json, json_schema, and
application libraries.
This initial implementation focuses on deriving OpenAPI documents from
objects implementing the open_api_provider_protocol protocol using a
small, portable descriptor vocabulary. This provides the following
benefits:
open_api is a companion library for the HTTP stack rather than a
transport or dispatch layer:
http_core library when you need request or
response contract validation against normalized HTTP terms or wire
sources.http_router library when router objects expose
open_api_provider_protocol metadata derived from route/4,
route_metadata/2, and route_produces/2.rest library when you want the same validation and
document derivation over higher-level endpoint descriptors built on
top of http_router.Open the `../../apis/library_index.html#open_api <../../apis/library_index.html#open_api>`__ link in a web browser.
To load this library, load the loader.lgt file:
::
| ?- logtalk_load(open_api(loader)).
To test this library, load the tester.lgt file:
::
| ?- logtalk_load(open_api(tester)).
open_api_provider_protocol protocoloperationId using operation/3http_request_protocol and
http_response_protocol protocols, against provider operation
descriptorshttp_core
library before validating them against provider operation descriptorsoperationId
atom for more than one operationsecurity defaults from provider
security/1components.securitySchemes
and reject top-level or operation security/1 references to
undeclared scheme names or undeclared OAuth flow scopes when locally
availabletype, and reject malformed declared OAuth
flow objects that omit their required URLs or scopesapiKey.in values and malformed
URL-valued security fields such as OAuth token or authorization
endpoints'2XX'Required = truecomponents.schemas and
components.securitySchemes plus the root security fieldhttp_core library for request and
response parsing and for protocol-based access to normalized HTTP
messages, but it limits itself to contract validation rather than
transport concernsAPI metadata ~~~~~~~~~~~~
The api_info/1 predicate returns an
info(Title, Version, Summary, Properties) descriptor for the
top-level OpenAPI info object. Currently recognized metadata
properties are limited to description(Description).
Provider objects that also implement application_protocol can
contribute missing OpenAPI metadata:
info.descriptioninfo.license.nameexternalDocs.url
Server descriptors
~~~~~~~~~~~~~~~~~~
The servers/1 predicate returns a list of
server(URL, Description) descriptors used to build the top-level
OpenAPI servers array. URL must be a valid OpenAPI Server Object
URL string, allowing absolute URLs, relative references, and templated
variables such as https://{username}.example.com:{port}/{basePath}.
Top-level security defaults ~~~~~~~~~~~~~~~~~~~~~~~~~~~
The security/1 predicate returns a list of top-level OpenAPI
security requirement alternatives. The returned list uses the same
Requirements representation accepted by operation
security(Requirements) properties: each requirement alternative is a
list of Scheme-Scopes pairs and [] denotes an empty security
requirement object. Scheme names must match declarations exposed by
security_scheme/2.
Operation descriptors ~~~~~~~~~~~~~~~~~~~~~
The operations/1 predicate returns a list of
operation(Id, Method, Path, Summary, Parameters, RequestBody, Responses, Properties)
descriptors. Id is used as the OpenAPI operationId and must be
unique across the returned descriptor list.
Nested descriptors are
parameter(Name, In, Description, Required, Schema),
request_body(Description, Required, MediaTypes),
response(Status, Description, MediaTypes), and
media(MediaType, Schema). Status may be an integer HTTP status
code, default, or a wildcard range atom such as '2XX'. Path
parameters must match a template expression in Path and must use
Required = true.
The current implementation keeps the operation property vocabulary narrow and supports only:
description(Description)tags(Tags)deprecated(Boolean)security(Requirements) where Requirements is a list of
requirement alternatives represented as lists of Scheme-Scopes
pairs and [] denotes an empty security requirement object
Scheme names referenced from security(Requirements) must match names
exposed by security_scheme/2, and operation-level security overrides
any top-level security/1 declaration.
Reusable schemas ~~~~~~~~~~~~~~~~
The schema/2 predicate maps reusable schema names to JSON Schema
curly terms compatible with the json_schema library. References to
reusable schemas are expressed using schema_ref(Name) terms.
Reusable security schemes ~~~~~~~~~~~~~~~~~~~~~~~~~
The security_scheme/2 predicate maps reusable security scheme names
to portable descriptor terms. This library accepts those terms and
normalizes them to OpenAPI Security Scheme Objects when deriving the
final document. The scheme names must match names referenced from
operation security(Requirements) properties. The descriptor
vocabulary keeps provider objects at the Logtalk domain level instead of
exposing OpenAPI JSON surface spelling directly:
openIdConnectUrl or clientCredentialsSupported descriptor shapes are:
api_key(In, Name)api_key(In, Name, Options)http(Scheme)http(Scheme, Options)mutual_tlsmutual_tls(Options)oauth2(Flows)oauth2(Flows, Options)openid_connect(URL)openid_connect(URL, Options)
Supported scheme options are:description(Description) for all scheme kindsbearer_format(Format) for http/2flows(Flows) for openid_connect/2 when locally declared scopes
are needed without relying on OpenID Connect discovery; these local
flow declarations are used only for provider-side security-reference
validation and are not emitted into the final OpenAPI document
Supported OAuth flow descriptors are:
implicit(AuthorizationURL, Scopes)implicit(AuthorizationURL, Scopes, [refresh_url(URL)])password(TokenURL, Scopes)password(TokenURL, Scopes, [refresh_url(URL)])client_credentials(TokenURL, Scopes)client_credentials(TokenURL, Scopes, [refresh_url(URL)])authorization_code(AuthorizationURL, TokenURL, Scopes)authorization_code(AuthorizationURL, TokenURL, Scopes, [refresh_url(URL)])
Scope descriptors are expressed as a list of
scope(Name, Description) terms.
Use descriptor terms such as:
::
security_scheme(
user_oauth,
oauth2([
client_credentials(
'https://auth.example.com/oauth/token',
[scope(read_users, 'Read user data')]
)
])
).
security_scheme(api_key, api_key(header, 'X-API-Key')).
security_scheme(user_bearer, http(bearer, [bearer_format('JWT')])).
security_scheme(user_oidc, openid_connect('https://example.com/.well-known/openid-configuration')).
An OpenID Connect scheme can also declare local scopes for the existing security reference validation path:
::
security_scheme(
user_oidc,
openid_connect(
'https://example.com/.well-known/openid-configuration',
[flows([
authorization_code(
'https://example.com/oauth/authorize',
'https://example.com/oauth/token',
[
scope(read_users, 'Read user data')
]
)
])]
)
).
Those local flow declarations are used only for provider-side security
reference validation. They are not emitted into the derived OpenAPI
document, as OpenID Connect Security Scheme Objects do not define a
flows field.
Provider-side validation checks, among other things:
apiKey locationstokenUrl,
authorizationUrl, refreshUrl, and openIdConnectUrlLoad the library and derive a document from a provider object:
::
| ?- logtalk_load(open_api(loader)),
open_api::document(sample_open_api_provider, Document).
Parse and generate OpenAPI documents in JSON term form:
::
| ?- open_api::parse(atom('{"openapi":"3.1.0","info":{"title":"Demo","version":"1.0.0"},"paths":{}}'), Document).
| ?- open_api::generate(atom(JSON), {openapi-'3.1.0', info-{title-'Demo', version-'1.0.0'}, paths-{}}).
Validate a document and inspect any structural errors:
::
| ?- open_api::validate_document(Document, Errors).
Resolve an operation descriptor and validate normalized requests, responses, or HTTP wire sources against it:
::
| ?- open_api::operation(sample_open_api_provider, update_user, Operation).
| ?- open_api::validate_request(
sample_open_api_provider,
update_user,
request(
put,
origin('/users/11111111-1111-1111-1111-111111111111'),
http(1, 1),
[],
content('application/json', json({name-'Alice Example', active-true})),
[query_pairs([verbose-true])]
),
Errors
).
validate_response(
sample_open_api_provider,
get_user,
response(
http(1, 1),
status(404, 'Not Found'),
[],
content('application/json', json({code-not_found, message-'User not found'})),
[]
)
).
| ?- open_api::validate_http_request(
sample_open_api_provider,
update_user,
atom('PUT /users/11111111-1111-1111-1111-111111111111?verbose=true HTTP/1.1\r\ncontent-type: application/json\r\n\r\n{"name":"Alice Example","active":true}')
).
Construct standard JSON request and response descriptors when building provider operations programmatically:
::
| ?- open_api::json_request_body_descriptor( 'Message payload', true, {type-object, properties-{title-{type-string}}, required-[title], additionalProperties- @false}, RequestBody ).
| ?- open_api::problem_response_descriptor(default, 'Problem response', Response).