Newer
Older
.. ==================================================
.. ==================================================
.. ==================================================
.. Header hierarchy
.. ==
.. --
.. ^^
.. ""
.. ;;
.. ,,
..
.. --------------------------------------------used to the update the records specified ------
.. Best Practice T3 reST: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/CheatSheet.html
.. Reference: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/Index.html
.. Italic *italic*
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap <http://getbootstrap.com/>`_
.. Internal Link: :ref:`downloadButton` (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Add Images: .. image:: ../Images/a4.jpg
..
..
.. Admonitions
.. .. note:: .. important:: .. tip:: .. warning::
.. Color: (blue) (orange) (green) (red)
..
.. Definition:
.. some text becomes strong (only one line)
.. description has to indented
.. -*- coding: utf-8 -*- with BOM.
.. include:: Includes.txt
.. _`restApi`:
REST
====
Via `REST <https://en.wikipedia.org/wiki/Representational_state_transfer>`_ it's possible to access the QFQ based
application. Each REST API endpoint has to be defined as a QFQ Form.
This describes the server side (=QFQ is server). For client access check :ref:`rest_client`.
The QFQ REST api implements the four most used REST HTTP methods:
GET - Read
Shows a list of database records or a single record. The QFQ form holds the definition which and what to show.
List: ``curl -X GET "http://localhost/qfq/typo3conf/ext/qfq/Classes/Api/rest.php/person/``
Data (id=123): ``curl -X GET "http://localhost/qfq/typo3conf/ext/qfq/Classes/Api/rest.php/person/123``
POST - Create new record
The QFQ form defines wich columns will be written in which table. Most of QFQ Form functionality can be used. Example:
``curl -X POST "http://localhost/qfq/typo3conf/ext/qfq/Classes/Api/rest.php/person/" -d '{"name":"Miller","firstname":"Joe"}'``
PUT - Update a record
Similar to POST, but a given record will be updated.
``curl -X PUT "http://localhost/qfq/typo3conf/ext/qfq/Classes/Api/rest.php/person/123" -d '{"name":"Miller","firstname":"Joe"}'``
DELETE - Delete a record
Similar to a QFQ Delete form.
``curl -X DELETE "http://localhost/qfq/typo3conf/ext/qfq/Classes/Api/rest.php/person/123"``
All data will be imported / exported in JSON notation.
Any QFQ form becomes a REST form via: ``Form > Access > Permit REST: get / insert / update / delete``
If the REST endpoint specifies an unknown form or access is forbidden, an HTTP error is reported.
Endpoint
--------
.. tip::
The basic REST API endpoint: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php``
``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/<level1>/<id1>/<level2>/<id2>/.../?<var1>=<value1>&...``
Append level names and ids after ``.../rest.php/``, each separated by '/' .
1. List of all persons: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person``
2. Data of person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123``
3. Addresses of person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123/address``
4. Address details of address 45 from person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123/address/45``
QFQ 'Forms' are used as a 'container' (to define all details).
.. tip::
The QFQ ``form name`` represents the level name.
Only the last <level> of an URI will be processed. The former ones are just to fulfil a good looking REST API.
.. note::
Each level name (=form name) is available via STORE_CLIENT and name ``_formX``. E.g. in example
(1) ``{{_form1:C:alnumx}}=person`` and ``{{_form2:C:alnumx}}=address``.
Each level id is available via STORE_CLIENT and name `_idX`. E.g. in example
(2) ``{{_id1:C}}=123`` and ``{{_id2:C}}=45``.
Also the ``id`` after the last ``level`` in the URI path, 123 in example (2) and 45 in example (4), is copied to
variable ``r`` in STORE_TYPO3, access it via ``{{r:T}}``.
GET - Read
----------
A REST (GET) form has two modes:
data
Specific content to a given id. Defined via ``form.parameter.restSqlData``. This mode is selected if there is an
A list of records will be exported. Defined via ``form.parameter.restSqlList``. This mode is selected if there is no
id or id=0.
.. note::
There are *no* native-FormElements necessary or loaded. Action FormElements will be processed.
To simplify access to id parameter of the URI, a mapping is possible via 'form.parameter.restParam'.
E.g. ``restParam=pId,adrId`` with example d) makes ``{{pId:C}}=123`` and ``{{adrId:C}}=45``. The order of variable
names corresponds to the position in the URI. ``_id1`` is always mapped to the first parameter name, ``_id2`` to
the second one and so on.
GET Variables provided via URL are available via STORE_CLIENT as usual.
**Form**
+-------------------+------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==============================================================================+
| name | *<level>* Mandatory. Level name (Endpoint) in URI. |
+-------------------+------------------------------------------------------------------------------+
| table | Mandatory. Name of the primary table |
+-------------------+------------------------------------------------------------------------------+
| Permit REST | *get* Mandatory. The form can be loaded in REST mode. |
+-------------------+------------------------------------------------------------------------------+
**Form.parameter**
+-------------------+----------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==================================================================================+
| restSqlData | Mandatory. SQL query selects content shown in data mode. |
| | | ``restSqlData={{!SELECT id, name, gender FROM Person WHERE id='{{r:T0}}' }} `` |
+-------------------+----------------------------------------------------------------------------------+
| restSqlList | Mandatory. SQL query selects content shown in data mode. |
| | | ``restSqlData={{!SELECT id, name FROM Person }}`` |
+-------------------+----------------------------------------------------------------------------------+
| restParam | Optional. CSV list of variable names. E.g.: ``restParam=pId,adrId`` |
+-------------------+----------------------------------------------------------------------------------+
| restToken | Optional. User defined string or dynamic token (see :ref:``restAuthorization``). |
+-------------------+----------------------------------------------------------------------------------+
.. note::
There are no :ref:`special-column-names` available in ``restSqlData`` or ``restSqlList``. Also there are no
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
SIPs possible, cause REST typically does not offer sessions/cookies (which are necessary for SIPs).
.. important::
If there is an ``ìd`` given, a record in the named primary with the specified table has to exist.
If not, an error is thrown.
POST - Insert
-------------
**Form**
+-------------------+------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==============================================================================+
| name | *<level>* Mandatory. Level name (Endpoint) in URI. |
+-------------------+------------------------------------------------------------------------------+
| table | Mandatory. Name of the primary table |
+-------------------+------------------------------------------------------------------------------+
| Permit REST | *insert* Mandatory. The form can be loaded in REST mode. |
+-------------------+------------------------------------------------------------------------------+
| id | Missing or '0'. |
+-------------------+------------------------------------------------------------------------------+
**Form.parameter**
+-------------------+----------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==================================================================================+
| restParam | Optional. CSV list of variable names. E.g.: ``restParam=pId,adrId`` |
+-------------------+----------------------------------------------------------------------------------+
| restToken | Optional. User defined string or dynamic token (see :ref:`restAuthorization`). |
+-------------------+----------------------------------------------------------------------------------+
| restSqlPostPut | Optional. Instead of returning the last_insert_id, a customized result might be |
| | specified. E.g. ``{{! SELECT id, token FROM Token WHERE id={{id:R0}} }}`` |
+-------------------+----------------------------------------------------------------------------------+
FormElement:
* For each column to save one FormElement with ``FE.name=<column>`` is necessary.
* A regular QFQ form can be used as REST Post endpoint.
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
PUT - Update
------------
**Form**
+-------------------+------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==============================================================================+
| name | *<level>* Mandatory. Level name (Endpoint) in URI. |
+-------------------+------------------------------------------------------------------------------+
| table | Mandatory. Name of the primary table |
+-------------------+------------------------------------------------------------------------------+
| Permit REST | *update* Mandatory. The form can be loaded in REST mode. |
+-------------------+------------------------------------------------------------------------------+
| id | >0 |
+-------------------+------------------------------------------------------------------------------+
**Form.parameter**
+-------------------+----------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==================================================================================+
| restParam | Optional. CSV list of variable names. E.g.: ``restParam=pId,adrId`` |
+-------------------+----------------------------------------------------------------------------------+
| restToken | Optional. User defined string or dynamic token (see :ref:`restAuthorization`). |
+-------------------+----------------------------------------------------------------------------------+
FormElement:
* For each column to save one FormElement with ``FE.name=<column>`` is necessary.
* A regular QFQ form can be used as REST Post endpoint
DELETE - Delete
---------------
**Form**
+-------------------+------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==============================================================================+
| name | *<level>* Mandatory. Level name (Endpoint) in URI. |
+-------------------+------------------------------------------------------------------------------+
| table | Mandatory. Name of the primary table |
+-------------------+------------------------------------------------------------------------------+
| Permit REST | *delete* Mandatory. The form can be loaded in REST mode. |
+-------------------+------------------------------------------------------------------------------+
| id | >0 |
+-------------------+------------------------------------------------------------------------------+
**Form.parameter**
+-------------------+----------------------------------------------------------------------------------+
| Attribute | Description |
+===================+==================================================================================+
| restParam | Optional. CSV list of variable names. E.g.: ``restParam=pId,adrId`` |
+-------------------+----------------------------------------------------------------------------------+
| restToken | Optional. User defined string or dynamic token (see :ref:`restAuthorization`). |
+-------------------+----------------------------------------------------------------------------------+
.. note::
There are *no* native-FormElements necessary - but might exist for dependent records to delete. Action FormElements
will be processed.
.. _`restAuthorization`:
Authorization
-------------
A QFQ form is only accessible via REST API, if ``Form.permitRest`` enables one of the HTTP Methods: **get, post, put, delete**
``Permit New`` or ``Permit Edit`` don't apply to QFQ forms called via REST.
.. important::
By default, the REST API is public accessible.
* HTTP AUTH (configured via web server).
* Any other web server based access restriction method.
* QFQ internal 'HTTP header token based authorization' (see below).
Token based authorization
^^^^^^^^^^^^^^^^^^^^^^^^^
A form will require a 'token based authorization', as soon as there is a ``form.parameter.restToken`` defined.
Therefore the HTTP Header 'Authorization' has to be set with ``token=<secret token>``. The 'secret token' will
be checked against the server.
Example: ::
form.parameter.restToken=myCrypticString0123456789
Test via commandline: curl -X GET -H 'Authorization: Token token=myCrypticString0123456789' "http://localhost/qfq/typo3conf/ext/qfq/Classes/Api/rest.php/person/123/address/"
The static setup with ``form.parameter.restToken=myCrypticString0123456789`` is fine, as long as only one token
exist. In case of multiple tokens, replace the static string against a SQL query.
.. tip::
The HTML Header Authorization token is available in STORE_CLIENT via '``{{Authorization:C:alnumx}}``.
Best Practice: For example all created tokens are saved in a table 'Auth' with a column 'token'. Define::
form.parameter.restToken={{SELECT a.token FROM Auth AS a WHERE a.token='{{Authorization:C:alnumx}}' }}
An invalid or empty Authorization string won't select any record in ``form.parameter.restSqlList / form.parameter.restSqlData``.
To restrict access to a subset of data, just save the limitations inside the Auth record and update the query
to check it::
form.parameter.restToken={{SELECT a.token FROM Auth AS a WHERE a.token='{{Authorization:C:alnumx}}'}}
form.parameter.restSqlList={{!SELECT p.id, p.name, p.email FROM Person AS p, Auth AS a WHERE a.token='{{Authorization:C:alnumx}}' AND a.attribute=p.attribute}}
form.parameter.restSqlData={{!SELECT p.* FROM Person AS p, Auth AS a WHERE a.token='{{Authorization:C:alnumx}}' AND a.attribute=p.attribute AND p.id='{{r:T0}}' }}
If authorization is denied, the request will be answered with a delay of 3 seconds (configured via securityFailedAuthDelay).