diff options
author | Orangerot <purple@orangerot.dev> | 2024-05-24 17:42:08 +0200 |
---|---|---|
committer | Orangerot <purple@orangerot.dev> | 2024-05-24 17:47:22 +0200 |
commit | 7fcdc1c788725f866de71fc9dfd8c4d1cb132b57 (patch) | |
tree | 89931c85ae3f149884ba02c69862558e93f01531 /10-entwurfsheft/sections/apidoc.tex |
Diffstat (limited to '10-entwurfsheft/sections/apidoc.tex')
-rw-r--r-- | 10-entwurfsheft/sections/apidoc.tex | 558 |
1 files changed, 558 insertions, 0 deletions
diff --git a/10-entwurfsheft/sections/apidoc.tex b/10-entwurfsheft/sections/apidoc.tex new file mode 100644 index 0000000..1eb181c --- /dev/null +++ b/10-entwurfsheft/sections/apidoc.tex @@ -0,0 +1,558 @@ +\newenvironment{urlParameter} +{ + \newcommand{\urlParamItem}[2] + { + \rowcolor{\methodLightColor} ##1 & ##2 \\ + } + \newcommand{\noUrlParameter}[1] + { + \small{\textit{##1}} + } + %\vspace{-0.61em} + + \arrayrulecolor{\methodColor} + + \begin{tabularx}{\textwidth}{X} + \rowcolor{\methodLightColor!20} + \textbf{URL-Parameter} \\ \hline + \end{tabularx} + + \tabularx{\textwidth}{l X} +} + +\newenvironment{pathParameter} +{ + \newcommand{\pathParamItem}[2] + { + \rowcolor{\methodLightColor} ##1 & ##2 \\ + } + \newcommand{\noPathParameter}[1] + { + \small{\textit{##1}} + } + %\vspace{-0.61em} + + \arrayrulecolor{\methodColor} + + \begin{tabularx}{\textwidth}{X} + \rowcolor{\methodLightColor!20} + \textbf{Pfad-Parameter} \\ \hline + \end{tabularx} + + \tabularx{\textwidth}{l X} +} + +\newenvironment{jsonKeys} +{ + \newcommand{\jsonKeyItem}[2] + { + \rowcolor{\methodLightColor} ##1 & ##2 \\ + } + \newcommand{\nojsonKeys}[1] + { + \small{\textit{##1}} + } + %\vspace{-0.61em} + + \arrayrulecolor{\methodColor} + + \begin{tabularx}{\textwidth}{X} + \rowcolor{\methodLightColor!20} + \textbf{Json-Keys} \\ \hline + \end{tabularx} + + \tabularx{\textwidth}{l X} +} + +\section{\Gls{api}} + +\subsection{Hypertext Transfer Protocol} +% könnte auch unter in die Sektion API + +Das Hypertext Transfer Protocol (http) ist ein Protokoll zum übertragen von +medialen Daten. Ein Webserver hört über den Port 80 auf Anfragen und antwortet. +Eine Anfrage besteht aus einer Methode, einem Pfad, Kopfzeilen (\texttt{Header}) +und Inhalt (\texttt{Body}). Die Methode ist eine Konvention, um zu verdeutlichen +was mit der Anfrage geschehen soll. Es können Daten abgefragt (\texttt{GET}), +erstellt (\texttt{POST}), aktualisiert (\texttt{PUT}) oder gelöscht werden +(\texttt{DELETE}). Der Pfad gibt an, für welche Daten die Methode gelten soll. +Die Kopfzeilen beinhalten dabei Metadaten, wie Authentifikationen, \Glspl{cookie}, +Datentypen (MIME-Types), Sprache und das Anwenderprogramm. + +Der Server antwortet mit einem Statuscode, Kopfzeilen und Inhalt. Der Statuscode +teilt mit, ob die Anfrage erhalten wurde ($\geq$ 100), erfolgreich bearbeitet +werden konnte ($\geq$ 200), eine Weiterleitung nötig ist ($\geq$ 300), +die Anfrage einen Fehler enthält ($\geq$ 400) oder +ein interner Serverfehler aufgetreten ist ($\geq$ 500). In den Kopfzeilen können +Berechtigungen gesetzt werden, welche festlegen, wie mit den Daten +umzugehen ist. + +\newpage +\subsection{Geräte} \label{Geräte} +Die \Gls{gpodder}, welche wir für unser Produkt verwenden und erweitern, bietet eine gerätespezifische +Synchronisation an. Diese bieten wir jedoch nicht an, denn wir synchronisieren Änderungen aller +Geräte gleichwertig mit dem Nutzeraccount. +Deshalb werden Geräte innerhalb der API ignoriert. + +\subsection{Authentication API}\label{a:auth} + +\subsubsection{Registrierung}\label{a:register} + +\begin{apiRoute}{post}{/api/2/auth/register.json} + {Registriert einen Nutzer mit einer E-Mail-Adresse und Passwort. + Versendet E-Mail mit Bestätigungslink an die angegebene E-Mail-Adresse.} + \begin{routeRequest}{application/json} + \begin{routeRequestBody} +{ + email: "jeff@example.com", + password: "MyNameIsJeff" +} + \end{routeRequestBody} + \end{routeRequest} + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: Nutzer wurde erfolgreich angelegt.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400} + {Bad Request: Fehler beim Parsen der Anfrage} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\newpage + +\subsubsection{Anmelden}\label{a:login} + +\begin{apiRoute}{post}{/api/2/auth/\{username\}/login.json} + {Gegebenen Nutzer des gegebenen Geräts mithilfe HTTP Basic Auth einloggen.} + \begin{pathParameter} + \pathParamItem{username}{Nutzername des einzuloggenden Nutzers} + \end{pathParameter} + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: Die Responseheader haben ein gesetztes Session-ID \Gls{cookie}.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400} + {Bad Request: Der Client stellt einen \Gls{cookie} für einen falschen Nutzer bereit.} + \end{routeResponseItem} + + \begin{routeResponseItem}{401} + {Unauthorized: Zugriff ohne Anmeldedaten} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\subsubsection{Abmelden}\label{a:logout} + +\begin{apiRoute}{post}{/api/2/auth/\{username\}/logout.json} + {Löscht den \Gls{cookie} beim Client.} + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \end{pathParameter} + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: Falls der Client keinen \Gls{cookie} gesendet hat oder der Nutzer + erfolgreich ausgeloggt wurde.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400} + {Bad Request: Der Client stellt einen \Gls{cookie} für den falschen Nutzer bereit.} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\newpage + +\subsubsection{Passwort ändern}\label{a:changepassword} + +\begin{apiRoute}{put}{/api/2/auth/\{username\}/changepassword.json} + {Passwort des gegebenen Nutzer ändern, indem altes und neues Passwort + übergeben werden. } + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \end{pathParameter} + \begin{routeRequest}{application/json} + \begin{routeRequestBody} +{ + password: "MyPasswordWasLeaked", + new_password: "SoIMadeANewOne" +} + \end{routeRequestBody} + \end{routeRequest} + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: Die Responseheader haben ein gesetztes Session-ID \Gls{cookie}.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400} + {Bad Request: Der Client stellt einen \Gls{cookie} für einen falschen Nutzer bereit.} + \end{routeResponseItem} + + \begin{routeResponseItem}{401} + {Unauthorized: Zugriff ohne Anmeldedaten} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\subsubsection{Passwort vergessen}\label{a:forgot} + +\begin{apiRoute}{post}{/api/2/auth/forgot.json} + {Sende eine E-Mail zum Zurücksetzen des Passworts. } + \begin{routeRequest}{application/json} + \begin{routeRequestBody} +{ + email: "jeff@example.com" +} + \end{routeRequestBody} + \end{routeRequest} + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: E-Mail wurde erfolgreich versendet.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400} + {Bad Request: Fehler beim Parsen der Anfrage} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\newpage +\subsubsection{Passwort zurücksetzen}\label{a:resetpassword} + +\begin{apiRoute}{put}{/api/2/auth/\{username\}/resetpassword.json} + {Passwort des gegebenen Nutzers ändern nachdem dieser sein Passwort + vergessen hat. } + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \end{pathParameter} + \begin{urlParameter} + \urlParamItem{token}{JSON-Web-Token} + \end{urlParameter} + \begin{routeRequest}{application/json} + \begin{routeRequestBody} +{ + password: "APasswordIWontForgetAgain" +} + \end{routeRequestBody} + \end{routeRequest} + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: Das Passwort wurde erfolgreich geändert.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400} + {Bad Request: Fehler beim Parsen der Anfragen. } + \end{routeResponseItem} + + \begin{routeResponseItem}{401} + {Unauthorized: JWT ist ungültig. } + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\newpage +\subsubsection{Account löschen}\label{a:delete} + +\begin{apiRoute}{delete}{/api/2/auth/\{username\}/delete.json} + {Der Account des gegebenen Nutzers wird gelöscht.} + \begin{pathParameter} + \pathParamItem{username}{Nutzername des zu löschenden Nutzers.} + \end{pathParameter} + \begin{routeRequest}{application/json} + \begin{routeRequestBody} +{ + password: "APasswordIWontHaveToRememberAnymore" +} + \end{routeRequestBody} + \end{routeRequest} + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: Der Account des gegebenen Nutzers wurde erfolgreich gelöscht.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400} + {Bad Request: Der Client stellt einen \Gls{cookie} für einen falschen Nutzer bereit.} + \end{routeResponseItem} + + \begin{routeResponseItem}{401} + {Unauthorized: Zugriff ohne Anmeldedaten} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\newpage +\subsection{Subscriptions API}\label{a:subs} +\subsubsection{Abrufen aller \Glspl{abo}}\label{a:getSubs} + +\begin{apiRoute}{get}{/subscriptions/\{username\}.json}{/subscriptions/\{username\}/\{deviceid\}.json} + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \pathParamItem{deviceid}{siehe~\nameref{Geräte}} + \end{pathParameter} + + \begin{urlParameter} + \urlParamItem{jsonp}{\Gls{JSONP} wird nicht unterstützt und der Parameter entsprechend ignoriert.} + \end{urlParameter} + + \begin{routeResponse}{application/json} + + \begin{routeResponseItem}{200} + {OK: \Glspl{abo} werden im \Gls{json}-Format zurückgegeben.} + \begin{routeResponseItemBody} +[ + "http://example.org/feed.rss", + "http://example.org/podcast.php", + "http://example.org/foo" +] + \end{routeResponseItemBody} + \end{routeResponseItem} + + \begin{routeResponseItem}{400}{Bad Request: falsches Format} + \end{routeResponseItem} + + \begin{routeResponseItem}{401} + {Unauthorized: falscher Nutzer oder nicht eingeloggt} + \end{routeResponseItem} + + \end{routeResponse} +\end{apiRoute} + +\newpage +\subsubsection{Abrufen der Informationen aller \Glspl{abo}}\label{a:getTitles} + +\begin{apiRoute}{get}{/subscriptions/titles/\{username\}.json}{/subscriptions/\{username\}/\{deviceid\}.json} + + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \end{pathParameter} + \begin{routeResponse}{application/json} + + \begin{routeResponseItem}{200} + {OK: \Glspl{abo} werden im angefragten Format zurückgegeben. Dabei werden für ein \Gls{abo} nur die aktuellsten 20 \Glspl{episode} zurückgegeben.} + \begin{routeResponseItemBody} +[ + { + "url": "http://example.com/podcast.php", + "title": "This is a cool podcast" + "timestamp": "2009-12-12T09:00:00", + "episodes": [ + { + "podcast": "http://example.org/podcast.php", + "episode": "http://ftp.example.org/foo.ogg", + "title": "Episode 1: My journy", + "timestamp": "2009-12-12T09:00:00", + "guid": "AU-20190814-1342-5100-A", + "action": "play", + "started": 15, + "position": 120, + "total": 500 + } + ] + } +] + \end{routeResponseItemBody} + \end{routeResponseItem} + + \begin{routeResponseItem}{400}{Bad Request: falsches Format} + \end{routeResponseItem} + + \end{routeResponse} + +\end{apiRoute} +\newpage + +\subsubsection{\Glspl{abo} hochladen}\label{a:uploadSubs} + +\begin{apiRoute}{put}{/subscriptions/\{username\}/\{deviceid\}.json} + {Falls bereits \Glspl{abo} im Nutzeraccount vorhanden, werden diese + zusammengeführt.} + + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \pathParamItem{deviceid}{siehe~\nameref{Geräte}} + \end{pathParameter} + + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200} + {OK: \Glspl{abo} wurden aktualisiert und leerer String wird zurückgegeben.} + \end{routeResponseItem} + + \begin{routeResponseItem}{400}{Bad Request: falsches Format} + \end{routeResponseItem} + + \begin{routeResponseItem}{401}{Unauthorized: falscher Nutzer} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\subsubsection{Abrufen von \Gls{abo}-Änderungen}\label{a:getSubDelta} + +\begin{apiRoute}{get}{/api/2/subscriptions/\{username\}/\{deviceid\}.json} + {} + + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \pathParamItem{deviceid}{siehe~\nameref{Geräte}} + \end{pathParameter} + + \begin{urlParameter} + \urlParamItem{since}{Timestamp-Wert der letzten Antwort} + \end{urlParameter} + + \begin{routeResponse}{application/json} + + \begin{routeResponseItemBody} +{ + "add": [ + "http://example.com/feed.rss", + "http://example.org/podcast.php" + ], + "remove": ["http://example.net/foo.xml"], + "timestamp": 12347 +} + \end{routeResponseItemBody} + \end{routeResponse} + +\end{apiRoute} + +\newpage +\subsubsection{Änderungen der \Glspl{abo} hochladen}\label{a:applySubDelta} + +\begin{apiRoute}{post}{/api/2/subscriptions/\{username\}/\{deviceid\}.json} + {} + + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \pathParamItem{deviceid}{siehe~\nameref{Geräte}} + \end{pathParameter} + + \begin{routeRequest}{application/json} + \begin{routeRequestBody} +{ + "add": [ + "http://example.com/feed.rss", + "http://example.org/podcast.php" + ], + "remove": ["http://example.net/foo.xml"] +} + \end{routeRequestBody} + \end{routeRequest} + + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200}{OK: \Glspl{abo} wurden aktualisiert.} + \begin{routeResponseItemBody} +{ + "timestamp": 1337, + "update_urls": [] +} + \end{routeResponseItemBody} + ``update\textunderscore urls'' wird nicht bereitgestellt, deshalb + wird eine leere Liste zurückgegeben. + \end{routeResponseItem} + \begin{routeResponseItem}{400}{Bad Request: falsches Format} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\newpage +\subsection{Episode Action API}\label{a:episodeActions} + +\subsubsection{Episode Actions hochladen}\label{a:uploadEpisodeActions} + +\begin{apiRoute}{post}{/api/2/episodes/\{username\}.json} + {} + + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \end{pathParameter} + + \begin{routeRequest} + + \begin{routeRequestBody} +POST /api/2/episodes/some-user.json +[ + { + "podcast": "http://example.org/podcast.php", + "episode": "http://ftp.example.org/foo.ogg", + "title": "Episode 1: My journey", + "timestamp": "2009-12-12T09:00:00" + "guid": "AU-20190814-1342-5100-A", + "action": "play", + "started": 15, + "position": 120, + "total": 500 + } +] + + \end{routeRequestBody} + + \end{routeRequest} + + \begin{jsonKeys} + \jsonKeyItem{podcast}{Feed-URL des \Glspl{podcast} zu welchem die \Gls{episode} gehört (erforderlich)} + \jsonKeyItem{episode}{Medien-URL der \Gls{episode} (erforderlich)} + \jsonKeyItem{device}{Geräte-ID auf welcher die Aktion stattfand.} + \jsonKeyItem{action}{Eins von: download, play, delete, new (erforderlich)} + \jsonKeyItem{timestamp}{UTC-Timestamp im ISO 8601 Format, wann die Aktion stattfand} + \jsonKeyItem{started}{Position in Sekunden, an welcher das Anhören der \Gls{episode} gestartet wurde (nur bei Aktion: play)} + \jsonKeyItem{position}{Position in Sekunden, an welcher das Anhören der \Gls{episode} gestoppt wurde (nur bei Aktion: play)} + \jsonKeyItem{total}{Länge der \Gls{episode} (nur bei Aktion: play)} + + \end{jsonKeys} + + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200}{OK} + \begin{routeResponseItemBody} +{ + "timestamp": 1337, + "update_urls": [] +} + \end{routeResponseItemBody} + ``update\textunderscore urls'' wird nicht bereitgestellt, deshalb + wird eine leere Liste zurückgegeben. + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + +\subsubsection{Abrufen von Episode Actions}\label{a:getEpisodeActions} + +\begin{apiRoute}{get}{/api/2/episodes/\{username\}.json} + {} + + \begin{pathParameter} + \pathParamItem{username}{Nutzername des betreffenden Nutzers} + \end{pathParameter} + + \begin{urlParameter} + \urlParamItem{podcast (string)}{URL des \Glspl{podcast}; falls gesetzt, werden nur Aktionen der \Glspl{episode} des gegebenen \Glspl{podcast} zurückgegeben.} + \urlParamItem{device (string)}{Device-ID; siehe~\nameref{Geräte}} + \urlParamItem{since (int)}{Nur \Glspl{episode}-Aktionen ab dem gegebenen Timestamp werden zurückgegeben.} + \urlParamItem{aggregated (bool)}{Wird ignoriert. } + \end{urlParameter} + + \begin{routeResponse}{application/json} + \begin{routeResponseItem}{200}{OK} + \begin{routeResponseItemBody} +{ + "actions": [ + { + "podcast": "http://example.org/podcast.php", + "episode": "http://ftp.example.org/foo.ogg", + "title": "Episode 1: My journey", + "timestamp": "2009-12-12T09:00:00" + "guid": "AU-20190814-1342-5100-A", + "action": "play", + "started": 15, + "position": 120, + "total": 500 + } + ], + "timestamp": 12345 +} + \end{routeResponseItemBody} + \end{routeResponseItem} + \end{routeResponse} +\end{apiRoute} + |