{"id":71378,"date":"2020-02-25T20:45:02","date_gmt":"2020-02-25T17:45:02","guid":{"rendered":"https:\/\/prohoster.info\/blog\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij"},"modified":"2020-03-03T16:14:21","modified_gmt":"2020-03-03T13:14:21","slug":"openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","title":{"rendered":"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/62eb484051c7963c96842393884ddd98.jpg\" style=\"display:block;margin: 0 auto;\" \/><em>Ponownie publikujemy zapis wyst\u0105pienia z konferencji <noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/\">HighLoad++<\/a><\/noindex> 2016 roku, kt\u00f3ra odby\u0142a si\u0119 w podmoskiewskim Skolkowie 7\u20138 listopada zesz\u0142ego roku. <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/post\/315726\/\">W\u0142adimir Protasow<\/a><\/noindex> opowiada, jak rozszerzy\u0107 funkcjonalno\u015b\u0107 NGINX za pomoc\u0105 OpenResty i Lua.<\/em><\/p>\n<p>Cze\u015b\u0107 wszystkim, nazywam si\u0119 W\u0142adimir Protasow, pracuj\u0119 w Parallels. Opowiem troch\u0119 o sobie. Trzy czwarte swojego \u017cycia po\u015bwi\u0119ci\u0142em na pisanie kodu. Zosta\u0142em programist\u0105 do szpiku ko\u015bci: czasami we \u015bnie widz\u0119 kod. Jedn\u0105 czwart\u0105 \u017cycia sp\u0119dzi\u0142em na komercyjnej rozw\u00f3j, pisz\u0105c kod, kt\u00f3ry trafia prosto do produkcji. Kod, kt\u00f3rego niekt\u00f3rzy z Was u\u017cywaj\u0105, ale nie zdaj\u0105 sobie z tego sprawy.<\/p>\n<p>Aby\u015bcie zrozumieli, jak \u017ale by\u0142o. Kiedy by\u0142em m\u0142odym junior developerem, przyszed\u0142em, a dostano mi takie dwutera, terabajtowe bazy. Teraz wszyscy m\u00f3wi\u0105 o highload. Chodzi\u0142em na konferencje, pyta\u0142em: \u201eLudzie, opowiedzcie, macie big data, wszystko \u015bwietnie? Ile macie tam baz?\u201d Odpowiadali: \u201eMamy 100 gigabajt\u00f3w!\u201d Ja m\u00f3wi\u0142em: \u201e\u015awietnie, 100 gigabajt\u00f3w!\u201d A my\u015bla\u0142em w sobie, jakby tu zachowa\u0107 pokerow\u0105 twarz. My\u015blisz, \u017ce tak, ludzie s\u0105 super, a potem wracasz i zmagasz si\u0119 z tymi wielotera, terabajtowymi bazami. I to b\u0119d\u0105c juniorem. Wyobra\u017cacie sobie, jaki to cios?<\/p>\n<p>Znam ponad 20 j\u0119zyk\u00f3w programowania. To co\u015b, co musia\u0142em ogarn\u0105\u0107 w trakcie pracy. Daje si\u0119 kod w Erlangu, w C, w C++, w Luie, w Pythonie, w Rubym, w czym\u015b jeszcze, i musisz ca\u0142y ten kod robi\u0107. W sumie tak to wysz\u0142o. Dok\u0142adnej liczby nie uda\u0142o si\u0119 policzy\u0107, ale gdzie\u015b na 20 w liczbie si\u0119 zgubi\u0142em.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nPoniewa\u017c wszyscy obecni wiedz\u0105, czym jest Parallels i czym si\u0119 zajmujemy, nie b\u0119d\u0119 m\u00f3wi\u0142 o tym, jacy jeste\u015bmy wspaniali i co robimy. Powiem tylko, \u017ce mamy 13 biur na ca\u0142ym \u015bwiecie, ponad 300 pracownik\u00f3w, a rozw\u00f3j odbywa si\u0119 w Moskwie, Tallinie i na Malcie. W razie ch\u0119ci mo\u017cna r\u00f3wnie\u017c przenie\u015b\u0107 si\u0119 na Malt\u0119, je\u015bli zima jest zimna i trzeba si\u0119 ogrza\u0107.<\/p>\n<p>Nasz dzia\u0142 konkretnie pisze w Pythonie 2. Zajmujemy si\u0119 biznesem i nie mamy czasu na wdra\u017canie modnych technologii, dlatego cierpimy. Mamy Django, poniewa\u017c ma wszystko, a nadmiarowe rzecz po prostu usun\u0119li\u015bmy. U\u017cywamy r\u00f3wnie\u017c MySQL, Redis i NGINX. Mamy wiele innych fajnych rozwi\u0105za\u0144. Mamy MongoDB, mamy kr\u00f3liki biegaj\u0105ce, mamy wszystko, co tylko mo\u017cna sobie wyobrazi\u0107 \u2013 ale to nie jest moje, i tym si\u0119 nie zajmuj\u0119.<\/p>\n<h1>OpenResty<\/h1>\n<p>\nOpowiedzia\u0142em o sobie. Sprawd\u017amy, o czym b\u0119d\u0119 dzi\u015b m\u00f3wi\u0142:<\/p>\n<ul>\n<li>Czym jest OpenResty i jak go u\u017cywa\u0107?<\/li>\n<li>Po co wynajdywa\u0107 jeszcze jeden rower, skoro mamy Pythona, NodeJS, PHP, Go i inne fajne technologie, kt\u00f3rymi wszyscy s\u0105 zadowoleni?<\/li>\n<li>A teraz kilka przyk\u0142ad\u00f3w z \u017cycia. Musia\u0142em znacznie skr\u00f3ci\u0107 moj\u0105 prezentacj\u0119, poniewa\u017c mia\u0142em a\u017c 3,5 godziny materia\u0142u, wi\u0119c przyk\u0142ad\u00f3w b\u0119dzie niewiele.<\/li>\n<\/ul>\n<p>\nOpenResty to NGINX. Dzi\u0119ki niemu mamy pe\u0142noprawny serwer WWW, kt\u00f3ry jest dobrze napisany i dzia\u0142a szybko. My\u015bl\u0119, \u017ce wi\u0119kszo\u015b\u0107 z nas u\u017cywa NGINX w produkcji. Wszyscy wiecie, \u017ce jest szybki i \u015bwietny. W nim zrobiono doskona\u0142e, synchroniczne wej\u015bcie\/wyj\u015bcie, wi\u0119c nie musimy nic wymy\u015bla\u0107 na nowo, jak w Pythonie, gdzie zrobiono gevent. Gevent jest rewelacyjny, ale je\u015bli napiszesz kod w C i co\u015b p\u00f3jdzie nie tak, to z gevent zwariujesz przy debuggowaniu. Mia\u0142em taki przypadek: zaj\u0119\u0142o mi to dwa dni, aby dowiedzie\u0107 si\u0119, co posz\u0142o nie tak. Gdyby nikt przedtem nie pogrzeba\u0142 przez kilka tygodni, nie znalaz\u0142 problemu, nie napisa\u0142 w Internecie i Google tego nie znalaz\u0142, to by\u015bmy ca\u0142kowicie oszaleli.<\/p>\n<p>W NGINX ju\u017c wdro\u017cono caching oraz tre\u015bci statyczne. Nie musisz si\u0119 martwi\u0107, jak to zrobi\u0107 poprawnie, aby nie spowolni\u0107 dzia\u0142ania, ani nie straci\u0107 gdzie\u015b kontroler\u00f3w. Nginx jest \u0142atwy w wdro\u017ceniu, nie musisz si\u0119 zastanawia\u0107, co wybra\u0107 \u2014 WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx zosta\u0142 zainstalowany, administracja przej\u0119\u0142a, oni wiedz\u0105, jak z tym pracowa\u0107. Nginx strukturalnie przetwarza zapytania. Opowiem o tym troch\u0119 p\u00f3\u017aniej. Kr\u00f3tko m\u00f3wi\u0105c, ma faz\u0119, kiedy tylko przyjmuje zapytanie, kiedy je przetwarza, oraz kiedy zwraca tre\u015b\u0107 u\u017cytkownikowi.<\/p>\n<p>Nginx jest \u015bwietny, ale ma jeden problem: nie jest wystarczaj\u0105co elastyczny, mimo wielu \u015bwietnych funkcji, kt\u00f3re tw\u00f3rcy wprowadzili do konfiguracji. Tej mocy brakuje. Dlatego kilka lat temu, chyba osiem, tw\u00f3rcy z Taobao zintegrowali Lua. Co to daje?<\/p>\n<ul>\n<li><strong>Rozmiar<\/strong>. Jest ma\u0142y. LuaJIT zu\u017cywa oko\u0142o 100-200 kilobajt\u00f3w dodatkowej pami\u0119ci i minimalny dodatkowy narzut na wydajno\u015b\u0107.<\/li>\n<li><strong>Pr\u0119dko\u015b\u0107<\/strong>. Interpreter LuaJIT w wielu przypadkach zbli\u017ca si\u0119 do C, w niekt\u00f3rych sytuacjach przegrywa z Jav\u0105, a w innych j\u0105 wyprzedza. Przez pewien czas uwa\u017cany by\u0142 za najnowocze\u015bniejszy, najlepszy kompilator JIT. Teraz s\u0105 bardziej zaawansowane, ale s\u0105 bardzo ci\u0119\u017ckie, na przyk\u0142ad V8. Niekt\u00f3re interpretery JavaScript i hotspot Javy w niekt\u00f3rych punktach s\u0105 szybsze, ale w innych miejscach wci\u0105\u017c przegrywaj\u0105.<\/li>\n<li><strong>\u0141atwo\u015b\u0107 w nauce<\/strong>. Je\u015bli na przyk\u0142ad masz baz\u0119 kodu w Perl, a nie jeste\u015b Bookingiem, nie znajdziesz programist\u00f3w Perl. Poniewa\u017c ich nie ma, wszyscy zostali zabrani, a nauka trwa d\u0142ugo i jest skomplikowana. Je\u015bli chcesz programist\u00f3w w czym\u015b innym, by\u0107 mo\u017ce tak\u017ce musisz ich przeszkoli\u0107 lub znale\u017a\u0107. W przypadku Lua jest to proste. Lua mog\u0105 opanowa\u0107 wszyscy juniorzy w trzy dni. Mi zaj\u0119\u0142o to oko\u0142o dw\u00f3ch godzin, aby si\u0119 zorientowa\u0107. Po dw\u00f3ch godzinach ju\u017c pisa\u0142em kod w produkcji. Gdzie\u015b po tygodniu trafi\u0142 prosto do produkcji.<\/li>\n<\/ul>\n<p>\nW rezultacie wygl\u0105da to tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/1e6c253c5436fdc894f8be7999799cb0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nJest tu wiele rzeczy. W OpenResty zebrano mn\u00f3stwo modu\u0142\u00f3w, zar\u00f3wno lua, jak i z silnika. I masz wszystko gotowe \u2013 wdro\u017cone i dzia\u0142a.<\/p>\n<h1>Przyk\u0142ady<\/h1>\n<p>\nDo\u015b\u0107 sentymentalnych rozmy\u015bla\u0144, przechodzimy do kodu. Oto ma\u0142y Hello World:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/bbd056b72c71b193b0f06dd3248f5381.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCo tu mamy? To lokalizacja z NGINX. Nie przejmujemy si\u0119, nie piszemy w\u0142asnego routingu, nie korzystamy z gotowego \u2014 mamy to ju\u017c w NGINX, \u017cyjemy dobrze i leniwie.<\/p>\n<p><code>content_by_lua_block<\/code> \u2013 to blok, kt\u00f3ry m\u00f3wi, \u017ce dostarczamy tre\u015b\u0107 za pomoc\u0105 skryptu Lua. Bierzemy zmienn\u0105 z NGINX <code>remote_addr<\/code> i podstawiamy j\u0105 w <code>string.format<\/code>. To to samo, co <code>sprintf<\/code>, tylko na Lua, tylko poprawnie. I wysy\u0142amy do klienta.<\/p>\n<p>W rezultacie b\u0119dzie to wygl\u0105da\u0107 tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/9f1aaf6625f1fe5904b1e8a568fac76d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nAle wr\u00f3\u0107my do rzeczywisto\u015bci. W produkcji nikt nie wypuszcza Hello World. Nasza aplikacja zazwyczaj \u0142\u0105czy si\u0119 z baz\u0105 danych lub gdzie indziej i przez wi\u0119kszo\u015b\u0107 czasu czeka na odpowied\u017a.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/485f713c0284e16b0817500c8606c104.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPo prostu siedzi i czeka. To nie jest zbyt dobre. Kiedy przychodzi 100 000 u\u017cytkownik\u00f3w, mamy du\u017ce problemy. Dlatego stw\u00f3rzmy prost\u0105 aplikacj\u0119 jako przyk\u0142ad. B\u0119dziemy szuka\u0107 obrazk\u00f3w, na przyk\u0142ad kot\u00f3w. Tylko nie b\u0119dziemy szuka\u0107 bez sensu, rozszerzymy s\u0142owa kluczowe i je\u015bli u\u017cytkownik poszuka\u0142 'koci\u0105t', znajdziemy mu koty, puchatki i inne. Na pocz\u0105tek musimy uzyska\u0107 dane \u017c\u0105dania na backendzie. Wygl\u0105da to tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/a2134f86f15764745ae8330f63185367.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDwie linijki pozwalaj\u0105 na pobranie parametr\u00f3w GET, bez \u017cadnych trudno\u015bci. Nast\u0119pnie z bazy danych, przy u\u017cyciu tabeli z kluczowymi s\u0142owami i rozszerzeniem, pobieramy te informacje za pomoc\u0105 standardowego zapytania SQL. To proste. Wygl\u0105da to tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/4543685dc907f30bba2a079a0fadad2c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPod\u0142\u0105czamy bibliotek\u0119 <code>resty.mysql<\/code>, kt\u00f3ra ju\u017c jest w naszym zestawie. Nie musimy nic instalowa\u0107, wszystko jest gotowe. Okre\u015blamy, jak si\u0119 po\u0142\u0105czy\u0107, i wykonujemy zapytanie SQL:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/2234b3a5b2e1d8efafec00a49f1a13b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nTutaj jest troch\u0119 strasznie, ale wszystko dzia\u0142a. Liczba 10 to limit. Pobieramy 10 rekord\u00f3w, jeste\u015bmy leniwi i nie chcemy pokazywa\u0107 wi\u0119cej. Zapomnia\u0142em o limicie w SQL.<\/p>\n<p>Nast\u0119pnie znajdujemy obrazy na podstawie wszystkich zapyta\u0144. Zbieramy zestaw zapyta\u0144 i wype\u0142niamy tabel\u0119 Lua, kt\u00f3ra nazywa si\u0119 <code>reqs<\/code>, i wykonujemy <code>ngx.location.capture_multi<\/code>.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/c18171845b3bd3872c4a7a7feae0d4bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWszystkie te zapytania id\u0105 r\u00f3wnolegle, a my otrzymujemy odpowiedzi. Czas wykonania r\u00f3wny jest czasowi odpowiedzi najwolniejszego. Je\u015bli wszystkie odpowiedzi przychodz\u0105 w ci\u0105gu 50 milisekund i wys\u0142ali\u015bmy sto zapyta\u0144, to otrzymamy odpowied\u017a w ci\u0105gu 50 milisekund.<\/p>\n<p>Poniewa\u017c jeste\u015bmy leniwi i nie chcemy pisa\u0107 obs\u0142ugi HTTP i cachingu, zmusimy NGINX, aby wszystko robi\u0142 za nas. Jak widzieli\u015bcie, tam by\u0142o zapytanie do <code>url\/fetch<\/code>, oto ono:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/ef8fcc6905b2860a7f214c41251582a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nWykonujemy proste <code>proxy_pass<\/code>, wskazujemy, gdzie zbuforowa\u0107, jak to zrobi\u0107, i wszystko dzia\u0142a.<\/p>\n<p>Ale to nie wystarczy, musimy jeszcze zwr\u00f3ci\u0107 dane u\u017cytkownikowi. Najprostszy spos\u00f3b to zserializowa\u0107 wszystko do JSON, \u0142atwo, w dw\u00f3ch linijkach. Zwracamy Content-Type, zwracamy JSON.<\/p>\n<p>Ale jest jeden problem: u\u017cytkownik nie chce czyta\u0107 JSON. Musimy zaanga\u017cowa\u0107 frontendowc\u00f3w. Czasami nie mamy na to ochoty na pocz\u0105tku. A SEO-wcy powiedz\u0105, \u017ce je\u015bli szukamy obrazk\u00f3w, to im to oboj\u0119tne. Ale je\u015bli dajemy im jaki\u015b content, powiedz\u0105, \u017ce nasze tre\u015bci nie s\u0105 indeksowane przez wyszukiwarki.<\/p>\n<p>Co z tym zrobi\u0107? Oczywi\u015bcie, b\u0119dziemy zwraca\u0107 u\u017cytkownikowi HTML. R\u0119czne generowanie nie jest cool, dlatego chcemy u\u017cywa\u0107 szablon\u00f3w. Do tego jest biblioteka <code>lua-resty-template<\/code>.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/66a6cffc402575d286cb00d138dc201a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNa pewno widzia\u0142e\u015b trzy straszne litery OPM. OpenResty ma w\u0142asnego mened\u017cera pakiet\u00f3w, przez kt\u00f3rego mo\u017cna zainstalowa\u0107 wiele r\u00f3\u017cnych modu\u0142\u00f3w, w tym <code>lua-resty-template<\/code>. To prosty silnik szablon\u00f3w, bliski Django templates. Mo\u017cna tam napisa\u0107 kod i wstawi\u0107 zmienne.<\/p>\n<p>W rezultacie wszystko b\u0119dzie wygl\u0105da\u0107 mniej wi\u0119cej tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/b54497e4f1ab5a80183dc49c172a7f15.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nZebrali\u015bmy dane i ponownie renderowali\u015bmy szablon w dw\u00f3ch linijkach. U\u017cytkownik jest zadowolony, otrzyma\u0142 kotki. Poniewa\u017c rozszerzyli\u015bmy zapytanie, dostaje r\u00f3wnie\u017c morskiego lwi\u0105tka. Kto wie, mo\u017ce akurat go szuka\u0142, ale nie m\u00f3g\u0142 poprawnie sformu\u0142owa\u0107 swojego zapytania.<\/p>\n<p>Wszystko \u015bwietnie, ale jeste\u015bmy w fazie dewelopmentu i nie chcemy, by u\u017cytkownicy to widzieli. Zr\u00f3bmy autoryzacj\u0119. Aby to zrobi\u0107, przyjrzyjmy si\u0119, jak NGINX przetwarza zapytanie w kontek\u015bcie OpenResty:<\/p>\n<ul>\n<li>Pierwsza faza\u00a0\u2014 <strong>access<\/strong>, gdy u\u017cytkownik w\u0142a\u015bnie wszed\u0142, a my go analizujemy po nag\u0142\u00f3wkach, po adresie IP oraz innych danych. Mo\u017cna go od razu zablokowa\u0107, je\u015bli nam si\u0119 nie podoba. Mo\u017cna to wykorzysta\u0107 do autoryzacji lub, je\u015bli przychodzi zbyt wiele zapyta\u0144, \u0142atwo je odrzuci\u0107 na tym etapie.<\/li>\n<li><strong>rewrite<\/strong>. Przepisywanie danych zapytania.<\/li>\n<li><strong>content<\/strong>. Oferujemy zawarto\u015b\u0107 u\u017cytkownikowi.<\/li>\n<li><strong>headers filter<\/strong>. Zmieniamy nag\u0142\u00f3wki odpowiedzi. Je\u015bli u\u017cyli\u015bmy <code>proxy_pass<\/code>, mo\u017cemy zmieni\u0107 niekt\u00f3re nag\u0142\u00f3wki przed oddaniem ich u\u017cytkownikowi.<\/li>\n<li><strong>body filter<\/strong>. Mo\u017cemy zmieni\u0107 cia\u0142o.<\/li>\n<li><strong>log<\/strong>\u00a0\u2014 logowanie. Mo\u017cna zapisywa\u0107 logi w elasticsearch bez dodatkowej warstwy.<\/li>\n<\/ul>\n<p>\nNasza autoryzacja b\u0119dzie wygl\u0105da\u0107 mniej wi\u0119cej tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/f6c16665b75ce0fa0ee69e07ab6a4a61.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDodamy to do <code>lokacji<\/code>, kt\u00f3r\u0105 wcze\u015bniej opisali\u015bmy, i umie\u015bcimy tam taki kod:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/126d8411c92afa92f3c4f5b9791b3e9c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nSprawdzamy, czy mamy token cookie. Je\u015bli nie, to przekierowujemy na autoryzacj\u0119. U\u017cytkownicy s\u0105 sprytni i mog\u0105 si\u0119 domy\u015bli\u0107, \u017ce musz\u0105 ustawi\u0107 token cookie. Dlatego dodatkowo umie\u015bcimy go w Redis:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/b876372412d648885c2f7d53e712a85b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nKod do pracy z Redis jest bardzo prosty i nie r\u00f3\u017cni si\u0119 od innych j\u0119zyk\u00f3w. Ca\u0142a operacja we\/wy, zar\u00f3wno tam, jak i tutaj, jest nieblokuj\u0105ca. Je\u015bli piszesz kod synchronny, to dzia\u0142a asynchronicznie. Troch\u0119 jak z gevent, tylko zrobione dobrze.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/74066c9c750c718f368617faacbe0acc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZr\u00f3bmy zatem sam\u0105 autoryzacj\u0119:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/0b3b486ca3c417716ebdaac189bfdcbf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nM\u00f3wimy, \u017ce musimy odczyta\u0107 cia\u0142o zapytania. Odbieramy argumenty POST, sprawdzamy, czy login i has\u0142o s\u0105 poprawne. Je\u015bli s\u0105 b\u0142\u0119dne, to przekierowujemy na autoryzacj\u0119. A je\u015bli poprawne, to zapisujemy token w Redis:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/bcf470d84791b6d1d01152d5ad511dbd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nNie zapominamy ustawi\u0107 cookie, to tak\u017ce robimy w dw\u00f3ch linijkach:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/efe06a113de28bacd14b26d6bb62a037.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPrzyk\u0142ad prosty, teoretyczny. Oczywi\u015bcie nie zamierzamy tworzy\u0107 us\u0142ugi, kt\u00f3ra pokazuje ludziom kotki. Cho\u0107 kto wie. Dlatego przejd\u017amy do tego, co mo\u017cna zrobi\u0107 w produkcji.<\/p>\n<ul>\n<li><strong>Minimalistyczny backend<\/strong>. Czasami potrzebujemy wyda\u0107 w backendzie tylko kilka danych: gdzie\u015b podstawi\u0107 dat\u0119, gdzie\u015b wy\u015bwietli\u0107 jak\u0105\u015b list\u0119, powiedzie\u0107, ilu u\u017cytkownik\u00f3w aktualnie jest na stronie, doda\u0107 licznik lub statystyki. Co\u015b takiego niewielkiego. Minimalne fragmenty mo\u017cna bardzo \u0142atwo zrealizowa\u0107. Dzi\u0119ki temu wszystko przebiega szybko, \u0142atwo i skutecznie.\n<\/li>\n<li><strong>Przetwarzanie wst\u0119pne danych<\/strong>. Czasami chcemy zintegrowa\u0107 na naszej stronie reklam\u0119, a t\u0119 reklam\u0119 pobieramy za pomoc\u0105 zapyta\u0144 API. To mo\u017cna bardzo \u0142atwo zrealizowa\u0107 tutaj. Nie obci\u0105\u017camy naszego backendu, kt\u00f3ry i tak pracuje ci\u0119\u017cko. Mo\u017cna wzi\u0105\u0107 i skonstruowa\u0107 wszystko tutaj. Mo\u017cemy \u0142\u0105czy\u0107 jakie\u015b JS lub, w przeciwnym razie, rozdzieli\u0107, przetworzy\u0107 co\u015b przed przekazaniem u\u017cytkownikowi.\n<\/li>\n<li><strong>Fasada dla mikrous\u0142ugi<\/strong>. To tak\u017ce bardzo dobry przypadek, kt\u00f3ry zrealizowa\u0142em. Wcze\u015bniej pracowa\u0142em w firmie Tenzor, kt\u00f3ra zajmuje si\u0119 elektronicznym raportowaniem, zapewniaj\u0105c raportowanie dla oko\u0142o po\u0142owy podmiot\u00f3w prawnych w kraju. Stworzyli\u015bmy serwis, w kt\u00f3rym za pomoc\u0105 tego samego mechanizmu zrealizowano wiele rzeczy: routing, autoryzacj\u0119 i inne.<br \/>\nOpenResty mo\u017ce s\u0142u\u017cy\u0107 jako spoiwo dla Twoich mikroserwis\u00f3w, zapewniaj\u0105c jednolity dost\u0119p do wszystkiego i wsp\u00f3lny interfejs. Poniewa\u017c mikroserwisy mog\u0105 by\u0107 napisane w r\u00f3\u017cnych j\u0119zykach, jak Node.js, PHP, Python, czy te\u017c w Erlang, rozumiemy, \u017ce nie chcemy powiela\u0107 tego samego kodu wsz\u0119dzie. Dlatego OpenResty mo\u017cna zainstalowa\u0107 na froncie.<\/p>\n<\/li>\n<li><strong>Statystyka i analityka<\/strong>. Zazwyczaj NGINX znajduje si\u0119 na wej\u015bciu, a wszystkie zapytania przechodz\u0105 przez niego. W tym miejscu mo\u017cna bardzo wygodnie zbiera\u0107 dane. Mo\u017cna co\u015b od razu policzy\u0107 i wys\u0142a\u0107 do dowolnego miejsca, na przyk\u0142ad do Elasticsearch, Logstash lub po prostu zapisa\u0107 w logu i p\u00f3\u017aniej gdzie\u015b wys\u0142a\u0107.\n<\/li>\n<li><strong>Systemy wieloosobowe<\/strong>. Na przyk\u0142ad, \u015bwietnie sprawdzaj\u0105 si\u0119 w przypadku gier online. Dzi\u015b w Kapsztadzie Aleksander H\u0142ady\u015b opowie, jak szybko prototypowa\u0107 gr\u0119 wieloosobow\u0105 przy u\u017cyciu OpenResty.\n<\/li>\n<li><strong>Filtracja zapyta\u0144 (WAF)<\/strong>. Obecnie popularne jest tworzenie r\u00f3\u017cnych zap\u00f3r aplikacji webowych, a na rynku jest wiele us\u0142ug, kt\u00f3re je oferuj\u0105. Przy pomocy OpenResty mo\u017cna stworzy\u0107 zapor\u0119 aplikacji webowej, kt\u00f3ra w prosty spos\u00f3b b\u0119dzie filtrowa\u0107 zapytania zgodnie z Twoimi wymaganiami. Je\u015bli masz Python, to wiesz, \u017ce PHP na pewno nie zostanie zainkturowany, chyba \u017ce uruchomisz go z konsoli gdzie\u015b indziej. Wiesz, \u017ce masz MySQL i Python. By\u0107 mo\u017ce kto\u015b spr\u00f3buje przeprowadzi\u0107 atak typu directory traversal i co\u015b zainkturowa\u0107 w bazie. Dlatego mo\u017cna szybko i tanio filtrowa\u0107 nietypowe zapytania bezpo\u015brednio na froncie.\n<\/li>\n<li><strong>Spo\u0142eczno\u015b\u0107.<\/strong> Poniewa\u017c OpenResty oparty jest na NGINX, ma dodatkowy atut \u2014 to <strong>spo\u0142eczno\u015b\u0107 NGINX<\/strong>. Jest bardzo obszerna, a znaczna cz\u0119\u015b\u0107 pyta\u0144, kt\u00f3re mog\u0105 si\u0119 pojawi\u0107 na pocz\u0105tku, zosta\u0142a ju\u017c rozwi\u0105zana przez spo\u0142eczno\u015b\u0107 NGINX.\n<p><strong>programi\u015bci Lua<\/strong>.\u00a0Wczoraj rozmawia\u0142em z lud\u017ami, kt\u00f3rzy przyszli na dzie\u0144 szkoleniowy HighLoad++ i us\u0142ysza\u0142em, \u017ce jedynie Tarantool jest napisany w Lua. To nieprawda, wiele rzeczy zosta\u0142o stworzonych w Lua. Przyk\u0142ady: OpenResty, serwer XMPP Prosody, silnik gier Love2D, skrypty Lua w Warcraft i w innych miejscach. Jest wielu deweloper\u00f3w Lua, a ich spo\u0142eczno\u015b\u0107 jest du\u017ca i responsywna. Wszystkie moje pytania dotycz\u0105ce Lua by\u0142y rozwi\u0105zywane w ci\u0105gu kilku godzin. Kiedy piszesz na list\u0119 dyskusyjn\u0105, dos\u0142ownie w ci\u0105gu kilku minut masz ju\u017c mn\u00f3stwo odpowiedzi z wyja\u015bnieniami, co i jak, co do czego. To naprawd\u0119 wspania\u0142e. Niestety, nie wsz\u0119dzie jest taka przyjazna spo\u0142eczno\u015b\u0107.<br \/>\nDla OpenResty dost\u0119pny jest GitHub, gdzie mo\u017cna zg\u0142osi\u0107 problem, je\u015bli co\u015b si\u0119 zepsu\u0142o. Jest lista dyskusyjna na Google Groups, gdzie mo\u017cna porozmawia\u0107 o og\u00f3lnych kwestiach, a tak\u017ce jest lista po chi\u0144sku \u2014 mo\u017ce nie znasz angielskiego, a znasz chi\u0144ski.<\/li>\n<\/ul>\n<p><\/p>\n<h1>Podsumowanie<\/h1>\n<p><\/p>\n<ul>\n<li>Mam nadziej\u0119, \u017ce uda\u0142o mi si\u0119 przekaza\u0107, \u017ce OpenResty to bardzo wygodny framework, idealny do aplikacji webowych.<\/li>\n<li>Ma niski pr\u00f3g wej\u015bcia, poniewa\u017c kod jest podobny do tego, na czym pracujemy, a j\u0119zyk jest do\u015b\u0107 prosty i minimalistyczny.<\/li>\n<li>Oferuje asynchroniczne I\/O bez callback\u00f3w, wi\u0119c nie b\u0119dziemy mie\u0107 ba\u0142aganu, jak to czasami ma miejsce w NodeJS.<\/li>\n<li>Jego wdro\u017cenie jest \u0142atwe, poniewa\u017c potrzebujemy tylko NGINX z odpowiednim modu\u0142em i naszego kodu, i to wszystko dzia\u0142a od razu.<\/li>\n<li>Du\u017ca i responsywna spo\u0142eczno\u015b\u0107.<\/li>\n<\/ul>\n<p>\nNie opisa\u0142em szczeg\u00f3\u0142owo, jak odbywa si\u0119 routowanie, wyszed\u0142by bardzo d\u0142ugi wyk\u0142ad.<\/p>\n<p>Dzi\u0119kuj\u0119 za uwag\u0119!<\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"silrEB0Brvo\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/silrEB0Brvo\/hqdefault.jpg\" alt=\"Odtw\u00f3rz wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\n<em><noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2016\/abstracts\/2432.html\">W\u0142odzimierz Protasow - OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji<\/a><\/noindex><\/em><br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/321864\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0441 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 HighLoad++ 2016, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b\u0430 \u0432 \u043f\u043e\u0434\u043c\u043e\u0441\u043a\u043e\u0432\u043d\u043e\u043c \u0421\u043a\u043e\u043b\u043a\u043e\u0432\u043e 7\u20148 \u043d\u043e\u044f\u0431\u0440\u044f \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430. \u0412\u043b\u0430\u0434\u0438\u043c\u0438\u0440 \u041f\u0440\u043e\u0442\u0430\u0441\u043e\u0432 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c NGINX \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e OpenResty \u0438 Lua. \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0412\u043b\u0430\u0434\u0438\u043c\u0438\u0440 \u041f\u0440\u043e\u0442\u0430\u0441\u043e\u0432, \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 Parallels. \u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043e \u0441\u0435\u0431\u0435. \u0422\u0440\u0438 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u0438 \u0441\u0432\u043e\u0435\u0439 \u0436\u0438\u0437\u043d\u0438 \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u0438\u0448\u0443 \u043a\u043e\u0434. \u0421\u0442\u0430\u043b [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":71379,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-71378","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47OpenResty: \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c NGINX \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-02-25T17:45:02+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:14:21+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji | ProHoster","description":"\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47OpenResty: \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c NGINX \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 | ProHoster","og:description":"\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-02-25T17:45:02+00:00","article:modified_time":"2020-03-03T13:14:21+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"71378","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:03:22","updated":"2022-09-30 08:39:30","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/71378","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=71378"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/71378\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/71379"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=71378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=71378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=71378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}