Using the Guillotina API¶
Before we start using the Guillotina API, let's get us some test data to play with.
Using the testdata command, we'll populate our database with some data from
wikipedia.
g testdata --per-node=5 --depth=2 --container=container
Interacting with the API¶
You can use whatever you'd like but this training will mention use of Postman.
Open up Postman and do a GET on http://localhost:8080/db/container
with the username root and password root for basic auth.
We can not necessarily go over every single API but will touch on a few and give a general understanding of how to explore and use the API.
Creating content¶
To create content, do a POST request on a container or folder object.
- POST /(db)/(container)¶
Add new resouce inside this container resource
Permission: guillotina.AddContent
Context: guillotina.interfaces.content.IResource
http
POST /db/container HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 { "@type": "Item", "id": "foobar5" }
curl
curl -i -X POST http://nohost/db/container -H "Accept: application/json" --data-raw '{ "@type": "Item", "id": "foobar5" }' --user root:root
httpie
echo '{ "@type": "Item", "id": "foobar5" }' | http POST http://nohost/db/container Accept:application/json -a root:root
response
HTTP/1.1 201 OK Content-Type: application/json Location: http://localhost/db/container/foobar5 { "@id": "http://localhost/db/container/foobar5", "@name": "foobar5", "@type": "Item", "@uid": "f16|9deecd20e52744f5acd90246ada64051" }
- Status Codes:
200 OK -- Resource data
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
Adding behaviors¶
To add a dynamic behavior, we use the @behavior endpoint.
- PATCH /(db)/(container)/(content)/@behaviors¶
Add behavior to resource
Permission: guillotina.ModifyContent
Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@behaviors HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 { "behavior": "guillotina.behaviors.attachment.IAttachment" }
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@behaviors -H "Accept: application/json" --data-raw '{ "behavior": "guillotina.behaviors.attachment.IAttachment" }' --user root:root
httpie
echo '{ "behavior": "guillotina.behaviors.attachment.IAttachment" }' | http PATCH http://nohost/db/container/foobar5/@behaviors Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json {}
- Status Codes:
200 OK -- Successfully added behavior
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
412 Precondition Failed -- Behavior already assigned here
Uploading files¶
Simple file uploads can be done with the @upload endpoint.
- PATCH /(db)/(container)/(content)/@upload/file¶
Permission: guillotina.ModifyContent
Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@upload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 <text data>
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@upload/file -H "Accept: application/json" --data-raw '<text data>' --user root:root
httpie
echo '<text data>' | http PATCH http://nohost/db/container/foobar5/@upload/file Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json {}
- Status Codes:
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
Then, to download the file, use the @download endpoint.
- GET /(db)/(container)/(content)/@download/file¶
Permission: guillotina.ViewContent
Context: guillotina.interfaces.content.IResource
http
GET /db/container/foobar5/@download/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290
curl
curl -i -X GET http://nohost/db/container/foobar5/@download/file -H "Accept: application/json" --user root:root
httpie
http http://nohost/db/container/foobar5/@download/file Accept:application/json -a root:root
response
HTTP/1.1 200 OK Accept-Ranges: bytes Content-Disposition: attachment; filename="a8a678fde7db449b87a68fa5a33fe7e5" Content-Length: 11 Content-Type: application/octet-stream <text data>
- Status Codes:
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
Uploading files with TUS¶
Guillotina also supports the TUS protocol using the @tusupload endpoint. The
TUS protocol allows you to upload large files in chunks and allows you to have
resumable uploads.
First, initialize the TUS upload with a POST
- POST /(db)/(container)/(content)/@tusupload/file¶
Permission: guillotina.ModifyContent
Context: guillotina.interfaces.content.IResource
http
POST /db/container/foobar5/@tusupload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 TUS-RESUMABLE: 1 UPLOAD-LENGTH: 22
curl
curl -i -X POST http://nohost/db/container/foobar5/@tusupload/file -H "Accept: application/json" -H "Tus-Resumable: 1" -H "Upload-Length: 22" --user root:root
httpie
http POST http://nohost/db/container/foobar5/@tusupload/file Accept:application/json Tus-Resumable:1 Upload-Length:22 -a root:root
response
HTTP/1.1 201 OK Content-Type: application/json Location: http://localhost/db/container/foobar5/@tusupload/file Tus-Resumable: 1.0.0 {}
- Status Codes:
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
Next, upload the chunks(here we're doing chunks):
- PATCH /(db)/(container)/(content)/@tusupload/file¶
Permission: guillotina.ModifyContent
Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@tusupload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 TUS-RESUMABLE: 1 Upload-Offset: 0 <text data>
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@tusupload/file -H "Accept: application/json" -H "Tus-Resumable: 1" -H "Upload-Offset: 0" --data-raw '<text data>' --user root:root
httpie
echo '<text data>' | http PATCH http://nohost/db/container/foobar5/@tusupload/file Accept:application/json Tus-Resumable:1 Upload-Offset:0 -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json Tus-Resumable: 1.0.0 Upload-Offset: 11 {}
- Status Codes:
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
And final chunk:
- PATCH /(db)/(container)/(content)/@tusupload/file¶
Permission: guillotina.ModifyContent
Context: guillotina.interfaces.content.IResource
http
PATCH /db/container/foobar5/@tusupload/file HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 TUS-RESUMABLE: 1 Upload-Offset: 11 <text data>
curl
curl -i -X PATCH http://nohost/db/container/foobar5/@tusupload/file -H "Accept: application/json" -H "Tus-Resumable: 1" -H "Upload-Offset: 11" --data-raw '<text data>' --user root:root
httpie
echo '<text data>' | http PATCH http://nohost/db/container/foobar5/@tusupload/file Accept:application/json Tus-Resumable:1 Upload-Offset:11 -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json Tus-Resumable: 1.0.0 Tus-Upload-Finished: 1 Upload-Offset: 22 {}
- Status Codes:
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
Unknown upload size¶
Guillotina's TUS implementation has support for the Upload-Defer-Length header.
This means you can upload files with an unknown final upload size.
In order to implement this correctly, you will need to provide the
Upload-Defer-Length: 1 header and value on the initial POST to start the TUS
upload. You are then not required to provide the UPLOAD-LENGTH header.
Then, before or on your last chunk, provide a UPLOAD-LENGTH value to let
TUS know the upload can not finish.
Simultaneous TUS uploads¶
Guillotina's TUS implementation also attempts to prevent simultaneous uploaders.
If two users attempt to start an upload on the same object + field at the same time, a 412 error will be thrown. Guillotina tracks upload activity to detect this. If there is no activity detected for 15 seconds with an unfinished TUS upload, no error is thrown.
To override this, send the TUS-OVERRIDE-UPLOAD: 1 header.
Modifying permissions¶
The @sharing endpoint is available to inspect and modify permissions on an object.
- GET /(db)/(container)/(content)/@sharing¶
Get sharing settings for this resource
Permission: guillotina.SeePermissions
Context: guillotina.interfaces.content.IResource
http
GET /db/container/foobar5/@sharing HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290
curl
curl -i -X GET http://nohost/db/container/foobar5/@sharing -H "Accept: application/json" --user root:root
httpie
http http://nohost/db/container/foobar5/@sharing Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json { "local": { "roleperm": {}, "prinperm": {}, "prinrole": { "root": { "guillotina.Owner": "Allow" } } }, "inherit": [ { "@id": "http://localhost/db/container", "roleperm": {}, "prinperm": {}, "prinrole": { "root": { "guillotina.ContainerAdmin": "Allow", "guillotina.Owner": "Allow" } } } ] }
- Status Codes:
200 OK -- All the sharing defined on this resource
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
To modify, we use the same endpoint but with a POST.
- POST /(db)/(container)/(content)/@sharing¶
Change permissions for a resource
Permission: guillotina.ChangePermissions
Context: guillotina.interfaces.content.IResource
http
POST /db/container/foobar5/@sharing HTTP/1.1 Accept: application/json Authorization: Basic cm9vdDpyb290 { "prinperm": [ { "principal": "foobar", "permission": "guillotina.ModifyContent", "setting": "Allow" } ] }
curl
curl -i -X POST http://nohost/db/container/foobar5/@sharing -H "Accept: application/json" --data-raw '{ "prinperm": [ { "principal": "foobar", "permission": "guillotina.ModifyContent", "setting": "Allow" } ] }' --user root:root
httpie
echo '{ "prinperm": [ { "principal": "foobar", "permission": "guillotina.ModifyContent", "setting": "Allow" } ] }' | http POST http://nohost/db/container/foobar5/@sharing Accept:application/json -a root:root
response
HTTP/1.1 200 OK Content-Type: application/json {}
- Status Codes:
200 OK -- Successfully changed permission
401 Unauthorized -- You are not authorized to perform the operation
404 Not Found -- The resource does not exist
There are three types of permission settings you can modify:
prinperm: principal + permission
prinrole: principal + role
roleperm: role + permission
Each change can use the following settings:
Allow : you set it on the resource and the children will inherit
Deny : you set in on the resource and the children will inherit
AllowSingle : you set in on the resource and the children will not inherit
Unset : you remove the setting
Exploring the API with OpenAPI¶
In the previous step, we installed guillotina.contrib.swagger. With OpenAPI, we can
inspect any context and explore the API.
Visit http://localhost:8080/@docs¶
Click the Authorize button¶
The top URL setting is what the current context is that you're exploring the API
on. If you create content at /db/container/foobar and want to explore that
content's API, you should change the URL. Different content types will have
different services available.
References