Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DotAAS Part 2: HTTP API #238

Merged
merged 195 commits into from
Aug 16, 2024
Merged

Conversation

jkhsjdhjs
Copy link
Contributor

@jkhsjdhjs jkhsjdhjs commented Feb 20, 2024

This PR adds the http adapter, an implementation of the HTTP AAS and Submodel Repository Interfaces of "Details of the Asset Administration Shell Part 2":

Partially implements #207

General TODOs:

AAS Routes @hadijannat

The following routes assume you know the submodel identifier, why wouldn't you use the submodel repository instead? Maybe simply return a redirect to the submodel repository for these routes :D

Submodel Routes @Frosty2500

The following routes invoke operations, which is currently not implemented in the basyx-python-sdk.

  • POST /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/invoke
  • POST /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/invoke/$value
  • POST /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/invoke-async
  • POST /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/invoke-async/$value
  • GET /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/operation-status/{handleId}
  • GET /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/operation-results/{handleId}
  • GET /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/operation-results/{handleId}/$value

list werkzeug as a dependency in the readme
adapter.http: add custom identifier converter for werkzeug
adapter.http: restructure routing map, add first submodel route
adapter.http: refine imports
adapter._generic: add identifier URI encode/decode functions
adapter.http: make api routes return ResponseData instead of the Response directly
adapter.http: add Result + Message types + factory function
adapter.http: add request body parsing
adapter.http: implement all remaining aas routes
- use stripped object serialization/deserialization
- change response format (new spec always returns a result object)
adapter.http: remove old routes, add a few new aas and submodel routes
using the werkzeug.routing.MapAdapter url builder
Requests to URIs with a trailing slash will now be redirected
to the respective URI without trailing slash.
e.g. GET /aas/$identifier/ -> GET /aas/$identifier

A redirect will only be set if the respective URI without trailing slash
exists and the current request method is valid for the new URI.

Historically, the trailing slash was only present when the requested
resource was a directory. In our case the resources don't work like
directories, in the sense, that each resource doesn't even list possible
subsequent resources. So because our resources don't behave like
directories, they shouldn't have a trailing slash.
to stay consistent with the rest of this library
add IdShortPathConverter and helper functions
change type check from `not A is B` to `A is not B` for better readability
… attributes

like statement, annotation and value
Frosty2500 and others added 24 commits June 7, 2024 13:22
adapter.http: remove excess blank line
merge `main` in `feature/http_api`
`AbstractSupplementaryFileContainer` and
`DictSupplementaryFileContainer` are extended by a `delete_file()`
method, that allows deleting files from them. Since different files may
have the same content, references to the files contents in
`DictSupplementaryFileContainer._store` are tracked via
`_store_refcount`. A files contents are only deleted from `_store`, if
all filenames referring to these these contents are deleted, i.e. if the
refcount reaches 0.
DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC)
This change makes use of the `SupplementaryFileContainer` interface of
the AASX adapter. It allows the API to operate seamlessly on AASX files,
including the contained supplementary files, without having to access
the filesystem.

Furthermore, the support for the modification of `Blob` values is
removed (the spec prohibits it).
…n_warning

adapter.http: fix a `DeprecationWarning`
adapter.http: allow retrieving and modifying `File` attachments via API
adapter.http: allow changing the API base path
This check was intended to return 501 instead of 404 for routes that
haven't been implemented. However, we explicitly implement these routes
to return 501 now anyway, returning 501 for all other paths would be
semantically incorrect anyway and the check never worked.
Werkzeug 3.0.3 contains a fix for [1], so by requiring at least 3.0.3,
we can remove unnecessary 'type: ignore' comments from the http adapter.

[1]: pallets/werkzeug#2836
Remove 'type: ignore' comments now that we require werkzeug >=3.0.3 [1].
Furthermore, fix the type hint of `WSGIApp._get_slice()` and make two
other 'type: ignore' comments more explicit.

[1]: pallets/werkzeug#2836
adapter.http: remove and improve `type: ignore` comments
…t_implemented_check

adapter.http: remove nonfunctional 'Not Implemented' check
This removes trailing slashes (and redirects to paths with trailing
slashes) from the API and makes it compatible with the PCF2 showcase and
other webapps.

Previously, all routes were implemented with a trailing slash, e.g.
`/submodels/` instead of `/submodels`. While the API spec only specifies
the routes without a trailing slash, this has the advantage of being
compatible with requests to the path with a trailing slash and without
trailing slash, as werkzeug redirects requests to the slash-terminated
path, if available.

However, this poses a problem with browsers that make use of [CORS
preflight requests][1] (e.g. Chromium-based browsers). Here, before
doing an actual API request, the browser sends an `OPTIONS` request to
the path it wants to request. This is done to check potential CORS
headers (e.g. `Access-Control-Allow-Origin`) for the path, without
retrieving the actual data. Our implementation doesn't support `OPTIONS`
requests, which is fine.
After the browser has received the response to the preflight request
(which may or may not have been successful), it attempts to retrieve the
actual data by sending the request again with the correct request method
(e.g. `GET`). With our server this request now results in a redirect, as
we redirect to the path with a trailing slash appended. This is a
problem, as the browser didn't send a CORS preflight request to the path
it is now redirected to. It also doesn't attempt to send another CORS
preflight request, as it already sent one, with the difference being the
now slash-terminated path. Thus, following the redirect is prevented by
CORS policy and the data fails to load.

By making the routes available via non-slash-terminated paths we avoid
the need for redirects, which makes the server compatible with webapps
viewed in browsers that use preflight requests. Requests to
slash-terminated paths will no longer work (they won't redirect to the
path without trailing slash). This shouldn't be a problem though, as the
API is only specified without trailing slashes anyway.
adapter.http: remove unnecessary generator expression
adapter.http: remove trailing slashes from routes
This adds a module docstring to `adapter.http`,
that details which features from the Specification
of the Asset Administration Shell Part 2 (API)
were not implemented.
@s-heppner s-heppner marked this pull request as ready for review August 16, 2024 12:55
@s-heppner s-heppner merged commit fef92d0 into eclipse-basyx:main Aug 16, 2024
8 checks passed
@s-heppner s-heppner deleted the feature/http_api branch September 3, 2024 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants