I'm working on some API service which consume REST queries (CRUD operations) and send appropriate CLI commands to some network equipment.
There is 2 possible ways to design Openapi specification for this service:
Detailed huge API spec. Describe exactly all the endpoints, all the schemas, all the params that exist in the network equipment CLI. I think specification will be about 100K of lines in this way. Specification can be autogenerated based on device CLI parsing (using ? and TAB keys).
Generalized tiny API spec. Hide all device configuration details in a few common parameters. Something like
paths:
/api/{CLI_endpoint}: # we say "CLI_endpoint" instead of describing all the endpoints
...
post:
requestBody:
content:
application/json:
schema:
type: object # we say "object" instead of describing all the params
In this way we simply say that all the endpoint names and param names correspond to network equipment CLI documentation.
Which of the ways will be better?
Related
One of the benefits being promoted for API-first design or OpenAPI is that of their use as a single source of truth. To my mind, these schemas only serve as a contract - the actual source of truth for your API lies in your microservices implementation (typically a http endpoint).
How can OpenAPI claim to be a single source of truth when the contract cannot be enforced until the implementation on the API side is complete? I realise there is tooling available to assist with this, such as validation middleware that can be used to match your request and response against your schema, however this is typically only validated at the point that a network request is made, not at compile time.
Of course you could write api tests to validate, but this is very much dependent on good test coverage and not something you get out of the box.
TLDR - OpenAPI markets itself as being a single source of truth for APIs, but this simply isn't true until your API implementation matches the spec. What tools/techniques (if any) can be used to mitigate this?
Did a bit of additional research into available tooling and found a solution that helps mitigate this issue:
open-api-backend (and presumably other such libraries) have capabilities to map your api routes/handlers to a specific openAPI operation or operationID. You can then enforce schema validation such that only routes defined in the spec can be implemented, else a fail-fast error is thrown)
What would be a rest API convention to get a resource based on a different identificator?
For example
GET
/resource/{id}
GET
/resource/{guid}
Since this could be considered as a dupliate resource and setting routes for this could be a problem, what is an alternative then would follow rest API guidelines?
Maybe
/resources/?guid={guid}
or
/resources/guid/{guid}
or something else?
Short answer
You could use both /resource/{id} and /resource/{guid}. Many frameworks support regular expressions for matching path parameter values.
Long answer
REST is an architectural style and not a cookbook for designing URIs (see notes below). It doesn't enforce any URI design and it's totally up to you to pick the URIs that better identify your resources.
What you should keep in mind is: it's perfectly fine to have multiple mappings for the same entity. And each mapping is a resource, according to Fielding's dissertation:
A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time.
With that being said, if you are supporting DELETE, it's important to mention how it's supposed to work:
4.3.5. DELETE
The DELETE method requests that the origin server remove the association between the target resource and its current functionality. In effect, this method is similar to the rm command in UNIX: it expresses a deletion operation on the URI mapping of the origin server rather than an expectation that the previously associated information be deleted. [...]
Note 1: The URI syntax is defined in the RFC 3986. As general rule, the path is organized in hierarchical form (with segments separated by /) and can contain non-hierarchical data in the query component (starting with ?).
Note 2: The REST architectural style is described in the chapter 5 of Roy T. Fielding's dissertation and it defines a set of constraints that must be followed by the applications that follow such architecture. However it says nothing about what the URIs must be like.
Note 3: The examples of a popular article written by Martin Fowler explaining a model defined by Leonard Richardson suggest a URI structure that looks friendly and easy to read.
I wouldn't normally duplicate an endpoint. The question would be:
why does one client have an id while another has a guid?
what design choice allowed that to happen?
I would leave it as a single resource endpoint:
GET
/resource/{id}
so clients who access resources via their id will use the above endpoint. I'd allow clients who access resources via their guid to exchange what they have (guid) for what they need (id):
GET
/id/{guid}
The above returns a resource id for the given resource guid. The client can then call the main resource endpoint with the id they have just received:
GET
/resource/{id}
but ultimately I'd look into why some clients use a guid rather than an id and change that so all clients access the API in the same way.
After some googling I decided to directly ask this:
Is it possible to run REST API endpoint "build tests" based on solely an OpenAPI 3.0 specification file?
I would like to add example request-response pairs to the OpenAPI spec file and have either an existing or self-written library run through all the such defined tests and report any failures.
As far as I understand the standard, it would be easily possible to include examples for requests and test the response in a schematic way (thinking http://json-schema.org/). But I don't yet see a way to incorporate more specific tests, such as testing a number in a specific response field to be an exact value. Also, it would be nice to have a way to sequentially test requests, but I don't expect to achieve that just from the spec file.
An optimal solution would be included in my repository and run the tests on localhost. Thank you all very much in advance.
Is it possible to run REST API endpoint "build tests" based on solely an OpenAPI 3.0 specification file?
Yes. The spec has at least two components that allow automatic tests generation:
Examples. You could specify examples for defined endpoints, which describe concrete data samples you send/receive.
Schemas. They describe data models, which you can use to generate requests to the API.
But I don't yet see a way to incorporate more specific tests, such as testing a number in a specific response field to be an exact value.
It can be done using the "enum" keyword with a single value in a list in the schema for the desired field. Open API doesn't support the "const" keyword in contrast with JSON Schema.
Also, it would be nice to have a way to sequentially test requests, but I don't expect to achieve that just from the spec file.
To achieve that you could use Open API links, which allows you to specify how to construct a request to endpoint B from request or response to endpoint A. For example:
paths:
/users:
post:
summary: Creates a user and returns the user ID
operationId: createUser
responses:
'201':
description: Created
content:
application/json:
schema:
type: object
properties:
id:
type: integer
format: int64
description: ID of the created user.
links:
GetUserByUserId:
operationId: getUser
parameters:
userId: '$response.body#/id'
/users/{userId}:
get:
summary: Gets a user by ID
operationId: getUser
parameters:
- in: path
name: userId
required: true
schema:
type: integer
format: int64
In this example, the id value returned in the 201 response to the POST /users can be used as the userId parameter in GET /users/{userId}. In this way, you can define sequences of requests to different endpoints.
I want to note two tools that can generate and execute test cases based only on the input Open API spec:
Schemathesis uses both sources and doesn't require configuration by default. It utilizes property-based testing and verifies properties defined in the tested schema - response codes, schemas, and headers. It supports Open API 2 & 3 and stateful testing via Open API links and automatically can generate sequences of API requests based on their definition in the spec file.
Dredd focuses more on examples and provides several automatic expectations. It supports only Open API 2, and the third version is experimental.
Both provide a CLI and could be extended with various hooks to fit the desired workflow.
Is there any way to request Magnolia REST API for list of products
which could be retrieved with equivalent of JCR SQL2
select * from [mgnl:product] where productName like '%Nikon%'
If it's only possible with custom rest end-point could you please point to tutorial.
Update as of Magnolia REST 2.1, using the v2 endpoint definition:
To answer the second question about node-types, here's what it looks like, as a YAML file in a light module, e.g. <module-name>/restEndpoints/delivery/my-products_v1.yaml:
class: info.magnolia.rest.delivery.jcr.v2.JcrDeliveryEndpointDefinition
workspace: products
rootPath: /
includeSystemProperties: false
bypassWorkspaceAcls: true
depth: 2
nodeTypes:
- mgnl:product
childNodeTypes:
- mgnl:contentNode
The Delivery endpoint config takes node-types to include.
nodeTypes specify the primary list of JCR node types to query—in your case mgnl:product;
childNodeTypes specify which child-nodes to include as JSON objects under the primary results, when depth is greater than 0.
With the above configuration, you may run the following requests to query products or get a single product, respectively:
GET <host>/.rest/delivery/my-products/v1?productName[like]=%25Nikon%25
GET <host>/.rest/delivery/my-products/v1/path/to/Nikon-1
This differs from Magnolia's former Nodes endpoint, which is not configurable, but only lets consumers exclude node-types.
Yes, you can use content delivery endpoint to do so. Syntax is like: GET /delivery/{endpoint-prefix}/v1?key1=value1&key2=value2
See https://git.magnolia-cms.com/projects/MODULES/repos/rest/browse/magnolia-rest-content-delivery for more details.
I have heard both "resource" and "endpoint" to refer to the same thing. It seems that resource is a newer term.
What is the difference between them? Does "resource" imply a RESTful design?
REST
Resource is a RESTful subset of Endpoint.
An endpoint by itself is the location where a service can be accessed:
https://www.google.com # Serves HTML
8.8.8.8 # Serves DNS
/services/service.asmx # Serves an ASP.NET Web Service
A resource refers to one or more nouns being served, represented in namespaced fashion, because it is easy for humans to comprehend:
/api/users/johnny # Look up johnny from a users collection.
/v2/books/1234 # Get book with ID 1234 in API v2 schema.
All of the above could be considered service endpoints, but only the bottom group would be considered resources, RESTfully speaking. The top group is not expressive regarding the content it provides.
A REST request is like a sentence composed of nouns (resources) and verbs (HTTP methods):
GET (method) the user named johnny (resource).
DELETE (method) the book with id 1234 (resource).
Non-REST
Endpoint typically refers to a service, but resource could mean a lot of things. Here are some examples of resource that are dependent on the context they're used in.
URL: Uniform "Resource" Locator
Could be RESTful, but often is not. In this case, endpoint is almost synonymous.
Resource Management
In GCP / AWS, resource is used in reference to cloud infrastructure.
In general computing, a resource is a reference to a component with limited availability.
Dictionary
The definitions provide many more uses of the word.
Something that can be used to help you:
The library was a valuable resource, and he frequently made use of it.
Resources are natural substances such as water and wood which are
valuable in supporting life:
[ pl ] The earth has limited resources, and if we don’t recycle them
we use them up.
Resources are also things of value such as money or possessions that you can use when you need them:
[ pl ] The government doesn’t have the resources to hire the number of
teachers needed.
The Moral
The term resource by definition has a lot of nuance. It all depends on the context its used in.
The terms resource and endpoint are often used synonymously. But in fact they do not mean the same thing.
The term endpoint is focused on the URL that is used to make a request.
The term resource is focused on the data set that is returned by a request.
Now, the same resource can often be accessed by multiple different endpoints.
Also the same endpoint can return different resources, depending on a query string.
Let us see some examples:
Different endpoints accessing the same resource
Have a look at the following examples of different endpoints:
/api/companies/5/employees/3
/api/v2/companies/5/employees/3
/api/employees/3
They obviously could all access the very same resource in a given API.
Also an existing API could be changed completely. This could lead to new endpoints that would access the same old resources using totally new and different URLs:
/api/employees/3
/new_api/staff/3
One endpoint accessing different resources
If your endpoint returns a collection, you could implement searching/filtering/sorting using query strings. As a result the following URLs all use the same endpoint (/api/companies), but they can return different resources (or resource collections, which by definition are resources in themselves):
/api/companies
/api/companies?sort=name_asc
/api/companies?location=germany
/api/companies?search=siemens
Possibly mine isn't a great answer but here goes.
Since working more with truly RESTful web services over HTTP, I've tried to steer people away from using the term endpoint since it has no clear definition, and instead use the language of REST which is resources and resource locations.
To my mind, endpoint is a TCP term. It's conflated with HTTP because part of the URL identifies a listening server.
So resource isn't a newer term, I don't think, I think endpoint was always misappropriated and we're realising that as we're getting our heads around REST as a style of API.
Edit
I blogged about this.
https://medium.com/#lukepuplett/stop-saying-endpoints-92c19e33e819
According https://apiblueprint.org/documentation/examples/13-named-endpoints.html is a resource a "general" place of storage of the given entity - e.g. /customers/30654/orders, whereas an endpoint is the concrete action (HTTP Method) over the given resource. So one resource can have multiple endpoints.
1. Resource description
“Resources” refers to the information returned by an API.
2. Endpoints and methods
The endpoints indicate how you access the resource, while the method indicates the allowed interactions (such as GET, POST, or DELETE) with the resource.
Additional info:
3. Parameters
Parameters are options you can pass with the endpoint (such as specifying the response format or the amount returned) to influence the response.
4. Request example
The request example includes a sample request using the endpoint, showing some parameters configured.
5. Response example and schema
The response example shows a sample response from the request example; the response schema defines all possible elements in the response.
Source-
Reference link
Consider a server which has the information of users, missions and their reward points.
Users and Reward Points are the resources
An end point can relate to more than one resource
Endpoints can be described using either a description or a full or
partial URL
Source: API Endpoints vs Resources