# 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. ```shell 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. ```eval_rst .. http:gapi:: :hidden: :path: /db/container :basic_auth: root:root :method: POST :body: { "@type": "Container", "id": "container" } .. http:gapi:: :path: /db/container :path_spec: /(db)/(container) :basic_auth: root:root :method: POST :body: { "@type": "Item", "id": "foobar5" } ``` ## Adding behaviors To add a dynamic behavior, we use the `@behavior` endpoint. ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@behaviors :path_spec: /(db)/(container)/(content)/@behaviors :method: PATCH :basic_auth: root:root :body: { "behavior": "guillotina.behaviors.attachment.IAttachment" } ``` ## Uploading files Simple file uploads can be done with the `@upload` endpoint. ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@upload/file :path_spec: /(db)/(container)/(content)/@upload/file :method: PATCH :basic_auth: root:root :body: ``` Then, to download the file, use the `@download` endpoint. ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@download/file :path_spec: /(db)/(container)/(content)/@download/file :basic_auth: root:root ``` ## Uploading files with TUS Guillotina also supports the [TUS](https://tus.io/ "Link to TUS website") 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 ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@tusupload/file :path_spec: /(db)/(container)/(content)/@tusupload/file :method: POST :headers: TUS-RESUMABLE:1,UPLOAD-LENGTH:22 :basic_auth: root:root ``` Next, upload the chunks(here we're doing chunks): ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@tusupload/file :path_spec: /(db)/(container)/(content)/@tusupload/file :method: PATCH :headers: TUS-RESUMABLE:1,Upload-Offset:0 :basic_auth: root:root :body: ``` And final chunk: ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@tusupload/file :path_spec: /(db)/(container)/(content)/@tusupload/file :method: PATCH :headers: TUS-RESUMABLE:1,Upload-Offset:11 :basic_auth: root:root :body: ``` ### 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. ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@sharing :path_spec: /(db)/(container)/(content)/@sharing :basic_auth: root:root ``` To modify, we use the same endpoint but with a `POST`. ```eval_rst .. http:gapi:: :path: /db/container/foobar5/@sharing :path_spec: /(db)/(container)/(content)/@sharing :method: POST :basic_auth: root:root :body: { "prinperm": [ { "principal": "foobar", "permission": "guillotina.ModifyContent", "setting": "Allow" } ] } ``` 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. ```eval_rst .. figure:: ../_static/img/swagger.png :alt: Swagger Visit ``http://localhost:8080/@docs`` ``` ```eval_rst .. figure:: ../_static/img/auth-swagger.png :alt: Authentication 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** - [REST API](../../rest/index) - [Behaviors](../../developer/behavior) - [Security](../../developer/security)