| Did you know ... | Search Documentation: |
| Pack logtalk -- logtalk-3.101.0/library/rest/NOTES.md |
This file is part of Logtalk https://logtalk.org/ SPDX-FileCopyrightText: 1998-2026 Paulo Moura <pmoura@logtalk.org> SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the License); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
rest
The rest library provides a small REST authoring layer on top of the
existing http_router library. It is implemented as a category so that
REST application objects can continue to implement the
http_handler_protocol protocol directly while reusing the existing router
dispatch, request annotation, middleware, and OpenAPI derivation logic.
This library reuses the http_core and http_router. It derives router hooks
from higher-level endpoint descriptors, provides small request and response
helpers, and normalizes simple action result terms into HTTP responses.
rest is the highest-level authoring layer in the current HTTP stack:
http_core library for normalized HTTP messages and with the
http_router library for declarative routing.rest library when you want to describe endpoints with endpoint/5,
keep the inherited handle/2 entry point, and return small result terms
instead of building every response manually.http_router library when you need direct control over
route/4, custom handler predicates, or router hooks without the
higher-level endpoint layer.open_api library when you want
derived OpenAPI documents or opt-in request and response contract
validation.Open the [../../apis/library_index.html#rest](../../apis/library_index.html#rest) link in a web browser.
To load the library, load the loader.lgt file:
| ?- logtalk_load(rest(loader)).
To test this library, load the tester.lgt file:
| ?- logtalk_load(rest(tester)).
The current version provides one imported routing predicate through the
category inheritance from http_router plus request and response helper
predicates:
json_response/4-5endpoint(Id, Method, Path, Action, Options)
Endpoint identifiers must be unique within the importing object. When the
object also exposes OpenAPI operations through http_router, those same
identifiers are reused as operation identifiers.
The Action argument is the name of a declared local predicate with arity 2, typically a protected predicate. The action predicate receives the annotated request and returns or throws one of the currently supported result terms:
ok(JSON)created(Location, JSON)no_contentjson(Status, JSON)json(Status, Headers, JSON)problem(Status, Type, Title, Detail)response(Response) or a normalized response/5 term directly
The category derives the http_router hooks from those endpoint
descriptors:
Endpoint options are passed through as route metadata except for the special
produces(MediaTypes) option, which is translated into route_produces/2.
This keeps endpoint metadata available to action predicates and response
middleware and also allows router-level OpenAPI derivation to keep working.
That same metadata pass-through also allows REST applications to reuse router
companion categories. For example, an object can import
http_router_digest_auth(_, _, _), declare digest_auth(Options) in endpoint
options, delegate authorize_routed_request/2 to
authorize_digest_auth_request/2, and register
add_digest_authentication_info/3 as response middleware.
The current helper predicates read the normalized HTTP request terms provided
by http_core:
request(Method, Target, Version, Headers, Body, Properties)
They rely on router annotations such as route/1 and path_params/1 plus
the normalized derived properties produced by the http_core library such as
query_pairs/1. The path_parameter/3 and query_parameter/3 helpers are
deterministic lookups. The decoded body helpers return `400 Bad Request`
problem responses when the current action expects a JSON, form, text, or
binary body and the normalized request body is missing or has a different
decoded shape. The json_object_body/2 and json_array_body/2 helpers build
on json_body/2 and additionally require the decoded JSON payload to be an
object or array term respectively.
Action result normalization currently builds normalized HTTP response terms from returned or thrown supported result terms using these rules:
application/jsonapplication/problem+json
Plain action failure and unsupported exceptions still default to generic
`500 Internal Server Error` problem responses, but importing objects can
override those defaults using rest_action_failure_response/3 and
rest_action_error_response/4.
When open_api_validate_request/1 succeeds for a matched endpoint, the category validates the normalized request against the derived OpenAPI operation descriptor before calling the endpoint action. When open_api_validate_response/1 succeeds for a matched endpoint, the category validates the normalized response after action result normalization.
By default, request validation failures preserve three classes of client
error: unsupported request media types return `415 Unsupported Media Type`,
schema-invalid request bodies return `422 Unprocessable Content`, and other
request validation failures return `400 Bad Request`. Response validation
failures still return a `500 Internal Server Error`
application/problem+json response. Importing objects can override those
defaults using the corresponding validation error response hooks. Validation
is skipped for the synthetic router requests used internally for OpenAPI
request and response inference.
When an importing object also implements the open_api_provider_protocol
protocol, the inherited http_router OpenAPI derivation continues to work.
Endpoint options such as summary/1, description/1, tags/1,
deprecated/1, security/1, parameters/1, request_body/1, and
responses/1 are exposed through route_metadata/2, while
produces(MediaTypes) drives route_produces/2 and therefore response
media type inference.