diff --git a/developer_manual/exapp_development/development_overview/ExAppLifecycle.rst b/developer_manual/exapp_development/development_overview/ExAppLifecycle.rst index b7df38ca51e..fc9458688d5 100644 --- a/developer_manual/exapp_development/development_overview/ExAppLifecycle.rst +++ b/developer_manual/exapp_development/development_overview/ExAppLifecycle.rst @@ -37,12 +37,12 @@ You can define any custom container startup logic here if needed. Heartbeat ********* -The ``GET /heartbeat`` method is called periodically by Nextcloud to check the ExApp health status, -i.e. if its webserver is running and receiving requests. +AppAPI calls ``GET /heartbeat`` periodically when it installs, updates or enables the ExApp, until it answers, +to check that its web server is up and running. URL: ``GET http://localhost:2345/heartbeat`` -AppAPI expects a response with HTTP status 200. +AppAPI expects HTTP status 200 with ``{"status": "ok"}``. This step fails if the ExApp does not respond within 10 minutes. .. note:: diff --git a/developer_manual/exapp_development/tech_details/Deployment.rst b/developer_manual/exapp_development/tech_details/Deployment.rst index a993baad4db..a61b672d60b 100644 --- a/developer_manual/exapp_development/tech_details/Deployment.rst +++ b/developer_manual/exapp_development/tech_details/Deployment.rst @@ -84,7 +84,7 @@ Options * ``--json-info JSON-INFO`` *[optional]* - ExApp deploy JSON info (json string) .. warning:: - After successful deployment (pull, create, and start container), there is a heartbeat check with a 90 second timeout (will be configurable). + After successful deployment (pull, create, and start container), there is a heartbeat check with a 10 minute timeout. Manual install for development ****************************** @@ -125,7 +125,7 @@ Application installation scheme ------------------------------- 1. AppAPI deploys the application and launches it. - 2. For `N` seconds (default ``90``), AppAPI checks the ``/heartbeat`` endpoint with a ``GET`` request. + 2. For up to 10 minutes, AppAPI checks the ``/heartbeat`` endpoint with a ``GET`` request. 3. AppAPI sends a ``POST`` request to the ``/init`` endpoint. If the ExApp does not implement the ``/init`` endpoint and AppAPI receives a 501 or 404 status code, AppAPI enables the application and goes straight to step 5. 4. The ExApp sends an integer from ``0`` to ``100`` to the OCS endpoint ``apps/app_api/apps/status`` indicating the initialization progress. After sending ``100``, the application is considered initialized. 5. AppAPI sends a ``PUT`` request to the ``/enabled`` endpoint. diff --git a/developer_manual/exapp_development/tech_details/api/routes.rst b/developer_manual/exapp_development/tech_details/api/routes.rst index 8cb44522994..a6fad54fc63 100644 --- a/developer_manual/exapp_development/tech_details/api/routes.rst +++ b/developer_manual/exapp_development/tech_details/api/routes.rst @@ -4,7 +4,7 @@ Routes ====== -All ExApps must declare the routes that are allowed to be accessed via the AppAPI ExApp proxy (``/apps/app_api/proxy/*``). +All ExApps must declare the routes that users and clients may access, through the AppAPI ExApp proxy (``/apps/app_api/proxy/*``) or, with HaRP, directly (``/exapps//*``). Register @@ -34,13 +34,38 @@ Example where the fields are: -- ``url``: the route to be registered on the ExApp side, can be a regex -- ``verb``: the HTTP verb that the route will accept, can be a comma separated list of verbs +- ``url``: the route to be registered on the ExApp side, a regex matched from the start of the decoded request path, which begins with ``/`` (e.g. ``^/api/.*``); only HaRP matches it case-sensitively +- ``verb``: the HTTP verbs that the route accepts, a comma separated list (e.g. ``GET,POST``) - ``access_level``: the name of the access level required to access the route, PUBLIC - public access without auth, USER - Nextcloud user auth required, ADMIN - admin user required -- ``headers_to_exclude``: a JSON-encoded string of an array of strings, the headers that the ExApp wants to be excluded from the request to it +- ``headers_to_exclude``: a JSON-encoded string of an array of strings, the headers that the ExApp wants to be excluded from the request to it; only the ExApp proxy applies it - ``bruteforce_protection``: a JSON-encoded string of an array of numbers, the HTTP status codes that must trigger the bruteforce protection +Matching +^^^^^^^^ + +The first route whose ``url`` matches the path and whose ``verb`` lists the method decides the access level; ``HEAD`` is accepted wherever ``GET`` is. +If routes match the path but none lists the method, the request gets ``405``; the ExApp proxy serves only ``GET``, ``HEAD``, ``POST``, ``PUT`` and ``DELETE`` and answers ``404`` instead. +HaRP and the ExApp proxy also check the path as ExApp web servers may read it (in any letter case, without a trailing slash, without ``;`` parameters, with ``%2F`` kept in its segment), and the route of such a reading can only raise the access level. +Paths with ``.`` or ``..`` segments and the ``/heartbeat``, ``/init`` and ``/enabled`` endpoints are refused. + +For example, with these routes in this order: + +================ ============ ================ +``url`` ``verb`` ``access_level`` +================ ============ ================ +``^/img(/.*)?$`` ``GET`` ``PUBLIC`` +``^/api/.*`` ``GET,POST`` ``USER`` +``.*`` ``GET`` ``ADMIN`` +================ ============ ================ + +- ``GET /img/logo.png`` and ``HEAD /img/logo.png`` are public. +- ``GET /api/items`` needs a user: the ``USER`` route comes before ``.*``. +- ``DELETE /api/items`` gets ``405`` from HaRP and ``404`` from the ExApp proxy; ``PATCH /api/items`` gets ``405`` from both. +- ``GET /IMG/logo.png`` needs an admin: in this letter case only ``.*`` matches it. +- With ``^/img/.*`` as the first route, ``GET /img/`` would need an admin: without the trailing slash only ``.*`` matches it, so write a route for a directory as ``^/img(/.*)?$``. + + Unregister ^^^^^^^^^^