Apitte – REST API navod a dokumentacia first start

duskohu
Člen | 778
+
0
-

Ahojte, mam aplikaciu nad nette, chcel by som do nej implementovat nejake REST API, zaujal ma projekt Apitte. Nieje niekde nejaky manual ako to rozchodit, ako rozbehat jednotlive routy?
Chale by som pouzivat, AUTH na viacero pouzivatelov, ACL, najlepsie aby som mohol implementovat to ktore uz pouzivam.
Zaujimalo by ma ci sa da generovat aj nejaka dokumentacia.

Marek Bartoš
Nette Blogger | 1172
+
-1
-

manual ako to rozchodit, ako rozbehat jednotlive routy

Dokumentace nestačí?

Zaujimalo by ma ci sa da generovat aj nejaka dokumentacia.

apitte/openapi, z core a phpdoc anotací se toho dá vygenerovat celkem dost

AUTH na viacero pouzivatelov, ACL, najlepsie aby som mohol implementovat to ktore uz pouzivam

apitte samo o sobě nic nemá, v dokumentaci najdeš jednoduchý příklad, jak implementovat pro tenhle případ request decorator. Případně lze použít middleware. Jaký autentizační a autorizační mechanizmus použiješ je už čistě jen na tobě

Felix
Nette Core | 1189
+
+1
-

@duskohu Rada ukazek je zde https://github.com/…e/playground

theo
Člen | 57
+
+3
-

V prvé řadě bych chtěl autorům poděkovat a vyjádřit obdiv nad tak rozsáhlou (a podle všeho) i dobře navrženou knihovnou pro vytváření API pro Nette. Něco takového bylo potřeba a je trochu s podivem, že to Nette neumí samo od přírody (jakkoliv chápu, že se k tomu jednak dá Nette poměrně snadno přesvědčit a druhak to není jeho primární účel).

Rozjet Apitte podle příkladů z playgroundu (v tomto směru mi jako velmi přínosný přišel především fullstack) není až takový problém (i když je to trochu divočina: co je napsáno v README.md občas nekoresponduje s tím co je v příkladech v playgroundu apod. ale to se dá přežít). Na co jsem ale narazil je absence vysvětlení k čemu jsou některé části Apitte. Např. Entity (pominu-li krátkou zmínku v dokumentaci Negotiations) nikde v dokumentaci popsáno není (a z příkladu v playgroundu příliš moudrý nejsem, resp. příliš to nekoresponduje s tím, k čemu bych očekával, že je bude možné použít). V Routeru je popsán pouze SimpleRouter, nějak jsem ale nepochopil jak jej používat. Nakonec jsem to vlastně ani řešit nemusel, protože při použití anotací to „prostě nějak funguje“, nevím ale moc jak a proč (což je ovšem obecnější problém anotací a jejich „magie“).

Co mě ale zaskočilo nejvíc je, že mám klasický případ API, kdy endpointy tvoří víceméně rozhraní pro získávání a ukládání dat z databáze. Bohužel jsem ale nepřišel na to jak to udělat. V normální Nette aplikaci je uživatelský presenter potomkem Nette\Application\UI\Presenter což zaručí, že má přes context přístupnou metodu getService() (sice se to teď v Nette 3.0 má zase dělat nějak jinak, ale to teď nechme stranou), kterou už není problém se dobrat potřebné servicy. V příkladech controllerů v playgroundu ale nic takového není, a připadá mi poněkud proti smyslu existence celé knihovny, abych si controller dědil od Nette\Application\UI\Presenter (nač bych pak potřeboval Apitte, že). Čili velice bych ocenil nějaký příklad, ze kterého by bylo zřejmé, jak se uvnitř controlleru dobrat získání služby, nebo (jestliže to takto není zamýšleno a má to být nějak jinak) který by ukázal jak správně napojit takto vyvíjené API na datové zdroje (intuitivně se domnívám, že by to mohlo souviset právě s Entity, ale možná se mýlím). Řekl bych, že je to natolik běžný use-case, že by v příkladech alespoň náznakem pokrytý být mohl.

Také bych připomněl, že v dokumentaci architektury je vložený obrázek, který ale nikam nevede (404) a vzhledem k tomu, že to patrně má být „jeden obrázek za tisíc slov“, je bez něj tato kapitola naprosto k ničemu. Bylo by možné to opravit?

Dále v kapitole Controller se píše „In our case endpoint is implemented as a controller method.“, znamená to tedy, že endpoint lze postavit i jinak než jen jako controller (tedy např. jako presenter)? Bylo by možné (a dává-li to smysl) připojit příklad?

Ve stejné kapitole dále jsou popisy jednotlivých anotací (jak jsem pochopil jsou pro fungování celého Apitte klíčové), nicméně popis jednotlivých položek anotací se omezují na technický popis toho co v nich má nebo nemá být, k čemu se vztahují, ale naprosto chybí popis jejich významu. Smysl @Path, @GroupPath a @ControllerPath si to ještě dovedu domyslet (zjevně slouží k popisu routování controllerů a metod), ale třeba smysl @GroupId je mi záhadou. Smysl @Id jsem po nějakém pátrání našel v README podprojektu Core.

Kapitola Presenter v dokumentaci obsahuje odkaz Setup, který ale vede na neexistující stránku (resp. na neexistující kapitolu Setup).

Je docela velká škoda, že dokumentace na contributte.org je velmi kusá až útržkovitá, zatímco v README souborech jednotlivých podprojektů je daleko obsáhlejší, prostudovat dané téma je v tak komplexním prostředí poměrně komplikované. Ocenil bych, kdyby se informace z README dostaly do dokumentace na contributte.org. Chápu, že je s tím dost práce a každá pomoc je vítaná, pokud bych mohl být nějak užitečný rád pomůžu. Jen se obávám, že při mém stavu porozumění celému projektu toho není mnoho, čím bych mohl pomoci…

Marek Bartoš
Nette Blogger | 1172
+
0
-

Rozjet Apitte podle příkladů z playgroundu

Playgroundy uznávám, nejsou vždy aktuální. Pokud narazíš na nesrovnalosti kódu a dokumentace, tak jako u všeho založ issue nebo se ideálně pokus problém opravit. Pro nás, co Apitte vyvíjíme nebo používáme delší dobu playground není relevantní a čas na komunitní support děláme zcela zdarma, a tak mu nelze věnovat neomezené množství času, i když se snažím na slacku i foru odpovídat.

absence vysvětlení k čemu jsou některé části Apitte

Pokud narazíš na chybějící dokumentaci, tak prosím opět založ issue. Dokumentaci jsem po roce vývoje přepsal ve snaze zahrnout tam všechno, co v Apitte je. Jen jakožto spoluautor a dlouhodobý uživatel na to mám jiný pohled, než běžný uživatel.

k čemu jsou některé části Apitte. Např. Entity (pominu-li krátkou zmínku v dokumentaci Negotiations)

Entity jsou použité právě jen v negotiations, proto nejsou v dokumentaci core zdokumentované. Z core časem zmizí, jsou tam momentálně hlavně pro jednoduchost, protože během prvotního vývoje nebylo jisté, jak se některé problémy budou řešit, tak jsme si nechali cesty otevřené. Rád bych, kdybys uvedl případně i další nejasnosti.

Entity jsou obálky na raw data, které se v negotiations transformují na výstup. Dovoluje to tak ke všem responses přidat data navíc, bez zásahu do controlleru a zároveň i odesílat data v různých formátech (xml, json), opět bez zásahu do controlleru.

V Routeru je popsán pouze SimpleRouter, nějak jsem ale nepochopil jak jej používat.

Router v případě Apitte je plně automatický, ve většině případů bys neměl mít potřebu v něm cokoli měnit. Je tam uvedený spíš jen proto, že jde o důležitou součást a někdo by ji mohl hledat.

při použití anotací to “prostě nějak funguje”, nevím ale moc jak a proč (což je ovšem obecnější problém anotací a jejich “magie”).

Anotace jsou způsob, jak definovat schema controlleru, stejně tak by mohlo být zapsané třeba v neonu. Schema samotné jsem nedokumentoval, jelikož jde o interní věc, do které nelze jednoduše zasáhnout a nikdo by neměl mít potřebu jej měnit. Možná by bylo fajn o něm ale něco napsat, na základě něj celé Apitte funguje.

normální Nette aplikaci je uživatelský presenter potomkem Nette\Application\UI\Presenter což zaručí, že má přes context přístupnou metodu getService()

Tohle celé je špatně. Jakékoli služby máš vyžadovat přes konstruktor třídy nebo nastavovat přes settery. Specialitou Nette jsou inject metody a anotace, které dovolují autowiring i jinak, než přes konstruktor (a i ty je vhodné využívat pouze na presentery, proto jsou ve výchozím nastavení nastavené jen pro ně). Tím že získáváš služby přes getService() degraduješ DIC na service locator. Komplikuješ tak výměnu služeb i testování, vytváříš skryté závislosti a skrýváš případné nedostatky v architektuře (nevidíš, že tvá třída pracuje s příliš mnoho závislostmi). Mimo to, context je jen DIC předaný jako služba. V jakékoli jiné službě jej můžeš získat přes konstruktor a využívat stejně jako v presenteru, i když bys to rozhodně neměl dělat.

dokumentaci architektury je vložený obrázek, který ale nikam nevede (404)

Ve zdrojové dokumentaci na githubu funguje, založil jsem za tebe issue v repozitáři webu
https://github.com/…hitecture.md
https://github.com/…ite/issues/9

Dále v kapitole Controller se píše “In our case endpoint is implemented as a controller method.”, znamená to tedy, že endpoint lze postavit i jinak než jen jako controller (tedy např. jako presenter)?

Tady jse spíš o koncept api endpointů – rest api definuje kombinaci HTTP metody a url adresy, která představuje endpoint. Endpoint je v Apitte implementován skrze metodu controlleru. Používat nette presenter by zde nedávalo smysl, jsou to neslučitelné koncepty.

Ve stejné kapitole dále jsou popisy jednotlivých anotací, nicméně popis jednotlivých položek anotací se omezují na technický popis toho co v nich má nebo nemá být, k čemu se vztahují, ale naprosto chybí popis jejich významu.

Tyhle nedostatky odhaluje právě zpětná vazba, sám o sobě tomu rozumím a přišel mi popis dostačující. Můžeš založit issue, co se nezdá srozumitelné.

Smysl @Path, @GroupPath a @ControllerPath si to ještě dovedu domyslet (zjevně slouží k popisu routování controllerů a metod)

Přesně tak.

@GroupId je mi záhadou. Smysl @Id jsem po nějakém pátrání našel v README podprojektu Core.

GroupId, ControllerId a Id se skládají do unikátního identifikátoru endpointu. Nejspíš koukáš na readme v masteru, kde jsou tyhle anotace spojené již do jedné (Id), stejně jako Path a související anotace. Nedávno jsem k anotaci dopsal následující větu, imho by to mělo být jasné Not used by Apitte for anything, it may just help you identify, group, etc. your endpoints

Kapitola Presenter v dokumentaci obsahuje odkaz Setup, který ale vede na neexistující stránku (resp. na neexistující kapitolu Setup)

Drobná chybka v dokumentaci, vygeneroval se plnohodnotný odkaz namísto kotvy na stránku
https://github.com/…adc6226de700

Je docela velká škoda, že dokumentace na contributte.org je velmi kusá až útržkovitá, zatímco v README souborech jednotlivých podprojektů je daleko obsáhlejší, prostudovat dané téma je v tak komplexním prostředí poměrně komplikované. Ocenil bych, kdyby se informace z README dostaly do dokumentace na contributte.org.

Můžeš uvést konkrétní případ? Dokumentace na webu se vytváří automaticky z dokumentace na githubu.

theo
Člen | 57
+
0
-

Playgroundy uznávám, nejsou vždy aktuální.

Ok, to chápu, v podstatě mají jakousi hodnotu k pochopení celé věci i tak jak jsou. Já jsem to byl podle nich víceméně schopen rozchodit bez větších problémů.

Pokud narazíš na nesrovnalosti kódu a dokumentace, tak jako u všeho založ issue nebo se ideálně pokus problém opravit.

Ok, tohle udělat můžu. Nevím jestli si teď vybavím všechno na co jsem narazil, ale zkusím to nějak pořešit.

Pro nás, co Apitte vyvíjíme nebo používáme delší dobu playground není relevantní a čas na komunitní support děláme zcela zdarma, a tak mu nelze věnovat neomezené množství času, i když se snažím na slacku i foru odpovídat.

Tomu rozumím, nicméně potíž je v tom, že pro nás ostatní, kteří bychom chtěli Apitte používat je ta dokumentace stále trochu spartánská. Podstatné věci v ní jsou (i díky příkladům v playgroundu!), byť občas je něco trochu záhada.

Rád bych, kdybys uvedl případně i další nejasnosti.

Jakmile na ně narazím, založím issue.

normální Nette aplikaci je uživatelský presenter potomkem Nette\Application\UI\Presenter což zaručí, že má přes context přístupnou metodu getService()

Tohle celé je špatně. Jakékoli služby máš vyžadovat přes konstruktor třídy nebo nastavovat přes settery. Specialitou Nette jsou inject metody a anotace, které dovolují autowiring i jinak, než přes konstruktor (a i ty je vhodné využívat pouze na presentery, proto jsou ve výchozím nastavení nastavené jen pro ně). Tím že získáváš služby přes getService() degraduješ DIC na service locator. Komplikuješ tak výměnu služeb i testování, vytváříš skryté závislosti a skrýváš případné nedostatky v architektuře (nevidíš, že tvá třída pracuje s příliš mnoho závislostmi). Mimo to, context je jen DIC předaný jako služba. V jakékoli jiné službě jej můžeš získat přes konstruktor a využívat stejně jako v presenteru, i když bys to rozhodně neměl dělat.

To jsem si myslel (proto jsem to také formuloval tak jak jsem to napsal). Potíž je v tom, že mi nějak unikalo jak to provést. Nakonec (i díky tvému nakopnutí) jsem pochopil, že nejvíc to bude asi dávat smysl udělat tak jak je to popsáno v dokumentaci DI Nette, tedy něco jako:

za předpokladu config.neon (příp. common.neon) v např. této podobě:

...
services:
	someModel: App\Models\SomeModel(@container)
...

je pak MyController.php takovýto:

<?php

class MyController extends BaseV1Controller {

	/** @var \App\Models\SomeModel */
	protected $someModel;

	public function injectSomeModel(\AppModels\SomeModel $someModel): void
	{
		$this->someModel = $someModel;
	}

	...
}

?>

případně některou jinou, tam popsanou metodou, což můj problém řeší. Píšu to sem hlavně pro ostatní, kteří by řešili stejný problém ;) Trochu jsem doufal, že se mi to podaří vyřešit v common.neon nějakým setupem, nebo něčím takovým, ale v podstatě to takto stačí.

dokumentaci architektury je vložený obrázek, který ale nikam nevede (404)

Ve zdrojové dokumentaci na githubu funguje, založil jsem za tebe issue v repozitáři webu
https://github.com/…hitecture.md
https://github.com/…ite/issues/9

Ok beru, že ve zdrojové dokumentaci ten obrázek funguje. Nicméně než jsem objevil to, že je ještě jedna „zdrojová“ dokumentace, tak jsem byl z té na contributte.org docela frustrovaný…

Ve stejné kapitole dále jsou popisy jednotlivých anotací, nicméně popis jednotlivých položek anotací se omezují na technický popis toho co v nich má nebo nemá být, k čemu se vztahují, ale naprosto chybí popis jejich významu.

Tyhle nedostatky odhaluje právě zpětná vazba, sám o sobě tomu rozumím a přišel mi popis dostačující. Můžeš založit issue, co se nezdá srozumitelné.

Pokusím se. Jak to tak sleduju, strávím nejspíš některý večer zakládáním issues ;)

Nedávno jsem k anotaci dopsal následující větu, imho by to mělo být jasné Not used by Apitte for anything, it may just help you identify, group, etc. your endpoints

Ano tuto větu jsem objevil, čili @Id je tam čistě jen pro potřeby vývojářů, resp. vygenerované dokumentace, případně OpenApi.

Je docela velká škoda, že dokumentace na contributte.org je velmi kusá až útržkovitá, zatímco v README souborech jednotlivých podprojektů je daleko obsáhlejší, prostudovat dané téma je v tak komplexním prostředí poměrně komplikované. Ocenil bych, kdyby se informace z README dostaly do dokumentace na contributte.org.

Můžeš uvést konkrétní případ? Dokumentace na webu se vytváří automaticky z dokumentace na githubu.

Tak například stránka Endpoints a zdrojová stránka Endpoints, které by obě patrně měly obsahovat totéž (aspoň soudě podle struktury a obsahu), leč přinejmenším v části List of annotations jde o poměrně dost odlišné texty. Na druhou stranu nakolik jsem tu dokumentaci procházel tak tohle bylo zatím jediné místo, na které jsem narazil, kde se dokumentace lišila. Pokud narazím na další založím issue.

Velice děkuji za odpovědi, problém mi nakonec vyřešily a doufám, že ti nevadilo odpovídat na místy poněkud „hloupé“ otázky. Je vidět, že za Apitte je docela dost práce (a tím nemyslím jen psaní kódu ;), nicméně jak jsem psal výše pro nás „začátečníky“ (myšleno s touto knihovnou ;) je trochu složitější do toho proniknout.

Marek Bartoš
Nette Blogger | 1172
+
0
-

Tak například stránka Endpoints a zdrojová stránka Endpoints, které by obě patrně měly obsahovat totéž

Už rozumím. Dokumentace na webu je z poslední stable verze (0.6), zatímco na githubu vždy vidíš první master, tedy budoucí v0.7