\documentclass{article}
\usepackage{ulem}
\usepackage{graphicx}
\usepackage{hyperref}
\pagestyle{headings}
\begin{document}
\part{Project Name}
Project to rewrite parts of Horde\_Rpc and the Horde Core Registry inter-app API for a new major release

\section{Bugs}
List any tickets on <a href="http://bugs.horde.org/">http://bugs.horde.org/</a> that cover this issue or are relevant to it.

\section{People}
Ralf Lang

\section{Description}
Main Design Goals:

\begin{itemize}
\item Facilitate mapping of free form URIs to API calls (for REST)


\item Facilitate customizing/amending APIs by administrator/downstream


\item Allow passing PHP Objects when using the API internally -> Need a defined way to fold them to array/scalar representations on RPC


\item Allow separate authentication mechanisms for external calls (REST, RPC) like using API keys, even limiting them.


\item Allow unauthenticated usage of select RPC API calls.


\item Ability for administrators to turn off remote access to some APIs


\item Avoid boilerplate inside Api method implementation


\item Little or no setup for default case


\item Allow but don't require versioning


\item keep code upgrade costs from H5 to H6 reasonable


\end{itemize}
Side Goal:

\begin{itemize}
\item Allow routing API calls to external horde instances


\end{itemize}
\section{Current H5 API}
API routing

An API is a named collection of methods

H5 registry allows to route an API to an app and to override this decision for certain methods<br />
For example, ingo is the default target for "filter" api and the defined target for certain methods of the "mail" api, which defaults to imp

<pre><code>    'provides' =\textbackslash\{\}> array\textbackslash\{\}(
        'filter',
        'mail/blacklistFrom',
        'mail/showBlacklist',
        'mail/whitelistFrom',
        'mail/showWhitelist',
        'mail/applyFilters',
        'mail/canApplyFilters',
        'mail/showFilters',
        'mail/newEmailFilter'
    \textbackslash\{\}),
</code></pre>
However, currently an App cannot provide separate implementations for the same method name in different APIs. Calling filter/newEmailFilter would yield the mail/newEmailFilter method due to all methods being part of one collective Api.php

The current API also does not allow named parameters, even if some RPC mechanisms would deal with it

If an API provides an evolving protocol, discerning versions and supporting older input and output formats would be the method implementation's task

The registry allows limited runtime introspection (hasMethod, listMethods, listApis) but no hints on input/output formats (parameter list and type)

\section{Proposed H6 API changes}
\subsection{implementation strategy}
A runner checks all known <a href="https://wiki.horde.org/ApiTypes">ApiTypes</a> (Jsonrpc, Rest, Xmlrpc, ...) if it can handle the request until it finds a suitable candidate

\begin{itemize}
\item Each <a href="https://wiki.horde.org/ApiType">ApiType</a> decides by request headers, URI scheme, request method, and request body content to rule out api types as fast/cheap as possible


\item A formally suitable apitype checks its router for known command implementations which match any parameter set (path, method, subdomain...)


\item <a href="https://wiki.horde.org/ApiType">ApiType</a> unpacks request parameters from apitype specific format


\item Perform any prefilter tasks like authentication, permission checking, if required by router configuration.


\item Delegate execution to the implementation class and method found from the router


\item pack return value into backend specific format (if not directly returned by implementation class)


\item Apply post filters if configured (API accounting, gzip postprocessing,


\item The runner writes the response to the stdout<br />
OPTIONAL


\item A simplified <a href="https://wiki.horde.org/ApiType">ApiType</a> for internal/interapp calls allows to skip most detection magic but use the extra features is desired - no runner needed here


\end{itemize}
\subsection{misc ideas}
\begin{itemize}
\item Split \$App\_Api class into \$App\_Api\_\$Api classes - Apis still need to be registered in registry. (MEDIUM)<br />
-> Limited support with fallback to \$App\_Api exists in <a href="https://github.com/ralflang/Core/tree/class-per-api">https://github.com/ralflang/Core/tree/class-per-api</a><br />
-> needs cleanup


\item Implement parameter and return hints -- TBD -> only needed for external interfaces? (Needed for REST, maybe SOAP)<br />
-> Generate openapi data from these hints


\item move DAV browsing/CRUD code to API methods -> Does this also make sense for <a href="https://wiki.horde.org/ActiveSync">ActiveSync</a>? (OPTIONAL)


\item Factor method routing out of Horde\_Rpc\_* into a loadable module to decouple Horde\_Rpc from the Horde ecosystem (HIGH)


\end{itemize}
-> The Rest feature will not use the Horde\_Rpc package, at least in its current form. Lessons Learned and helper infrastructure should go into a rewrite for Horde\_Rpc backends with some smooth transition path.

-> For any meaningful Rest support, Horde\_Controller needs to support raw request body.<br />
<a href="https://github.com/horde/Controller/pull/1">https://github.com/horde/Controller/pull/1</a>

A simple boilerplate router should be part of Horde\_Rpc to facilitate unit testing<br />
A Horde-specific router Horde\_Core\_Rpc\_Router should be part of Horde\_Core and interact with registry

Call internal api \$App\_Api\_\$Api to actually run a command<br />
should check what returns for PHP objects and reduce them to arrays (<u>sleep or Serializable)<br />
allow plugging separate authentication, accounting ...<br />
may have to be amended by specific classes or config to support some RPC types (REST)

In Question: Does it make sense to also wrap internal calls into a Runner\_Internal ?

\$registry->calendar->addEvent(\$args);<br />
\$registry->call('calendar/addEvent', \$args);

The Internal runner simply moves setting up the execution environment and calling the actual class and method from the registry class.<br />
As of now, no additional functionality is considered but it may be handy for debugging.

++ Accounting

Accounting is optional and will probably only be implemented if somebody is interested. Accounting defines a set of limits (value per timespan) and stores usage timestamps in a backend (user, timestamp, action). If the number of usages inside a sliding window hits the limit, the request is denied.<br />
Asking for a past window (like first of month, first of next month) allows for billing/reporting, if this is of any interest.<br />
Implementation could use horde\_histories, horde\_locks (no billing due to cleanup) or a text file backend (probably inefficient).

The accounting lib can probably be reused for other things.

++ CODE UPGRADE<br />
For internal app calls, git mv \$app/lib/Api.php to \$app/lib/Api/\$Api.php and change class name. Move overrides into a separate class. Done.<br />
For most external calls, additionally extend to-be-written Horde\_Core\_Api\_Rpc into \$App\_Api\_\$Api\_Rpc - probably the defaults will be just fine for upgrade.

++ API Protection<br />
Protection modules may be combined, probably at first we only want Horde Auth (like Login, for <a href="https://wiki.horde.org/ActiveSync">ActiveSync</a>, DAV) and Extra Auth (API keys or SSL)

No Auth<br />
Horde Default Auth<br />
Admin Only<br />
Need Permission (implies any auth)<br />
Extra Auth (how to map to Horde Users for permissions?)

Per-User global accounting<br />
Per-User Per-Api accounting<br />
Per-User Per-Method accounting

++ CONFIG:<br />
Horde Level:<br />
Rpc<br />
Decide which RPC Types are generally enabled. Default?<br />
Decide which RPC Types use Horde Auth, Separate Auth or both

Accounting<br />
Set up accounting system at all (yes/no)<br />
Set up global per-user accounting (yes/no)<br />
Set up anonymous accounting (yes/no)

App Level:<br />
Upstream provides defaults on which RPC methods are available and how they are protected (multiple available).<br />
Admin / Config may override, empty config uses defaults

++ API characteristics

LOCAL: INTERNAL

\begin{itemize}
\item use registry to discover API methods and their implementations


\item any api/method combination may be served by any application (registry knows)


\item no real metadata on parameter count and formats available


\item currently no named parameters


\item can directly use objects as parameters or return types (rarely used yet, breaks external apis as of now)


\end{itemize}
RPC: JSON-RPC, XML-RPC

\begin{itemize}
\item use registry to discover API methods and their implementations


\item wraps INTERNAL API in specific formats (JSON, XML)


\item Currently breaks for INTERNAL apis which use objects


\item Requires authentication, but any authorization/limits beyond that is left to the INTERNAL method implementation


\item Needs custom serialization for API objects which don't implement </u>toString


\item In theory, named parameters are possible, but the Horde infrastructure can't handle them


\item HTTP-wise, it's POST to a well-known endpoint


\item need to parse data to find the appropriate api/method, hence implementation


\end{itemize}
Webdav, Caldav, Carddav:

\begin{itemize}
\item Fixed set of methods


\item Webdav implemented for multiple resources, Caldav/Carddav backends are really designed to work for one app each


\item No need to discover or route methods, can use fixed class layout for implementation (browse, delete, ...)


\end{itemize}
REST:

\begin{itemize}
\item Resource-centric


\item Should we assume each registry API is a resource?


\item Any URL formats and lengths possible,


\item methods per resource should be limited to http verbs


\item multiple input and output formats may be governed by content type


\item Supports multiple API versions in parallel (either by URL or by content type)


\item each request must be authenticated, no sessions.


\end{itemize}
Horde AJAX Framework

\begin{itemize}
\item Not currently part of the RPC family


\item separate endpoint


\item URL exposes application and method


\item Uses cookies/sessions/tokens


\item mostly JSON


\end{itemize}
SOAP:

\begin{itemize}
\item Unsure if it really still works


\item similar to XML-RPC


\item but SHOULD generate meta information for the client (where? how?)


\end{itemize}
Common:

\begin{itemize}
\item We can discern each http remote protocol by URL and/or content type. What is not covered, should be assumed REST.


\item Once we know the protocol, we know how to find out API and method (and, via registry, implementation)


\end{itemize}
\section{Resources}

\noindent\rule{\textwidth}{1pt}
Back to the <a href="https://wiki.horde.org/Project">Project List</a>

\end{document}
