Hey there,
currently I’m having a go on trying to implement a custom NextCloud app - native, not ExApp. While I already got some things working, I have a hard time understanding how to correctly use Controllers, Routes & Responses. Basically, I’d like to know when to use which of the respectively available subtypes and how to combine them.
I’ll explain in more detail below and also link to the available resources & discussions that I’ve already found. If I’ve overlooked some available documentation or thread that already clarifies these questions, I’d be glad to receive some pointers. Moreover, if I can get some answers in this thread, I’ll try to suggest improvements to the docs on nextcloud/documentation:
Nextcloud documentation, but it didn’t seem wise to start that discussion over there.
Okay, hereI we go. I’m aware of the following things.
Controllers
AFAIK there are 5 controller classes available, as documented here:
Controller, base class: refApiController: ref | dev-docsOCSController: ref | dev-docsPublicShareController: ref|dev-docsAuthPublicShareController: ref | dev-docs
I already found some discussions about ApiController vs OCSController, namely in Dev manual is contradicting re: OCS versus REST -
Development, which also lead to dev-doc updates in Issue #12157 · nextcloud/documentation / Pull Request #12264 · nextcloud/documentation with the changes now public here. TL;DR: OCS is preferred over REST and hence, OCSController should be preferred should be preferred. The page also explains how using OCSController affects any DataResponse return values:
Methods from
Controllerclasses can returnDataResponseobjects similar toOCSControllerclass methods. For methods of aControllerclass, the data of this response is sent e.g. as JSON as you provide it. Basically, the output is very similar to whatjson_encodewould do. In contrast, theOCSControllerwill encapsulate the data in an outer shell that provides some more (meta) information. For example a status code (similar to the HTTP status code) is transmitted at top level. The actual data is transmitted in thedataproperty.
Routes
AFAIK there are 3 Route classe available, as documented here:
Developer documentation for all three is mostly available here. Moreover, there is a comment in the app dev tutorial, specifically in part 6, which reads
There are 2 types of network APIs in Nextcloud:
the internal API (defined by the
FrontpageRoutePHP attribute) and the OCS API (defined by theApiRouteattribute).The internal API is supposed to be created and consumed by the same developers. Since the API is not used by other developers, it does not have to be stable in time and developers can change their internal APIs whenever they wish.
The OCS APIs can be used internally but can also allow clients to interact with an app. Therefore, it must be stable to avoid breaking the clients. This is why we include the API version number in the endpoint paths. For example, any change breaking the version 1 of our API will lead to creating a version 2. This way we can keep version 1 untouched and old clients can still work because they still target version 1.
From this description, it’s not clear to me if
FrontpageRouteendpoints are protected at runtime to be accessible through the nextcloud frontend or- if this is simply a convention discouraging external services to use these endpoints, but no actual enforcement happens
Responses
AFAIK there are response classes available, as documented here and here:
DataDisplayResponse: refDataDownloadResponse: refDataResponse: ref | dev-docsDownloadResponse: ref | dev-docsFileDisplayResponse: refJSONResponse: ref | dev-docsNotFoundResponse: refRedirectResponse: ref | dev-docsResponse, base class: ref | dev-docsStandaloneTemplateResponse: refStreamResponse: ref | dev-docsTemplateResponse: ref | dev-docsPublicTemplateResponse: ref | dev-docsTextPlainResponse: refTooManyRequestsResponse: refZipResponse: ref
The dev-docs of JSONResponse say
The usage of standard controller to access content data like JSON (no HTML) is considered legacy. Better use OCS for this type of requests.
Based on the comments on ApiController and OCSController, I would hence expect, that this hint boilds down to using OCSController with DataResponse. However, I noticed that the example snippets here use the plain Controller with JSONResponse instead of OCSController.
On REST APIs — Nextcloud latest Developer Manual latest documentation, the snippets suggest to use ApiController for REST APIs.
In part 6 of the tutorial linked above, they use DataResponse on a plain Controller and on a OCSController. Moreover, they use DataResponse both with FrontpageRoute and ApiRoute. TemplateResponse is used only with FrontpageRoute.
On OCS OpenAPI tutorial — Nextcloud latest Developer Manual latest documentation, the use TemplateResponse in some examples, but the overall guide says that OCSController should be used which to my understanding is meant to be used together with DataResponse.
On Routing — Nextcloud latest Developer Manual latest documentation it says
FrontpageRoutehas to be used for routes that were in theroutessection andApiRoutehas to be used for routes that were in theocssection.
and
Registering of OCS routes requires to use a corresponding controller. Additionally, the route must be configured to be an OCS route in the router.
In addition to PublicTemplateResponse and TooManyRequestsResponse, I’ve also seen the attributes
PublicPage(ref). On Controllers — Nextcloud latest Developer Manual latest documentation it’s used in combination withController, on Public Pages — Nextcloud latest Developer Manual latest documentation it’s used in combination withPublicShareControllerUserRateLimit,AnonRateLimiteandARateLimit(apparently base casse), all documented here, dev-docs here.
And now what?
With the above summary I hope to illustrate the wide range of available controllers, routes, responses and even attributes and that from the available documentation resources it’s not straightforward to understand which of those objects should be used for which use cases in which combination.
I would very much like to get some guidelines on how to combine controllers, routes, responses & attributes for standard use cases, maybe similar to the ones listed here, which are:
- Access from web frontend means the user is accessing the Nextcloud web frontend with a web browser.
- Access from non-browser is if the user accesses the resource or page using something that is not a web browser, like an Android app or a curl command.
- Access from external website means that the user browses some third party web site and data from your Nextcloud server appears. The other website has to embed/load/use images, JSON data, or other resources from a URL pointing to the Nextcloud server, to be able to do this.
The use cases of endpoints serving GUIs (e.g. the NextCloud frontend) and endpoints serving data/APIs (i.e. frontend-backend communication or public APIs) certainly need to be separated.
Additionally, I have some specific questions in addition to the general understanding
- If certain combinations (e.g. router & controller, response type & router) are desired or even necessary, are there any runtime checks for these?
- What is the difference between using the
PublicPageattribute and returning aPublicTemplateResponseresponse? - What effects exactly do controllers, routes & attributes have on the endpoints in terms of
- effective url
- data format
- CSRF, CORS and possibly other security mechanisms?
- does
FrontpageRouteindeed “hide” the endpoint from access outside the NextCloud API or is that a misunderstanding? If that’s not the case:- what’s the benefit using using
DataResponsewithFrontpageRouteas done in the tutorial - shouldn’t that rather be done throughOCSController+ApiRoute, then? - What’s the recommended approach to split an internal API used for communication between frontend & backend from an external API that’s allowed to be used directly by users or 3rd parties?
- what’s the benefit using using
- what would be a good place to suggest improving the class documentation of the different PHP classes such that the API reference is more informative? The nextcloud/server repository or the nextcloud/documentation repository?
This has become quite a bit longer than I had anticipated. Nevertheless, I’m glad for any hints, tips, replies or redirections to existing threads. Please excuse me if I’ve missed some things that might be more intuitive after more experience with NextCloud development or web development in general.
Cheers ![]()