Навіщо нам потрібні RESTful веб-сервіси?


123

Я збираюся вивчити RESTful веб-сервіси (краще сказати, що мені доведеться це робити, тому що це частина програми магістерської програми CS).

Я прочитав деяку інформацію у Вікіпедії, а також прочитав статтю про REST в Sun Developer Network і бачу, що це непроста технологія, існують спеціальні рамки для побудови програм RESTful, і це часто порівнюється з веб-сервісами SOAP і програміст повинен розуміти, коли використовувати SOAP і коли REST може бути приємним підходом.

Я пам’ятаю, що кілька років тому SOAP був дуже популярним (модно?), А пункт «SOAP» повинен був бути присутнім у кожному хорошому резюме. Але на практиці його застосовували дуже рідко і для досягнення дуже простих цілей.

Мені здається, що REST - це ще одне «останнє слово моди» (або я можу абсолютно помилятися, тому що я ніколи не бачив REST на практиці).

Чи можете ви надати мені кілька прикладів: REST слід використовувати і чому ми не можемо зробити те ж саме без REST (або чому ми повинні витратити набагато більше часу, щоб зробити те ж саме без REST)?

UPD : На жаль, я не бачу жодних конкретних аргументів, які можуть забити мій погляд у перших коментарях. Змусити мене думати, що REST - це приголомшлива технологія!

Я хотів би побачити такі відповіді:

Я розробляв ще одне складне додаток HelloWorld, і нам потрібно передати багато / крихітних даних, і я запропонував REST рішення своєму колезі:

- О, чорт! Джоні, ми, звичайно, повинні використовувати REST для реалізації цього додатка!
- Так, Біллі, ми можемо використовувати REST, але краще використовувати SOAP. Повірте мені, бо я знаю щось про розробку програм HelloWorld.
- Але SOAP - це старомодна технологія минулого століття, і ми можемо використовувати кращу.
- Біллі, ти готовий витратити 3 дні на експерименти з REST? Ми можемо це зробити за допомогою SOAP за 2 години ..
- Так, я впевнений, що ми витратили ще більше часу на досягнення такої ж безпеки / продуктивності / / масштабованості / що б там не було ще з SOAP. Я впевнений, що програми HelloWorld відтепер повинні розроблятися лише з REST.


2
Це не дивовижна технологія - це інша технологія. Якщо ви хочете, щоб хтось переконав вас, що це дивовижно, і його слід використовувати кожен раз, спробуйте консультанта.
quillbreaker

Відповіді:


133

REST слід використовувати, якщо для вас дуже важливо мінімізувати зв'язок між клієнтськими та серверними компонентами в розподіленій програмі.

Це може бути, якщо ваш сервер буде використовуватися багатьма різними клієнтами, над якими ви не маєте контролю. Також це може бути, якщо ви хочете регулярно оновлювати сервер, не потребуючи оновлення клієнтського програмного забезпечення.

Я можу запевнити, що досягти цього низького рівня з’єднання зробити непросто . Важливо дотримуватися всіх обмежень REST, щоб досягти успіху. Підтримувати чисто бездержавний зв’язок важко. Вибір правильних типів мультимедіа та видавлення даних у формати є складним. Створення власних типів медіа може бути ще складніше.

Адаптація насиченої поведінки сервера в єдиний інтерфейс HTTP може бути заплутаною і часом здається педантичною порівняно з порівняно простим підходом RPC.

Незважаючи на труднощі, переваги полягають у тому, що у вас є послуга, яку розробник клієнта повинен мати можливість легко зрозуміти через послідовне використання протоколу HTTP. Послуга має бути легко відкритою через гіпермедіа, і клієнт повинен бути надзвичайно стійким до змін на сервері .

Переваги гіпермедіа та уникнення стану сеансу робить балансування навантажень простим, а службовий розподіл можливим . Суворе відповідність HTTP правилам робить доступність таких інструментів, як налагоджувачі та кешування проксі-серверів.

Оновлення

Мені здається, що REST - це ще одне «останнє слово моди» (або я можу абсолютно помилятися, тому що я ніколи не бачив REST на практиці).

Я думаю, що REST став модним, тому що люди, що намагаються робити проекти типу SOA, виявили, що використовуючи стек SOAP, вони не реалізують обіцяних переваг. Люди постійно повертаються до Інтернету як приклад простих методологій інтеграції. На жаль, я вважаю, що люди недооцінюють обсяг планування та передбачуваності, який був розроблений в Інтернеті, і вони надмірно спрощують, що потрібно зробити, щоб дозволити багаторазове використання, яке відбувається в Інтернеті.

Ви кажете, що REST ніколи не бачили на практиці, але це не може бути правдою, якщо ви коли-небудь використовувати веб-браузер. Веб-браузер - це REST-клієнт.

  • Чому вам не потрібно оновлювати браузер, коли хтось змінює якийсь html на веб-сайті?
  • Чому я можу додати повний новий набір сторінок на веб-сайт, і "клієнт" все ще може отримати доступ до цих нових сторінок без оновлення?
  • Чому мені не потрібно надавати веб-браузеру "мову-опис служби", щоб сказати, коли мова йде про http://example.org/images/cat, що тип повернення буде зображенням jpeg та коли ви переходите для http://example.org/description/cat тип повернення буде text / html?
  • Чому я можу використовувати веб-браузер для відвідування сайтів, які не існували після виходу браузера? Як клієнт може знати про ці сайти?

Вони можуть здатися невідповідними питаннями, але якщо ви знаєте відповідь, тоді ви можете почати бачити, про що йдеться REST. Подивіться на StackOverflow, щоб отримати більше переваг REST. Переглядаючи питання, я можу зробити закладку на цій сторінці або надіслати URL-адресу другові, і він може побачити ту саму інформацію. Щоб знайти це питання, йому не потрібно переходити через сайт.

StackOverflow використовує різні сервіси OpenId для аутентифікації, gravatar.com для зображень аватарів, google-analytics та Quantserve для аналітичної інформації. Така різнорівнева інтеграція компаній є типом речі, про який мріє світ SOAP . Одним з найкращих прикладів є той факт, що бібліотеки jQuery, які використовуються для керування інтерфейсом StackOverflow, отримують із мережі доставки вмісту Google. Те, що SO може направити клієнта (тобто вашого веб-браузера) на завантаження коду з сторонніх сайтів для підвищення продуктивності, свідчить про низьку зв’язок між веб-клієнтом та сервером.

Це приклади архітектури REST на роботі.

Зараз деякі веб-сайти / програми порушують правила REST, і тоді браузер не працює, як очікувалося.

  • Сумнівна проблема з кнопкою повернення викликана використанням стану сеансу на стороні сервера.
  • Балансування навантаження може стати болем, коли у вас є стан сеансу на стороні сервера.
  • Флеш-програми часто заважають URL-адресу конкретно ідентифікувати представлення.
  • Інша проблема, яка порушує веб-браузери - це погана відповідність стандартам медіа-типу. Ми постійно чуємо про те, як потрібно вбити IE6. Проблема полягає в тому, що стандарти не дотримувалися належним чином або були ігноровані з будь-якої причини.
  • Використання сеансів входу є джерелом багатьох пробілів у безпеці.

REST скрізь. Саме робота в Інтернеті змушує її добре працювати. Якщо ви хочете створити розповсюджені програми, які можуть масштабуватись як веб, будьте стійкі до змін, як Інтернет, та сприяти повторному використанню, як це робилося в Інтернеті, то дотримуйтесь тих самих правил, що і при створенні веб-браузерів.


@Darrell: як у світі REST зменшує зв'язок через SOAP? Або як SOAP збільшує зв'язок над REST? Ви маєте на увазі той факт, що клієнт SOAP насправді повинен розуміти SOAP, а клієнт REST повинен розуміти лише типи медіа?
Джон Сондерс

4
@John Взагалі спосіб використання SOAP викликає у клієнта необхідні "складені" знання про кожну кінцеву точку на стороні сервера, кожен тип даних параметрів і кожен тип повернення. У світі SOAP немає вказівок намагатися використовувати стандартизовані типи для передачі даних між клієнтом і сервером. Це означає, що кожна нова послуга, яку розробляє клієнт, має свій унікальний набір типів, кінцевих точок та протокол взаємодії. Це зчеплення.
Даррел Міллер

@John REST намагається стандартизувати протокол взаємодії з семантикою дієслів HTTP, формати даних до зареєстрованих типів IANA та всі кінцеві точки повинні бути динамічно відкритими. Це означає, що зв'язок клієнт / сервер локалізований для визначення типу медіа. Як сказав Річ, "ваша послуга звужує сферу зв'язку лише на одне - типи медіа".
Даррел Міллер

@Darrell: це не зв'язок у традиційному розумінні. Клієнта можна вважати "приєднаним" до метаданих (WSDL), але не до сервісу. Розглянемо службу, яка повертає "Співробітник": {int id; рядок firstName, lastName, streetAddress1, streetAddress2, місто, штат; int zip;}. Ви, здається, пропонуєте або зареєструвати "Співробітник" в IANA, або ми просто вважаємо "Співробітник" асоціативним масивом пар імен / значень.
Джон Сондерс

@John Дозвольте мені визначити, що я маю на увазі під сполученням у WSDL термінах. Уявіть, що ви можете мати договір на обслуговування, до якого можна додати методи, видалити методи та перейменувати методи без необхідності перекомпілювати клієнта. Також врахуйте, що клієнту можна було б доручити використовувати ці нові методи без перекомпіляції. Договір повідомлення фіксується HTTP, але розширюється через заголовки, і договір даних є єдиною зміною, яка може зламати клієнта, проте, використовуючи метадані в договорі повідомлення, сервер міг динамічно доставити відповідну версію договору даних клієнту.
Даррел Міллер

11

Наскільки мені відомо, REST розпочав роботу дисертацією Роя Філдінга « Архітектурні стилі та дизайн мережевих програмних архітектур» , яку варто прочитати, якщо ви її ще не вивчали.

Вгорі дисертації - цитата:

Майже кожен відчуває себе в спокої з природою: слухаючи океанські хвилі проти берега, біля нерухомого озера, у полі трави, на вітряній вітрі. Одного разу, коли ми знову навчимося позачасовому шляху, ми будемо відчувати те саме про свої міста, і ми відчуємо стільки ж спокою в них, як і сьогодні, гуляючи біля океану чи простягнувшись у довгій траві луг.

- Крістофер Олександр, Невічний шлях будівництва (1979)

І це дійсно підсумовує це там. REST багато в чому елегантніший.

SOAP - це протокол поверх HTTP, тому він обходить безліч конвенцій HTTP для побудови нових конвенцій у SOAP, і в ряді способів є надмірним для HTTP. HTTP, однак, більш ніж достатньо для відновлення, пошуку, запису та видалення інформації через HTTP, і це багато чого з REST. Оскільки REST побудований за допомогою HTTP замість нього, це означає, що програмне забезпечення, яке хоче інтегруватися з ним (наприклад, веб-браузер), не потребує розуміння SOAP для цього, а лише HTTP, який повинен бути найбільшим широко зрозумілий та інтегрований - з протоколом, що використовується в даний момент.


SOAP було визначено ще в 1998 році. Скільки HTTP-конвенцій було тоді конвенцій?
Джон Сондерс

Відповідно до цього w3.org/Protocols/HTTP/1.0/spec.html HTTP використовується з 1990 року. Що робити? Ми всі знаємо, що єдиною причиною використання SOAP http було те, що порт 80, швидше за все, був відкритий на брандмауері. Microsoft не збирається знову робити помилку DCOM.
Даррел Міллер

1
" REST побудований за допомогою HTTP, а не над ним " +1. Весь цей потік мені дуже допомагає зрозуміти обґрунтованість використання REST через SOAP та навпаки.
Chris22

9

Від сюди :

Переваги:

  • Легка вага - не багато зайвої розмітки в Xml
  • Результати, зрозумілі для людини
  • Простота в побудові - не потрібні набори інструментів

Також перевірте це :

Для справедливості, REST - не найкраще рішення для кожної веб-служби. Дані, які потрібно захистити, не повинні надсилатися як параметри в URI. А велика кількість даних, як, наприклад, у детальних замовленнях на купівлю, може швидко стати громіздкою або навіть вийти за межі в межах URI. У цих випадках SOAP дійсно є надійним рішенням. Але важливо спробувати REST спершу і вдатися до SOAP лише при необхідності. Це допомагає забезпечити просту та доступну розробку додатків.


4
Мінус коментар не дуже коректний. Переміщення параметра з URI в тіло це все ще не захищено. Використовуйте SSL для безпеки. Крім того, коли дані в урі можуть бути дуже довгими, ви можете використовувати пост і вносити їх у тіло. Більшість мов на сервері поєднують дані з параметрів URI та параметрів POST, тому ніяких змін на сервері не потрібно.
Еміль Іванов

1
@Emil - Пам’ятайте, що SSL доступний не завжди. Деякі люди хочуть забезпечити безпеку на основі повідомлень, а не безпеку на рівні транспорту. Що стосується використання тіла POST ... POST - це одне з дієслів, яке використовується для обробки запитів REST. Ви не завжди зможете повторно використовувати його відповідно до своїх потреб.
Джастін Нісснер

1
Великий CON: відсутність стандартизованої мови "опису", як WSDL для SOAP-сервісів - кожна служба REST може бути або не може бути задокументована, а якість документації сильно відрізняється від надання послуг іншим .....
marc_s

3
@Marc_s Якщо REST виконано правильно, немає необхідності в "мові опису" на зразок WSDL. Використовувані типи носіїв інформації повинні бути задокументовані, але не повинно існувати документації, яка б з'єднувала кінцеві точки з типами медіа.
Даррел Міллер

@Darrel: Вибачте, я не купую дурниць "мови без опису". Навіть якщо типи документів задокументовані, їх також потрібно описати. Крім того, деякі люди насправді люблять десаріалізувати вміст в об'єкти мовою програмування. У цьому випадку дуже корисно мати машиночитане визначення того, що служба може надсилати та отримувати, щоб ваш інструмент міг створити відповідні класи та код серіалізації.
Джон Сондерс

8

Я з упевненістю можу сказати, що я витратив багато часу, щоб зрозуміти це як початківець, але це найкраще посилання для початку з REST з нуля! http://www.codeproject.com/Articles/21174/Everything- About-REST-Web-Services-What-and-How-Pa

Просто щоб затягнути вас,

Подумайте, що таке "традиційний веб-сервіс". Це інтерфейс з відкритими "методами". Клієнти знають ім'я методів, введення та виведення методів, а тому можуть викликати їх.

Тепер уявіть собі інтерфейс, який не піддається "методам". Натомість він викриває "предмети". Отже, коли клієнт бачить цей інтерфейс, все, що він бачить, - це один або кілька «об’єктів». "Об'єкт" не має вводу та виводу - тому що "він нічого не робить". Це іменник, а не дієслово. Це "річ", а не "дія".

Наприклад, подумайте про традиційний веб-сервіс, який надає поточні погодні умови, якщо ви надаєте йому місто. Ймовірно, є веб-метод на кшталт GetWeatherInfo (), який приймає місто як вхідний дані та надає дані про погоду як вихід. Поки вам легко зрозуміти, як споживач споживає цю веб-службу.

А тепер уявіть, що на місці вищевказаного веб-сервісу з'явився новий, який розкриває міста як об’єкти. Отже, коли ви дивитесь на нього як на клієнта, замість GetWeatherInfo () ви бачите Нью-Йорк, Даллас, Лос-Анджелес, Лондон тощо. І ці міста не мають жодних прикладних методів, які звисають до них - вони, схоже, інертні гази - вони самі не реагують.

Ви, мабуть, думаєте - ну як це допомагає вам, як клієнту, дістатися до погоди Далласа? До цього ми дістанемося через кілька моментів.

Якщо все, що ви отримуєте від веб-сервісу, - це «набір об’єктів», очевидно, вам потрібен спосіб «діяти на них». Самі об’єкти не мають методів виклику, тому вам потрібен набір дій, які ви можете застосувати до цих об'єктів. Іншими словами, вам потрібно «застосувати дієслово до іменника». Якщо ви бачите предмет, скажімо, яблуко, яке є "іменником", ви можете застосувати до нього "дієслово", як їсти. Але не всі дієслова можуть бути застосовані до всіх іменників. Мовляв, ти можеш керувати автомобілем, але не можеш керувати телевізором.

Таким чином, якщо веб-сервіс виставляє лише об'єкти, а вас запитують - ну давайте тепер розробимо кілька стандартних дій або дієслів, які "всі клієнти можуть застосовувати до всіх об'єктів, які вони бачать", ...


Тож яка користь мати об'єкт замість методу?
Soumya Rauth

4

Ось кілька ідей:

  • REST обмежує вашу послугу використовувати єдиний інтерфейс. Вам не доведеться витрачати час на мріяння (або сперечаючись) про всі можливі способи роботи вашої служби - ви отримаєте право працювати над визначенням ресурсів у вашій системі. Виявляється, це сама велика робота, але, на щастя, проблеми, як правило, визначаються набагато краще.
  • З ресурсами, їх об'єднаннями та представництвами в роботі насправді дуже мало робити в реалізації вашої послуги, оскільки для вас було прийнято багато рішень.
  • Ваша система буде дуже схожа на інші системи RESTful; Криві навчання колег, партнерів та клієнтів будуть зменшені.
  • У вас буде загальний словник, щоб обговорити проблеми дизайну з іншими розробниками, і навіть з тими менш технічно налаштованими (такими як клієнти).
  • Як каже Даррел, оскільки ви використовуєте дизайн, керований гіпертекстом , ваша послуга звужує сферу зв'язку лише до одного - типів носія. Це допомагає вам як розробнику, оскільки зміни у вашій системі містяться у вузькій смузі контактів. Це допомагає вашим клієнтам у тому, що менша кількість ваших змін порушить їх код.
  • Практично кожну проблему, яка може виникнути при впровадженні REST, можна вирішити, відкривши новий ресурс або переосмисливши свою ресурсну модель. Цей фокус є, IMO, великим підвищенням продуктивності.

Підсумок, REST видаляє багато робочих процесів вашої команди та найбільш трудомісткі та суперечливі рішення щодо проектування та впровадження. Це переключає вашу увагу від впровадження вашої послуги до її розробки . І це робиться, не складаючи gobbledygook на протокол HTTP.


@John Якщо я запускаю VS і створюю проект WCF і створюю інтерфейс з атрибутом [ServiceContract], я можу додати будь-які дзвінки методу, які мені подобаються. CreateCustomer (), MakeOrder (), ConfirmOrder (), VerifyOrder (), SubmitOrder (), CheckStockAvailable (), CancelOrder () З цих методів, чи можете ви сказати мені, яку послідовність я повинен використовувати для обробки замовлення? Чи можете ви сказати мені, коли мені дозволено зателефонувати CancelOrder ()? Чи варто перевірити наявність, перш ніж підтвердити замовлення? Чи слід перевірити замовлення, перш ніж перевірити наявність? Цей інтерфейс, швидше за все, не буде відповідати тому, який виконується з оплати праці.
Даррел Міллер

1
@Darrel: Я не бачу, як REST допомагає вирішити це. Чи MakeOrderвидає URL-адреси для ConfirmOrderта CancelOrder? Клієнт вже не знає, як зателефонувати в службу, а навпаки повинен керуватися даними?
Джон Сондерс

1
@John Рівно. Клієнт знає, що URL-адреса ConfirmOrder та URLOpollerOrder можуть бути надані йому, але він не знає, як виглядають ці URL-адреси, і буде виконувати їх лише за умови надання. Ви називаєте це керованим даними, Рой називає його Hypermedia як двигун стану програми.
Даррел Міллер

@Darrel: Напевно, я ніколи не бачив жодної критично важливої ​​для бізнесу послуги, де я хочу визначити, що мені дзвонити далі, виходячи з того, яку URL-адресу мені передали з попереднього дзвінка.
Джон Сондерс

1
@JohnSaunders: це тому, що виклик REST - це не виклики методу, а перехід стану (думаю, що стан машини). У будь-якому даному стані сервер RESTful задає дійсні переходи стану, і користувач або користувальницький агент вибирає переходи, які він хоче виконати.
Лі Лі Райан

4

Більшість "профі" відповідей про REST, схоже, надходять від людей, які ніколи не розробляли веб-службу SOAP або клієнта, використовуючи середовище, яке забезпечує відповідні інструменти для виконання завдання. Вони скаржаться на проблеми, з якими я просто ніколи не стикався, використовуючи Visual Studio .NET та Rational Web Developer. Я припускаю, що якщо вам доведеться розробляти веб-сервіси або клієнтів на мові сценаріїв чи іншою мовою з малою підтримкою інструментів або взагалі, це справжні скарги.

Я також мушу визнати, що кілька "про" пунктів звучать як речі, які насправді можуть бути правдивими, - але я ніколи не бачив приклад, який ілюструє їхню цінність. Зокрема, я дуже вдячний, якщо хтось опублікує коментар, що містить посилання на хороший приклад веб-сервісу REST. Це має бути той, хто використовує декілька рівнів ресурсів, можливо в ієрархії, і використовує типи медіа належним чином. Можливо, якщо я дивлюсь на хороший приклад, я зрозумію, у такому випадку я повернусь сюди і зізнаюся.


Найкращий на сьогодні загальнодоступний приклад - це API Sun Cloud. Ось основна інформація щодо кенаї.com/projects/suncloudapis/pages/… Просто для того, щоб кваліфікувати свій досвід роботи з SOAP. Я створив і досі підтримую веб-сервіси ASMX за допомогою Фабрики програмного забезпечення для веб-служб Microsoft із групи Шаблони і практики. Я створив послуги на базі WCF, використовуючи пізніший випуск тієї ж фабрики програмного забезпечення. Я також користувався системою WC.ServiceModel.Web WCF, оскільки вперше був випущений разом із SDK Biztalk Services SDK у травні 2007 року.
Даррел Міллер

1
Джон - один із прикладів API відпочинку - Amazon. Вони мають як @SOAP, так і REST API. Це може бути корисно для вас- docs.amazonwebservices.com/AmazonS3/latest/…
RichardOD

3

Щоб додати дещо прозаїчне відвертання до вже відповідей, зважаючи на те, що ми використовуємо послуги REST, де я є, це те, що якщо ви знаєте, ви можете передати діловому партнеру URL-адресу і знаєте, що вони отримають, взамін, чудово викладену плитку XML незалежно від того, працюють вони.

Це також означає, що в кінцевому підсумку наші продавці можуть похвалитися нашим універсальним API людям, не боячись виглядати як повноцінні мапетки.

Окрім технічних переваг, непогано пояснити, продемонструвати, продемонструвати та почути себе впевнено - це добре. SOAP, хоча настільки ж крутий для технологій набагато менш доступний для нетехнологів, а тому «продати» його не так просто.

Я, як правило, помічаю, що речі, які не мають технологій, можуть закручуватися, як правило, прилипають. Тому я сумніваюся, що REST як техніка може бути настільки ж сприйнятливим, як SOAP до примх мод.

Але все, що стосується того, щоб нічого не ставити в службу REST, яка повинна бути заблокована, є подвійною правдою хоча б тому, що технологію так легко зрозуміти людям, які не так технічно налаштовані.


3

REST - це стиль архітектури для проектування мережевих додатків. Ідея полягає в тому, що замість використання складних механізмів, таких як CORBA, RPC або SOAP для з'єднання між машинами, для здійснення дзвінків між машинами використовується простий HTTP.

Багато в чому саме Всесвітня павутина, заснована на HTTP, може розглядатися як архітектура на основі REST. Програми RESTful використовують запити HTTP для розміщення даних (створення та / або оновлення), зчитування даних (наприклад, здійснення запитів) та видалення даних. Таким чином, REST використовує HTTP для всіх чотирьох операцій CRUD (Create / Read / Update / Delete).

REST - це легка альтернатива таким механізмам, як RPC (віддалені виклики процедури) та веб-сервіси (SOAP, WSDL та ін.). Пізніше ми побачимо, наскільки простішим є REST.

Незважаючи на простоту, REST є повнофункціональним; у веб-сервісах ви нічого не можете зробити, що не можна зробити з архітектурою RESTful. REST - це не «стандарт». Наприклад, ніколи не буде рекомендації W3C для REST. І хоча існують рамки програмування REST, робота з REST настільки проста, що ви часто можете "прокатати свої" за допомогою стандартних функцій бібліотеки такими мовами, як Perl, Java або C #.


" Багато в чому саму Всесвітню павутину, засновану на HTTP, можна розглядати як архітектуру на основі REST. RESTful програми використовують HTTP-запити для розміщення даних (створення та / або оновлення), зчитування даних (наприклад, здійснення запитів), і видалити дані. Таким чином, REST використовує HTTP для всіх чотирьох операцій CRUD (Створення / читання / оновлення / видалення). "Це ще один чудовий практичний приклад для мене, щоб зняти цю посаду. Дякую.
Chris22
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.