Používanie AWS Lambda s API Gateway

1. Prehľad

AWS Lambda je výpočtová služba bez servera poskytovaná službou Amazon Web Services.

V dvoch predchádzajúcich článkoch sme diskutovali o tom, ako vytvoriť funkciu AWS Lambda pomocou Javy, a tiež o tom, ako získať prístup k DynamoDB z funkcie Lambda.

V tomto výučbe si povieme niečo o tom ako zverejniť funkciu Lambda ako koncový bod REST pomocou AWS Gateway.

Podrobne sa pozrieme na nasledujúce témy:

  • Základné pojmy a pojmy brány API
  • Integrácia funkcií Lambda s API Gateway pomocou integrácie Lambda Proxy
  • Vytvorenie API, jeho štruktúra a spôsob mapovania zdrojov API na funkcie Lambda
  • Nasadenie a testovanie API

2. Základy a pojmy

Brána API je a plne spravovaná služba, ktorá umožňuje vývojárom vytvárať, publikovať, udržiavať, monitorovať a zabezpečovať API v akomkoľvek rozsahu.

Môžeme implementovať konzistentné a škálovateľné programovacie rozhranie založené na protokole HTTP (označované tiež ako služby RESTful) na prístup k backendovým službám, ako sú funkcie Lambda, ďalšie služby AWS (napr. EC2, S3, DynamoDB) a akékoľvek koncové body HTTP.

Medzi funkcie patria okrem iného:

  • Riadenie dopravy
  • Autorizácia a kontrola prístupu
  • Monitorovanie
  • Správa verzií API
  • Škrtenie požiadaviek na zabránenie útokom

Rovnako ako AWS Lambda, aj API Gateway je automaticky škálovaná a je účtovaná za volanie API.

Podrobné informácie nájdete v oficiálnej dokumentácii.

2.1. Podmienky

Brána API je služba AWS, ktorá podporuje vytváranie, nasadenie a správu rozhrania RESTful programovania aplikácií na vystavenie koncových bodov HTTP koncového bodu, funkcií AWS Lambda a ďalších služieb AWS.

An API brány API je kolekcia zdrojov a metód, ktoré možno integrovať do funkcií Lambda, iných služieb AWS alebo koncových bodov HTTP v backende. API sa skladá zo zdrojov, ktoré tvoria štruktúru API. Každý prostriedok API môže vystaviť jednu alebo viac metód API, ktoré musia mať jedinečné slovesá HTTP.

Ak chcete zverejniť API, musíme vytvoriť Nasadenie API a spájať to s tzv etapa. Fáza je ako momentka z API. Ak znova nasadíme API, môžeme buď aktualizovať existujúcu fázu, alebo vytvoriť novú. Takto sú možné rôzne verzie API súčasne, napríklad a dev etapa, a test a dokonca aj niekoľko produkčných verzií v1, v2, atď.

Integrácia Lambda Proxy je zjednodušená konfigurácia pre integráciu medzi funkciami Lambda a API Gateway.

Brána API odosiela celú požiadavku ako vstup do back-endovej funkcie Lambda. Z hľadiska reakcie transformuje brána API výstup funkcie Lambda späť na frontendovú odpoveď HTTP.

3. Závislosti

Budeme potrebovať rovnaké závislosti ako v článku AWS Lambda Používanie DynamoDB s Java.

Okrem toho potrebujeme aj knižnicu JSON Simple:

 com.googlecode.json-simple json-simple 1.1.1 

4. Vývoj a nasadenie funkcií lambda

V tejto časti budeme vyvíjať a budovať naše funkcie Lambda v Jave, nasadíme ich pomocou AWS Console a vykonáme rýchly test.

Pretože chceme demonštrovať základné možnosti integrácie API Gateway s Lambda, vytvoríme dve funkcie:

  • Funkcia 1: prijíma užitočné zaťaženie z API pomocou metódy PUT
  • Funkcia 2: demonštruje, ako používať parameter cesty HTTP alebo parameter dopytu HTTP pochádzajúci z API

Z hľadiska implementácie si jeden vytvoríme RequestHandler triedy, ktorá má dve metódy - jednu pre každú funkciu.

4.1. Model

Pred implementáciou skutočného vybavovača požiadaviek sa poďme rýchlo pozrieť na náš dátový model:

public class Osoba {private int id; súkromné ​​meno reťazca; public Person (String json) {Gson gson = new Gson (); Žiadosť o osobu = gson.fromJson (json, Person.class); this.id = request.getId (); this.name = request.getName (); } public String toString () {Gson gson = nový GsonBuilder (). setPrettyPrinting (). create (); vrátiť gson.toJson (toto); } // zakladatelia a zakladatelia}

Náš model sa skladá z jedného jednoduchého Osoba triedy, ktorá má dve vlastnosti. Jedinou pozoruhodnou časťou je Osoba (reťazec) konštruktor, ktorý akceptuje reťazec JSON.

4.2. Implementácia triedy RequestHandler

Rovnako ako v článku AWS Lambda With Java, vytvoríme implementáciu RequestStreamHandler rozhranie:

verejná trieda APIDemoHandler implementuje RequestStreamHandler {private static final String DYNAMODB_TABLE_NAME = System.getenv ("TABLE_NAME"); @Override public void handleRequest (InputStream inputStream, OutputStream outputStream, kontextový kontext) hodí IOException {// implementation} public void handleGetByParam (InputStream inputStream, OutputStream outputStream, kontextový kontext) hodí IOException {// implementácia}}

Ako vidíme, RequestStreamHander rozhranie definuje iba jednu metódu, handeRequest (). V každom prípade môžeme definovať ďalšie funkcie v tej istej triede, ako sme to urobili tu. Ďalšou možnosťou by bolo vytvoriť jednu implementáciu RequestStreamHander pre každú funkciu.

V našom konkrétnom prípade sme pre jednoduchosť vybrali prvý. Voľba sa však musí robiť od prípadu k prípadu, berúc do úvahy také faktory ako výkon a udržiavateľnosť kódu.

Tiež sme si prečítali názov našej tabuľky DynamoDB z TABLE_NAME premenná prostredia. Túto premennú definujeme neskôr počas nasadenia.

4.3. Implementácia funkcie 1

V našej prvej funkcii chceme demonštrovať ako získať užitočné zaťaženie (napríklad z požiadavky PUT alebo POST) z brány API:

public void handleRequest (InputStream inputStream, OutputStream outputStream, kontextový kontext) hodí IOException {JSONParser parser = nový JSONParser (); Čítačka BufferedReader = nový BufferedReader (nový InputStreamReader (inputStream)); JSONObject responseJson = nový JSONObject (); AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient (); DynamoDB dynamoDb = nový DynamoDB (klient); try {JSONObject event = (JSONObject) parser.parse (reader); if (event.get ("body")! = null) {Osoba osoba = nová Osoba ((String) event.get ("body")); dynamoDb.getTable (DYNAMODB_TABLE_NAME) .putItem (nový PutItemSpec (). withItem (nová položka (). withNumber ("id", person.getId ()) .withString ("meno", person.getName ()))); } JSONObject responseBody = nový JSONObject (); responseBody.put ("správa", "bola vytvorená nová položka"); Hlavička JSONObjectJson = nový JSONObject (); headerJson.put ("x-custom-header", "moja vlastná hodnota hlavičky"); responseJson.put ("statusCode", 200); responseJson.put ("hlavičky", headerJson); responseJson.put ("body", responseBody.toString ()); } catch (ParseException pex) {responseJson.put ("statusCode", 400); responseJson.put ("výnimka", pex); } Zapisovač OutputStreamWriter = nový OutputStreamWriter (outputStream, "UTF-8"); writer.write (responseJson.toString ()); writer.close (); }

Ako sme už diskutovali, nakonfigurujeme API neskôr tak, aby používalo integráciu Lambda proxy. Očakávame, že brána API odovzdá úplnú požiadavku funkcii Lambda v InputStream parameter.

Všetko, čo musíme urobiť, je vybrať príslušné atribúty z obsiahnutej štruktúry JSON.

Ako vidíme, metóda v zásade pozostáva z troch krokov:

  1. Prebieha načítanie telo objekt z nášho vstupného toku a vytvorenie a Osoba objekt z toho
  2. To sa ukladá Osoba objekt v tabuľke DynamoDB
  3. Budovanie objektu JSON, ktorý môže obsahovať niekoľko atribútov, napríklad a telo pre odpoveď, vlastné hlavičky, ako aj stavový kód HTTP

Jeden bod, ktorý tu stojí za zmienku: API Gateway očakáva telo byť String (pre žiadosť aj odpoveď).

Ako očakávame, že dostaneme String ako telo z API Gateway sme obsadili telo do String a inicializovať naše Osoba objekt:

Osoba osoba = nová Osoba ((String) event.get ("body"));

Odpoveď očakáva aj brána API telo byť String:

responseJson.put ("body", responseBody.toString ());

Táto téma nie je v oficiálnej dokumentácii výslovne uvedená. Ak sa však pozrieme bližšie, vidíme, že atribút body je a String v oboch úryvkoch pre požiadavku aj pre odpoveď.

Výhoda by mala byť jasná: aj keď je JSON formát medzi API Gateway a funkciou Lambda, skutočné telo môže obsahovať obyčajný text, JSON, XML alebo čokoľvek iné. Za správne spracovanie formátu je potom zodpovednosťou funkcie Lambda.

Uvidíme, ako bude telo žiadosti a odpovede vyzerať neskôr, keď otestujeme naše funkcie v konzole AWS.

To isté platí aj pre nasledujúce dve funkcie.

4.4. Implementácia funkcie 2

V druhom kroku to chceme demonštrovať ako používať parameter cesty alebo reťazec dotazu na vyzdvihnutie a Osoba položka z databázy pomocou jej ID:

public void handleGetByParam (InputStream inputStream, OutputStream outputStream, kontextový kontext) vyvolá IOException {JSONParser parser = nový JSONParser (); Čítačka BufferedReader = nový BufferedReader (nový InputStreamReader (inputStream)); JSONObject responseJson = nový JSONObject (); AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient (); DynamoDB dynamoDb = nový DynamoDB (klient); Výsledok položky = null; try {JSONObject event = (JSONObject) parser.parse (reader); JSONObject responseBody = nový JSONObject (); if (event.get ("pathParameters")! = null) {JSONObject pps = (JSONObject) event.get ("pathParameters"); if (pps.get ("id")! = null) {int id = Integer.parseInt ((String) pps.get ("id")); result = dynamoDb.getTable (DYNAMODB_TABLE_NAME) .getItem ("id", id); }} else if (event.get ("queryStringParameters")! = null) {JSONObject qps = (JSONObject) event.get ("queryStringParameters"); if (qps.get ("id")! = null) {int id = Integer.parseInt ((String) qps.get ("id")); result = dynamoDb.getTable (DYNAMODB_TABLE_NAME) .getItem ("id", id); }} if (result! = null) {Person person = new Person (result.toJSON ()); responseBody.put ("Osoba", osoba); responseJson.put ("statusCode", 200); } else {responseBody.put ("správa", "nenašla sa žiadna položka"); responseJson.put ("statusCode", 404); } Hlavička JSONObjectJson = nový JSONObject (); headerJson.put ("x-custom-header", "moja vlastná hodnota hlavičky"); responseJson.put ("hlavičky", headerJson); responseJson.put ("body", responseBody.toString ()); } catch (ParseException pex) {responseJson.put ("statusCode", 400); responseJson.put ("výnimka", pex); } Zapisovač OutputStreamWriter = nový OutputStreamWriter (outputStream, "UTF-8"); writer.write (responseJson.toString ()); writer.close (); }

Opäť sú relevantné tri kroky:

  1. Skontrolujeme, či a pathParameters alebo an queryStringParameters pole s id atribút sú prítomné.
  2. Ak pravda, hodnotu príslušnosti používame na vyžiadanie a Osoba položka s týmto ID z databázy.
  3. Do odpovede pridáme JSON reprezentáciu prijatej položky.

Oficiálna dokumentácia poskytuje podrobnejšie vysvetlenie vstupného a výstupného formátu pre integráciu servera Proxy.

4.5. Stavebný zákon

Opäť môžeme náš kód jednoducho zostaviť pomocou Mavenu:

mvn čisté balenie odtieň: odtieň

Súbor JAR sa vytvorí pod cieľ priečinok.

4.6. Vytvorenie tabuľky DynamoDB

Tabuľku môžeme vytvoriť, ako je vysvetlené v AWS Lambda, pomocou DynamoDB s Java.

Vyberme si Osoba ako názov tabuľky, id ako názov primárneho kľúča a Číslo ako typ primárneho kľúča.

4.7. Nasadzovanie kódu prostredníctvom konzoly AWS

Po zostavení nášho kódu a vytvorení tabuľky môžeme teraz vytvárať funkcie a nahrávať kód.

To je možné dosiahnuť opakovaním krokov 1 - 5 z článku AWS Lambda with Java, jedenkrát pre každú z našich dvoch metód.

Použime nasledujúce názvy funkcií:

  • StorePersonFunction pre handleRequest metóda (funkcia 1)
  • Funkcia GetPersonByHTTPParamFunction pre handleGetByParam metóda (funkcia 2)

Musíme tiež definovať premennú prostredia TABLE_NAME s hodnotou „Osoba“.

4.8. Testovanie funkcií

Pred pokračovaním v aktuálnej časti API Gateway môžeme spustiť rýchly test v konzole AWS, len aby sme skontrolovali, či naše funkcie Lambda fungujú správne a či dokážu spracovať formát integrácie Proxy.

Testovanie funkcie Lambda z konzoly AWS funguje podľa popisu v článku AWS Lambda s Java.

Avšak pri vytváraní testovacej udalosti musíme brať do úvahy špeciálny formát integrácie proxy, ktoré naše funkcie očakávajú. Môžeme použiť buď API Gateway AWS Proxy šablónu a prispôsobte ju svojim potrebám, alebo môžeme skopírovať a prilepiť nasledujúce udalosti:

Pre StorePersonFunction, mali by sme použiť toto:

{"body": "{\" id \ ": 1, \" meno \ ": \" John Doe \ "}"}

Ako už bolo uvedené, telo musí mať typ String, aj keď obsahuje štruktúru JSON. Dôvod je ten, že brána API bude odosielať svoje požiadavky v rovnakom formáte.

Mali by ste vrátiť nasledujúcu odpoveď:

{"isBase64Encoded": false, "headers": {"x-custom-header": "moja vlastná hodnota hlavičky"}, "body": "{\" správa \ ": \" Bola vytvorená nová položka \ "}", "statusCode": 200}

Tu vidíme, že telo našej odpovede je a String, aj keď obsahuje štruktúru JSON.

Pozrime sa na vstup pre Funkcia GetPersonByHTTPParamFunction.

Na testovanie funkčnosti parametra cesty by vstup vyzeral takto:

{"pathParameters": {"id": "1"}}

A vstup na odoslanie parametra reťazca dotazu by bol:

{"queryStringParameters": {"id": "1"}}

Ako odpoveď by sme mali dostať pre oba prípady nasledujúce:

{"headers": {"x-custom-header": "my custom header value"}, "body": "{\" Person \ ": {\ n \" id \ ": 88, \ n \" meno \ ": \" John Doe \ "\ n}}", "statusCode": 200}

Opäť platí, že telo je a String.

5. Vytvorenie a testovanie API

Potom, čo sme vytvorili a nasadili funkcie Lambda v predchádzajúcej časti, teraz môžeme vytvoriť skutočné API pomocou konzoly AWS.

Pozrime sa na základný pracovný postup:

  1. Vytvorte API v našom účte AWS.
  2. Pridajte prostriedok do hierarchie zdrojov rozhrania API.
  3. Vytvorte jednu alebo viac metód pre zdroj.
  4. Nastavte integráciu medzi metódou a príslušnou funkciou Lambda.

Zopakujeme kroky 2-4 pre každú z našich dvoch funkcií v nasledujúcich častiach.

5.1. Vytváranie API

Na vytvorenie API budeme musieť:

  1. Prihláste sa do konzoly API Gateway na adrese //console.aws.amazon.com/apigateway
  2. Kliknite na „Začíname“ a potom vyberte „Nové API“
  3. Zadajte názov nášho API (TestAPI) a potvrďte kliknutím na „Vytvoriť API“

Po vytvorení API môžeme teraz vytvoriť štruktúru API a prepojiť ju s našimi funkciami Lambda.

5.2. Štruktúra API pre funkciu 1

Nasledujúce kroky sú nevyhnutné pre náš StorePersonFunction:

  1. V strome „Zdroje“ vyberte položku nadradeného zdroja a potom v rozbaľovacej ponuke „Akcie“ vyberte možnosť „Vytvoriť zdroj“. Potom musíme na table „Nový zdroj dieťaťa“ urobiť nasledovné:
    • Do vstupného textového poľa „Názov zdroja“ zadajte „Osoby“ ako meno
    • Vo vstupnom textovom poli „Cesta zdroja“ ponechajte predvolenú hodnotu
    • Vyberte možnosť „Vytvoriť zdroj“
  2. Vyberte zdroj, ktorý ste práve vytvorili, v rozbaľovacej ponuke „Akcie“ vyberte možnosť „Vytvoriť metódu“ a vykonajte nasledujúce kroky:
    • Z rozbaľovacieho zoznamu Metóda HTTP vyberte PUT a výberom ikony vyberte ikonu začiarknutia
    • Ako typ integrácie nechajte „Lambda Function“ a vyberte možnosť „Použiť integráciu Lambda Proxy“
    • Vyberte si región z „Lambda Region“, kde sme predtým nasadili naše funkcie Lambda
    • Typ „StorePersonFunction“ vo funkcii „Lambda“
  3. Vyberte „Uložiť“ a po zobrazení výzvy „Pridať povolenie k funkcii Lambda“ potvrďte tlačidlom „OK“

5.3. Štruktúra API pre funkciu 2 - parametre cesty

Kroky pre naše parametre načítania cesty sú podobné:

  1. Vyber /osôb pod stromom „Zdroje“ a potom v rozbaľovacej ponuke „Akcie“ vyberte možnosť „Vytvoriť zdroj“. Potom musíme na table Nové zdroje dieťaťa urobiť nasledovné:
    • Typ „Osoba“ ako názov vo vstupnom textovom poli „Názov zdroja“
    • Zmeňte vstupné textové pole „Cesta zdroja“ na „{Id}“
    • Vyberte možnosť „Vytvoriť zdroj“
  2. Vyberte zdroj, ktorý ste práve vytvorili, v rozbaľovacej ponuke „Akcie“ vyberte možnosť „Vytvoriť metódu“ a vykonajte nasledujúce kroky:
    • Z rozbaľovacieho zoznamu Metóda HTTP vyberte GET a výber uložte kliknutím na ikonu začiarknutia
    • Ako typ integrácie nechajte „Lambda Function“ a vyberte možnosť „Použiť integráciu Lambda Proxy“
    • Vyberte si región z „Lambda Region“, kde sme predtým nasadili naše funkcie Lambda
    • Typ „GetPersonByHTTPParamFunction“ vo funkcii „Lambda“
  3. Vyberte „Uložiť“ a po zobrazení výzvy „Pridať povolenie k funkcii Lambda“ potvrďte tlačidlom „OK“

Poznámka: je dôležité tu nastaviť parameter „Cesta zdroja“ na „{Id}“, ako náš GetPersonByPathParamFunction očakáva, že tento parameter bude pomenovaný presne takto.

5.4. Štruktúra API pre funkciu 2 - parametre reťazca dotazu

Kroky na príjem parametrov reťazca dotazu sú trochu odlišné nemusíme vytvárať zdroj, ale namiesto toho musíme vytvárať parameter dotazu pre id parameter:

  1. Vyber / osôb v strome „Zdroje“ vyberte položku zdroja, z rozbaľovacej ponuky „Akcie“ vyberte možnosť „Vytvoriť metódu“ a vykonajte nasledujúce kroky:
    • Z rozbaľovacieho zoznamu Metóda HTTP vyberte GET a výber uložte výberom ikony začiarknutia
    • Ako typ integrácie nechajte „Lambda Function“ a vyberte možnosť „Použiť integráciu Lambda Proxy“
    • Vyberte si región z „Lambda Region“, kde sme predtým nasadili naše funkcie Lambda
    • Typ „GetPersonByHTTPParamFunction“ v časti „Lambda funkcia“.
  2. Vyberte „Uložiť“ a po zobrazení výzvy „Pridať povolenie k funkcii Lambda“ potvrďte tlačidlom „OK“
  3. Vyberte možnosť „Žiadosť o metódu“ vpravo a vykonajte nasledujúce kroky:
    • Rozbaľte zoznam Parametre reťazca dotazu URL
    • Kliknite na „Pridať reťazec dopytu“
    • Typ „Id“ v poli s menom a uložte ikonu začiarknutia
    • Začiarknite políčko „Vyžadované“
    • Kliknite na symbol pera vedľa položky „Vyžiadať validátor“ v hornej časti panela, vyberte „Overiť parametre reťazca dotazu a hlavičky“ a kliknite na ikonu začiarknutia

Poznámka: Je dôležité nastaviť parameter „Query String“ na „Id“, ako náš Funkcia GetPersonByHTTPParamFunction očakáva, že tento parameter bude pomenovaný presne takto.

5.5. Testovanie API

Naše API je teraz pripravené, ale zatiaľ nie je verejné. Predtým, ako ho zverejníme, chceme najskôr spustiť rýchly test z konzoly.

Z tohto dôvodu môžeme v strome „Zdroje“ zvoliť príslušnú metódu, ktorá sa má testovať, a kliknúť na tlačidlo „Testovať“. Na nasledujúcej obrazovke môžeme zadať náš vstup, pretože by sme ho odoslali s klientom prostredníctvom protokolu HTTP.

Pre StorePersonFunction, musíme do poľa „Žiadosť tela“ napísať nasledujúcu štruktúru:

{"id": 2, "name": "Jane Doe"}

Pre Funkcia GetPersonByHTTPParamFunction s parametrami cesty musíme písať 2 ako hodnotu do poľa „{id}“ v časti „Cesta“.

Pre Funkcia GetPersonByHTTPParamFunction s parametrami reťazca dotazu musíme písať id = 2 ako hodnota do poľa „{osôb}“ v časti „Dotazové reťazce“.

5.6. Nasadenie API

Naše API nebolo doteraz verejné a bolo tak dostupné iba z AWS Console.

Ako už bolo uvedené, keď nasadíme API, musíme ho spojiť s fázou, ktorá je ako momentka z API. Ak znova nasadíme API, môžeme buď aktualizovať existujúcu fázu, alebo vytvoriť novú.

Pozrime sa, ako bude vyzerať schéma URL pre naše API:

//{restapi-id}.execute-api.{region}.amazonaws.com/{stageName}

Pre nasadenie sú potrebné nasledujúce kroky:

  1. Na navigačnom paneli „API“ vyberte konkrétne API
  2. Na navigačnej table zdrojov vyberte možnosť „Akcie“ a v rozbaľovacej ponuke „Akcie“ vyberte možnosť „Nasadiť API“
  3. V rozbaľovacej ponuke „Fáza nasadenia“ vyberte „[Nová etapa]“ a zadajte „Test“ v časti „Názov scény“ a voliteľne poskytnúť popis fázy a nasadenia
  4. Spustite nasadenie výberom možnosti „Nasadiť“

Po poslednom kroku poskytne konzola koreňovú adresu URL rozhrania API, napríklad //0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test.

5.7. Vyvolanie koncového bodu

Keďže API je teraz verejné, môžeme to nazvať pomocou ktoréhokoľvek HTTP klienta, ktorého chceme.

S curl, by hovory vyzerali nasledovne.

StorePersonFunction:

curl -X PUT '//0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons' \ -H 'content-type: application / json' \ -d '{"id": 3, "name": "Richard Roe"} '

Funkcia GetPersonByHTTPParamFunction pre parametre cesty:

curl -X ZÍSKAŤ '//0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons/3' \ -H 'content-type: application / json'

Funkcia GetPersonByHTTPParamFunction pre parametre reťazca dopytu:

curl -X ZÍSKAJTE '//0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons?id=3' \ -H 'content-type: application / json'

6. Záver

V tomto článku sme sa pozreli na to, ako sprístupniť funkcie AWS Lambda ako koncové body REST pomocou brány AWS API.

Preskúmali sme základné pojmy a terminológiu API Gateway a naučili sme sa, ako integrovať funkcie Lambda pomocou integrácie Lambda Proxy.

Nakoniec sme videli, ako vytvoriť, nasadiť a otestovať API.

Ako obvykle je všetok kód tohto článku k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found