Closed paul121 closed 3 years ago
One clarification: Authorization
headers are not needed for each individual sub-request. They are run in the same session as the initial request that is sent to /subrequests
Added this in v1.0.0-alpha.2: https://github.com/farmOS/farmOS.py/releases/tag/v1.0.0-alpha.2
2: Extra: consider creating client.resource.endpoint(type, bundle, id=None, params=None) and client.log.endpoint(bundle, id=None, params=None) methods for building correct API endpoints that include IDs and query parameters.
3: Extra: create helper methods for common tasks eg: client.subrequests.createLog(references = []) (tbd...)
I think these would be nice features but lets wait to add these until later on as use cases further develop.
Why
The Drupal Subrequests module allows multiple, dependent or independent requests to be defined in a "blueprint". The blueprint is sent to the server in a single POST (or query string encoded GET request) to
/subrequests
, where the server performs each request and returns a singlemultipart/related
response containing the result of each individual sub-request.This enables more complex API operations to be completed in a single step. For example, creating a new asset and immediately creating a movement log to locate the asset. Subrequests would also help API users with creating Logs that have multiple quantities. This works by allowing response values in later requests via JSON Paths.
Implementation Details
Adding support for Subrequests to the client is nearly as easy as creating a new
client.subrequests
namesapce with asend(blueprint)
method. Users can be responsible for building a valid Subrequests blueprint.Each request in the blueprint only requires an
action
andurl
property.But in general, most subrequests to a farmOS server will require an(an additional permission is required for users to use theAuthorization
header to be set as well/subrequests
endpoint).For DX, the farmOS client libraries could auto-fill theSimilarly, the base URL shouldn't need to be provided. The farmOS client could auto-fill this as value as well.Authorization
header of each individual request, unless one is already provided.The
body
property that is need for sub-requests sending data, such ascreate
orupdate
actions, needs to be a serialized JSON string. This is something the client could handle as well.By default Subrequests returns an HTML
multipart/related
response which is fairly complicated to parse (see https://www.drupal.org/project/subrequests/issues/3194286). BUT subrequests can also return a JSON response with the result of each sub-request keyed byrequestId
. To do this, the JSON format must be requested by adding the?_format=json
query parameter. I don't see a reason that users would want the HTML response, but we could support this by adding aformat
parameter that defaults tojson
, eg;client.subrequests.send(blueprint, format='html')
.A nice addition would be for the farmOS clients to provide some "helper" methods for building a Subrequests blueprint. I think the main pain points for developers will be:
client.log.get()
anyways)Proposed resolution
client.subrequests
namespace with aclient.subrequests.send(blueprint, format="json")
method to submit blueprints to the server. Unlessformat="html"
is specified, append the?_format=json
query parameter.Auto-fill theThis is not necessary! Each sub-request is run in same session as the "master request".Authorization
header on each sub-request within the blueprint, unless the header is already set (allow NULL so that un-authenticated requests can be made).Accept
andContent-Type
headers to beapplication/vnd.api+json
, unless the header is already set.api_endpoint
orendpoint
property for individual subrequests. If nourl
is provided, theendpoint
will be appended to the base URL already configured on the client.body
is a string or an object. If an object is provided, serialize it as a JSON string.client.resource.endpoint(type, bundle, id=None, params=None)
andclient.log.endpoint(bundle, id=None, params=None)
methods for building correct API endpoints that include IDs and query parameters.client.subrequests.createLog(references = [])
(tbd...)