Прикладний програмний інтерфейс. Що таке api? Api функції

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

API (application programming interface) - це інтерфейс прикладного програмування. Якщо говорити більш простою мовою, це набір різних функцій, констант, класів, форматів запитів, які можна використовувати інших програмах.

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

прикладом APIє Windows API, OpenGL API, Direct3D APIі так далі.

Наприклад, нещодавно я теж зіткнувся безпосередньо з API. Я зареєструвався на сервісі поштових розсилок SmartResponder.ruі завів розсилку, на яку стали підписуватися люди. Завдання було наступне: протягом доби після підписки людина може придбати зі знижкою мій платний відеокурс. SmartResponder.ru", то звичайний доступ (наприклад, через БД) до цих даних я не мав, а реалізовувати це було потрібно. Благо, у " SmartResponder.ruє свій власний API, Яким я і скористався.

Я знайшов у них APIформат запиту, щоб витягти дату передплати. Далі через CURLя надіслав відповідний запит і отримав потрібну дату передплати для конкретного e-mail адреси. Далі стандартна обробка та виведення результату.

Леонід Якубович 26 листопада 2012 о 13:59

Що таке API

  • Чулан *

Вітаю!
У цій статті ми з вами розглянемо, що таке API, де, як і для чого воно застосовується. Також ми розглянемо, як API можна застосувати у своїх веб-розробках і чим це може спростити життя програмісту.

Отже, почнемо з визначення. API (Application Programming Interface) – це інтерфейс програмування, інтерфейс створення програм. Якщо говорити більш зрозумілою мовою, то API – це готовий код для спрощення програмісту життя. API створювався для того, щоб програміст реально міг полегшити завдання написання тієї чи іншої програми завдяки використанню готового коду (наприклад, функцій). Усім відомий jQuery, написаний на JavaScript є також свого роду API. Якщо розглядати цей приклад, то jQuery дозволяє набагато полегшити написання коду. Те, що звичайними засобами JavaScript можна було зробити за 30 рядків, через jQuery пишеться через 5-6. Якщо розглядати API загалом, можна знайти дуже багато сервісів, які мають рішення розробки. Найвідоміший на сьогоднішній день це сервіс code.google.com, що надає близько півсотні різноманітних API! Це і інтерфейс для створення Android-додатків, і різні API для роботи з AJAX, і різні API-додатків, які можна легко підлаштувати під свій лад.

Адже чи є сенс писати код своїми руками? Навіщо працювати над тим, що вже створено? Хіба є сенс відмовлятися від безкоштовних рішень (а фактично і від безкоштовної допомоги) у web розробці? Якщо ви відповіли на ці запитання «НІ», то вважайте, що ви зрозуміли суть API.

Але ще хочу обмовитися. Розробникам-початківцям НЕ слід користуватися напівготовими рішеннями, оскільки в майбутньому вони не впораються з реальним завданням. Тому, якщо ви початківець програміст, то не використовуйте напівфабрикати! Навчайтеся думати своєю головою, будувати різні алгоритми, щоб зрозуміти суть програмування. Також кажу, вже звертаючись до всіх, що API - це не готові рішення, це середовище, інтерфейс для створення своїх проектів. Ви ж не їсте заморожені котлети з магазину? Ви спочатку їх посмажіть, чи не так? Ця аналогія дуже ясно відображає суть API.

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

Windows API – набір функцій операційної системи

Абревіатура API багатьом програмістам-початківцям здається дуже таємничою і навіть лякаючою. Насправді Application Programming Interface (API) - це просто деякий готовий набір функцій, який можуть використовувати розробники додатків. У загальному випадку це поняття еквівалентне тому, що раніше частіше називали бібліотекою підпрограм. Однак, зазвичай, під API мається на увазі особлива категорія таких бібліотек.

У ході розробки практично будь-якого досить складного додатка (MyAppication) для кінцевого користувача формується набір специфічних внутрішніх функцій, які використовуються реалізації цієї конкретної програми, який називається MyApplication API. Однак часто виявляється, що ці функції можуть ефективно використовуватися і для створення інших програм, зокрема іншими програмістами. У цьому випадку автори, виходячи зі стратегії просування свого продукту, мають вирішити питання: чи відкривають вони доступ до цього набору для зовнішніх користувачів чи ні? При ствердній відповіді в описі програмного пакета як позитивна характеристика з'являється фраза: «Комплект включає відкритий набір API-функцій» (але іноді за додаткові гроші).

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

Відповідно, Windows API - це набір функцій, що є частиною самої операційної системи і в той же час - доступний для будь-якої іншої програми, у тому числі написаної за допомогою VB. У цьому плані цілком виправдана аналогія з набором системних переривань BIOS/DOS, який фактично є DOS API.

Відмінність у тому, що склад функцій Windows API, з одного боку, значно ширше проти DOS, з іншого - не включає багато засобів прямого управління ресурсами комп'ютера, доступні програмістам у попередній ОС. Крім того, звернення до Windows API виконується за допомогою звичайних процедурних звернень, а виклик функцій DOS через спеціальну машинну команду процесора, яка називається Interrupt («переривання»).

Навіщо потрібний Win API для VB-програмістів

Незважаючи на те, що VB має безліч різноманітних функцій, у процесі більш-менш серйозної розробки виявляється, що їх можливостей часто не достатньо для вирішення необхідних завдань. При цьому програмісти-новачки часто починають скаржитися на недоліки VB і подумувати про зміну інструменту, не підозрюючи, що на їхньому комп'ютері є величезний набір коштів і потрібно вміти ними скористатися.

При знайомстві з Win API виявляється, що багато вбудованих VB-функцій не що інше, як звернення до відповідних системних процедур, але тільки реалізоване у вигляді синтаксису даної мови. З огляду на це необхідність використання API визначається наступними варіантами:

  1. API-функції, що повністю реалізовані у вигляді вбудованих VB-функцій. Тим не менш, іноді і в цьому випадку буває корисним перейти до застосування API, так як це дозволяє часом істотно підвищити продуктивність (зокрема, за рахунок відсутності непотрібних перетворень параметрів, що передаються).
  2. Вбудовані VB-функції реалізують лише окремий випадок відповідної API-функції. Це досить простий варіант. Наприклад, API-функція CreateDirectory має ширші можливості порівняно з вбудованим VB-оператором MkDir.
  3. Величезна кількість API-функцій взагалі немає аналогів у існуючому сьогодні варіанті мови VB. Наприклад, видалити каталог засобами VB не можна – для цього потрібно використовувати функцію DeleteDirectory.

Слід також підкреслити, що деякі API-функції (їх частка у Win API дуже незначна) не можуть викликатися з VB-програм через ряд обмежень мови, наприклад, через відсутність можливості роботи з адресами пам'яті. Але в ряді випадків можуть допомогти нетривіальні прийоми програмування (зокрема, у випадку з тими самими адресами).

Особиста думка автора така - замість розширення від версії до версії вбудованих функцій VВ слід було б давати хороший опис найбільш ходових API-функцій. У той же час хочеться порадити розробникам не чекати на появу нової версії засобу з розширеними функціями, а уважніше вивчити склад існуючого Win API - цілком імовірно, що потрібні вам можливості можна було реалізувати вже у версії VB 1.0 випуску 1991 року.

Як вивчати Win API

Це не таке просте питання, якщо врахувати, що кількість функцій Win32 API оцінюється в розмірі близько 10 тисяч (точної цифри не знає ніхто, навіть Microsoft).

До складу VB (версій 4-6) входить файл з описом оголошень Win API - WIN32API.TXT (докладніше про його застосування ми розповімо пізніше). Але, по-перше, з його допомогою можна отримати відомості про призначення тієї чи іншої функції та її параметри лише за використовуваними мнемонічним іменами, а по-друге - перелік функцій у цьому файлі далеко не повний. Свого часу (сім років тому) у VB 3.0 були спеціальні довідкові файли з описом функцій Win16 API. Проте вже у v.4.0 ця корисна інформація зі зручним інтерфейсом зникла.

Вичерпну інформацію про Win32 API можна знайти у довідковій системі Platform Software Development Kit, яка, зокрема, знаходиться на компакт-дисках MSDN Library, включених до складу VB 5.0 та 6.0 Enterprise Edition та Office 2000 Developer Edition. Однак розшукати там потрібну інформацію та розібратися в ній зовсім не просто. Не кажучи вже про те, що всі описи там наводяться стосовно мови C.

Загальновизнаним у світі посібником вивчення API-программирования серед VB є книжки відомого американського експерта Даніеля Епплмана (Daniel Appleman). Його серія Dan Appleman's Visual Basic Programmer's Guide до Windows API (для Win16, Win32, стосовно різних версій VB) з 1993 року незмінно входить до бестселерів для VB-програмістів. Книгу Dan Appleman's VB 5.0 Programmer's Guide to the Win32 API, випущену в 1997 році, автору привіз зі США приятель, який знайшов її в першій книгарні невеликого провінційного містечка.

Ця книга об'ємом понад 1500 сторінок включає опис загальної методики API-програмування серед VB, а також більше 900 функцій. Компакт-диск, що додається, містить повний текст книги та всіх програмних прикладів, а крім того, кілька додаткових розділів, які не увійшли до друкованого варіанту. У 1999 році Ден Епплман випустив нову книгу Dan Appleman's Win32 API Puzzle Book and Tutorial для Visual Basic Programmers, яка включає відомості про ще 7600 функцій (хоч і не настільки докладні).

Win API та Dynamic Link Library (DLL)

Набір Win API реалізований як динамічних DLL-бібліотек. Далі фактично піде про технологію використання DLL в середовищі VB на прикладі бібліотек, що входять до складу Win API. Однак, говорячи про DLL, необхідно зробити кілька важливих зауважень.

У цьому випадку під DLL ми маємо на увазі традиційний варіант двійкових динамічних бібліотек, які забезпечують пряме звернення до потрібних процедур - підпрограм або функцій (приблизно так само, як це відбувається при виклику процедур всередині VB-проекту). Такі бібліотеки можуть створюватися за допомогою різних інструментів: VC++, Delphi, Fortran, крім VB (подивимося, що з'явиться у версії 7.0) – останній може робити лише ActiveX DLL, доступ до яких виконується через інтерфейс OLE Automation.

Зазвичай файли динамічних бібліотек мають розширення.DLL, але це не обов'язково (для Win16 часто застосовувалося розширення.EXE); драйвери зовнішніх пристроїв позначаються за допомогою DRV.

Як ми вже зазначали, визначити точну кількість API-функцій Windows і файлів, що містять їх, досить складно, проте всі вони знаходяться в системному каталозі. У цьому плані краще виділити склад бібліотек, що входять до ядра операційної системи, та основних бібліотек із ключовими додатковими функціями.

А тепер кілька порад.

Порада 1. Слідкуйте за правильним оформленням оголошення DL L-процедур

Саме звернення до DLL-процедур у програмі виглядає так само, як до «звичайних» процедур Visual Basic, наприклад:

Call DllName ([список аргументів])

Однак для використання зовнішніх DLL-функцій (у тому числі і Win API) їх потрібно обов'язково оголосити у програмі за допомогою оператора Declare, який має такий вигляд:

Declare Sub Ім'яПроцедури Lib _ “Ім'яБібліотеки” _ [([СписокАргументів])]

Declare Function Ім'яФункції _ Lib “Ім'яБібліотеки” _ [([СписокАргументів])]

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

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

Набір Win32 API реалізований лише у вигляді функцій (у Win16 API було багато підпрограм Sub). Здебільшого це функції типу Long, які найчастіше повертають код завершення операції.

Оператор Declare з'явився в MS Basic ще за DOS, причому він використовувався і для оголошення внутрішніх процедур проекту. Visual Basic цього не потрібно, так як оголошенням внутрішніх процедур автоматично є їх опис Sub або Function. Порівняно з Basic/DOS у новому описі обов'язково вказувати ім'я файлу-бібліотеки, де знаходиться процедура, що шукається. Бібліотеки Wip API розміщуються в системному каталозі Windows, тому достатньо лише назва файлу. Якщо ви звертаєтеся до DLL, яка знаходиться в довільному місці, потрібно записати повний шлях до цього файлу.

Опис оператора Declare зазвичай займає досить багато місця і не міститься в один рядок у вікні коду. Тому ми рекомендуємо дотримуватися при написанні програм будь-якої певної схеми перенесення рядків, наприклад:

Declare Function GetTempPath _ Lib “kernel32” Alias ​​“GetTempPathA” _ (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long

І тут всі основні елементи опису рознесені різні рядки і тому добре читаються.

Порада 2. Будьте особливо уважні під час роботи з DLL-функціями

Використання Win API та різноманітних DLL-функцій суттєво розширює функціональні можливості VB та найчастіше дозволяє підвищити продуктивність програм. Однак розплата за це - ризик зниження надійності роботи програми, особливо в процесі її налагодження.

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

Використання безпосередньо функцій Windows API або інших DLL-бібліотек знімає такий контроль за передачею даних та процесом виконання коду за межами середовища VB. Тому помилка у зверненні до зовнішніх функцій може призвести до непрацездатності та VB та операційної системи. Це особливо актуально на етапі розробки програми, коли наявність помилок – справа цілком природна. Таким чином, застосовуючи ширші можливості функцій базового шару системи, програміст бере він відповідальність за правильність їх застосування.

Проблема ускладнюється ще й тим, що різні мови програмування використовують різні способи передачі параметрів між процедурами. (Точніше, різні способи передачі використовуються за замовчуванням, так як багато мов можуть підтримувати кілька способів.) Win API реалізовані на C/C++ і застосовують угоди про передачу параметрів, прийняті в цій системі, які відрізняються від звичного VB варіанта.

У зв'язку з цим слід зазначити, що поява вбудованих VB аналогів API-функцій виправдано саме адаптацією останніх до синтаксису VB і реалізацією відповідного механізму контролю обміну даними. Звернемо також увагу, що на етапі дослідної налагодження програми при створенні модуля, що виконується, краще використовувати варіант компіляції P-code замість Native Code (машинний код). У першому випадку програма працюватиме під управлінням інтерпретатора - повільніше проти машинним кодом, але надійніше з погляду можливого помилкового на операційну систему і забезпечуючи зручніший режим виявлення можливих помилок.

Порада 3. Десять рекомендацій Дена Епплмана щодо надійного API-програмування в середовищі VB

Використання функції API вимагає більш уважного програмування з використанням деяких не дуже звичних методів звернення до процедур (проти VB). Далі ми постійно звертатимемося до цих питань. А зараз наведемо виклад сформульованих Деном Епплманом порад на цю тему (їхній перший варіант з'явився ще 1993 року) з деякими нашими доповненнями та коментарями.

1. Пам'ятайте про ByVal.Найчастіша помилка, що здійснюється при зверненні до функцій API і DLL, полягає в некоректному використанні ключового слова ByVal: його або забувають ставити, або, навпаки, ставлять, коли в ньому немає потреби.

На цих прикладах показано вплив оператора ByVal на передачу параметрів

Тип параметра З ByVal Без ByVal
Integer У стек міститься 16-розрядне ціле У стек міститься 32-розрядна адреса 16-розрядного цілого
Long У стек міститься 32-розрядне ціле У стек міститься 32-розрядна адреса 32-розрядного цілого
String Рядок перетворюється на формат, що використовується в С (дані та завершальний нульовий байт). 32-розрядна адреса нового рядка міститься у стек У стек міститься VB-дескриптор рядка. (Такі дескриптори ніколи не використовуються самим Windows API і розпізнаються тільки в DLL, реалізованих спеціально для VB.)

Тут слід нагадати, що передача параметрів у будь-якій системі програмування, у тому числі і VB, виконується двома основними шляхами: посилання (ByRef) або значення (ByVal). У першому випадку передається адреса змінної (цей варіант використовується у VB за замовчуванням), у другому – її величина. Принципова відмінність полягає в тому, що за допомогою посилання забезпечується повернення в програму, що викликає, зміненого значення переданого параметра.

Щоб розібратися в цьому, проведіть експеримент за допомогою таких програм:

Dim v As Integer v = 2 Call MyProc(v) MsgBox “v = “ & v Sub MyProc (v As Integer) v = v + 1 End Sub

Запустивши на виконання цей приклад, ви отримаєте повідомлення зі значенням змінної, рівним 3. Справа в тому, що в даному випадку в підпрограму MyProc передається адреса змінної v, фізично створеної програми, що викликає. Тепер змініть опис процедури на

Sub MyProc (ByVal v As Integer)

В результаті при виконанні тесту ви отримаєте v = 2, тому що в процедуру передається лише вихідне значення змінної - результат виконаних з ним операцій не повертається до програми, що викликає. Режим передачі значення можна змінити також за допомогою оператора Call наступним чином:

Sub MyProc (v As Integer) ... Call MyProc ((v)) '(v) - дужки вказують режим передачі _ за значенням.

Однак при зверненні до внутрішніх VB-процедур використання в операторі Call ключового слова ByVal заборонено - замість нього застосовуються круглі дужки. Цьому є пояснення.

У класичному випадку (С, Fortran, Pascal) відмінність режимів ByRef і ByVal залежить від того, що саме міститься в стек обміну даними - адреса змінної або її значення. В Basic історично використовується варіант програмної емуляції ByVal - у стеку завжди знаходиться адреса, але тільки при передачі за значенням для цього створюється тимчасова змінна. Щоб відрізнити ці два варіанти (класичний і Basic), використовуються різні способи опису режиму ByVal. Зазначимо, що емуляція режиму ByVal в VB забезпечує більш високу надійність програми: переплутавши форму звернення, програміст ризикує лише тим, що в програму, що викликає, повернеться (або не повернеться) виправлене значення змінної. У «класичному» варіанті така плутанина може призвести до фатальної помилки під час виконання процедури (наприклад, коли замість адреси пам'яті використовуватиметься значення змінної, рівне, скажімо, нулю).

DLL-функції реалізовані за «класичними» принципами і тому вимагають обов'язкового опису того, як відбувається обмін даними з кожним з аргументів. Саме цій меті служать оголошення функцій через опис Declare (точніше, списку аргументів, що передаються). Найчастіше передача параметрів у функцію Windows API або DLL виконується за допомогою ключового слова ByVal. Причому воно може бути задане як в операторі Declare, так і безпосередньо під час виклику функції.

Наслідки неправильної передачі параметрів легко передбачити. У разі отримання явно неприпустимої адреси, вам буде видано повідомлення GPF (General Protection Fault - помилка захисту пам'яті). Якщо ж функція отримає значення, що збігається з допустимою адресою, то функція API залізе в чужу область (наприклад, в ядро ​​Windows) з усіма катастрофічними наслідками, що звідси випливають.

2. Перевірте тип параметрів, що передаються.Не менш важливі правильне число і тип параметрів, що передаються. Необхідно, щоб оголошені в Declare аргументи відповідали очікуваним параметрам функції API. Найпоширеніший випадок помилки у передачі параметрів пов'язані з різницею між NULL і рядком нульової довжини - слід пам'ятати, що це одне й те.

3. Перевіряйте тип значення, що повертається.

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

  • DLL-функція, яка не повертає значення (аналог void в 'C'), має бути оголошена як VB Sub.
  • функцію API, що повертає ціле значення (Integer або Long), може бути визначена або як Sub, або як Function, що повертає значення відповідного типу.
  • жодна з функцій API не повертає числа з плаваючою точкою, але деякі DLL можуть повертати такий тип даних.

4. З великою обережністю використовуйте конструкцію As Any.Багато функцій Windows API мають можливість приймати параметри різних типів і використовують при цьому поводження із застосуванням конструкції As Any (інтерпретація типу виконується залежно від значення інших параметрів, що передаються).

Хорошим рішенням у разі може бути використання кількох псевдонімів (Alias) функції зі створенням двох і більше оголошень однієї і тієї ж функції, причому у кожному з описів вказуються параметри певного типу.

5. Не забувайте ініціалізувати рядки.У Win API існує безліч функцій, що повертають інформацію шляхом завантаження даних у рядкові буфери, що передаються як параметр. У своїй програмі ви можете як би все зробити правильно: не забути про ByVal, правильно передати параметри в функцію. Але Windows не може перевірити, наскільки великий розмір виділеного під рядок ділянки пам'яті. Розмір рядка повинен бути достатнім для розміщення всіх даних, які можуть бути вміщені в нього. Відповідальність за резервування буфера необхідного розміру лежить на VB-програміст.

Слід зазначити, що в 32-розрядних Windows при використанні рядків здійснюється перетворення з Unicode (двобайтове кодування) в ANSI (однобайтове) і назад, причому з урахуванням національних установок системи. Тому для резервування буферів часом зручніше використовувати байтові масиви замість рядкових змінних. (Докладніше про це буде розказано нижче.)

Найчастіше функції Win API дозволяють самим визначити максимальний розмір блоку. Зокрема, іноді для цього потрібно викликати іншу функцію API, яка підкаже розмір блоку. Наприклад, GetWindowTextLength дозволяє визначити розмір рядка, необхідний розміщення заголовка вікна, одержуваного функцією GetWindowText. У цьому випадку Windows гарантує, що ви не вийдете за кордон.

6. Обов'язково використовуйте Option Explicit.

7. Уважно перевіряйте значення параметрів та величин, що повертаються. VB має гарні можливості для перевірки типів. Це означає, що, коли ви намагаєтеся передати неправильний параметр у функцію VB, найгірше, що може статися, - ви отримаєте повідомлення про помилку від VB. Але цей механізм, на жаль, не працює при зверненні до функцій Windows API.

Windows 9x має вдосконалену систему перевірки параметрів для більшості функцій API. Тому наявність помилки в даних зазвичай не викликає фатальної помилки, проте визначити, що ж стало її причиною - не так просто.

Тут можна порадити використати кілька способів налагодження помилки даного типу:

  • використовуйте покроковий режим налагодження або Debug.Print для перевірки кожного підозрілого виклику функції API. Перевірте результати цих викликів, щоб переконатися, що все в межах норми та функція коректно завершилася;
  • Використовуйте Windows-відладчик типу CodeView та налагоджувальну версію Windows (є у Windows SDK). Ці засоби можуть виявити помилку параметрів та щонайменше визначити, яка функція API призводить до помилки;
  • використовуйте додаткові засоби третіх фірм для перевірки типів параметрів та допустимості їх значень. Такі засоби можуть не тільки знаходити помилки параметрів, але навіть вказати на рядок VB коду, де відбулася помилка.

Крім того, необхідно обов'язково перевіряти результат виконання API-функції.

8. Пам'ятайте, що цілі числа в VB і Windows - не одне й те саме.Насамперед слід пам'ятати, що під терміном «Integer» у VB розуміється 16-розрядне число, у документації Win 32 - 32-разрядное. По-друге, цілі числа (Integer і Long) у VB - це величини зі знаком (тобто один розряд використовується як знак, інші - як мантиса числа), у Windows - використовуються лише невід'ємні числа. Ця обставина потрібно мати на увазі, коли ви формуєте параметр за допомогою арифметичних операцій (наприклад, обчислюєте адресу за допомогою підсумовування деякої бази і зміщення). Для цього стандартні арифметичні функції VB не підходять. Що робити в цьому випадку, ми поговоримо окремо.

9. Уважно стежте за іменами функцій.На відміну від Win16 імена всіх функцій Win32 API є чутливими до точного використання малих і великих літер (у Win16 такого не було). Якщо ви десь застосовуєте маленьку літеру замість великої або навпаки, то потрібна функція не буде знайдена. Слідкуйте також за правильним використанням суфікса A або W у функціях, які застосовують рядкові параметри. (Докладніше про це – див. нижче.)

10. Найчастіше зберігайте результати роботи.Помилки, пов'язані з неправильним використанням DLL і Win API, можуть призводити до аварійного завершення роботи VB-середовища, а можливо, і всієї операційної системи. Ви повинні подбати про те, щоб написаний вами код перед тестовим запуском було збережено. Найпростіше - це встановити режим автоматичного запису модулів проекту перед запуском проекту серед VB.

Після прочитання попередньої поради може виникнути думка, що використання функцій Win API – справа ризикована. Певною мірою це так, але тільки в порівнянні з безпечним програмуванням, що надається самим VB. Але при вмілому їх застосуванні та знанні можливих підводних каменів цей ризик мінімальний. До того ж повністю відмовитися від застосування Win API часто просто неможливо - вони все одно знадобляться при серйозній розробці.

До того ж раніше ми згадували про «підводні» камені для широкого класу DLL. У випадку з Win API все набагато простіше, тому що тут чітко уніфікована форма звернення до цих функцій. При цьому слід мати на увазі такі основні моменти:

  1. Функції Win32 API є функціями, тобто процедурами типу Function (у Win16 API було багато підпрограм Sub). Усе це функції типу Long, тому їх описи записуються у такому виде: Declare Function name ... As Long ‘ тип функції _ визначається явному вигляді

    Declare Function name& ' тип функції _ визначається за допомогою суфікса

    Звернення до функції API виглядає так:

Result& = ApiName& ([ СписокАргументів]
  1. Найчастіше значення функції, що повертається, є кодом завершення операції. Причому ненульове значення означає у разі нормальне завершення, нульове - помилку. Зазвичай (але не завжди) можна уточнити характер помилки за допомогою звернення до функції GetLastError. Опис цієї функції має такий вигляд: Declare Function GetLastError& Lib “kernel32” ()

    УВАГА!При роботі в середовищі VB для отримання значення уточненого коду помилки краще використовувати властивість LastDLLError об'єкта Err, тому що іноді VB обнулює функцію GetLastError у проміжку між зверненням до API та продовженням виконання програми.

    Інтерпретувати код, який повертається GelLastError, можна за допомогою констант, записаних у файлі API32.TXT, з іменами, що починаються з суфіксу ERROR_.

    Найбільш типові помилки мають такі коди:

    • ERROR_INVALID_HANDLE = 6& - неправильний описувач
    • ERROR_CALL_NOT_IMPLEMENTED = 120& - виклик у Windows 9x функції, доступної тільки для Windows NT
    • ERROR_INVALID_PARAMETER = 87& - неправильне значення параметра

    Однак багато функцій повертають значення деякого запитуваного параметра (наприклад, OpenFile повертає значення описувача файлу). У разі помилка визначається якимось іншим спеціальним значенням Return&, найчастіше 0 чи –1.

  2. Win32 API використовують строго фіксовані способи передачі найпростіших типів даних. а) ByVal ... As Long

    З допомогою змінних типу Long виконується щонайменше 80% передачі аргументів. Зверніть увагу, що аргумент завждисупроводжується ключовим словом ByVal, а це, крім іншого, означає, що виконується одностороння передача даних - від VB-програми до API-функції.

    Б) ByVal ... As String

    Цей тип передачі також зустрічається досить часто, причому з аргументом також завждизастосовується ByVal. При виклику API-функції у стек записується адреса рядка, тому в цьому випадку можливий двосторонній обмін даними. Під час роботи з рядками потрібно враховувати кілька небезпек.

    Перша - резервування пам'яті під рядок проводиться у програмі, що викликає, тому якщо API-функція буде заповнювати рядки, то потрібно перед її викликом створити рядок необхідного розміру. Наприклад, функція GetWindowsDirectory повертає шлях до каталогу Windows, який не повинен займати більше 144 символів. Відповідно звернення до цієї функції має виглядати приблизно так:

    WinPath$ = Space$(144) ' резервуємо рядок в _ 144 символу Result& = GetWindowsDirectory& (WinTath$, 144) _ 'заповнення буфера ' Result& - фактичне число символів в імені _ каталогу WinPath$ = Left$(WinPath, Result&)

    Друга проблема полягає в тому, що при зверненні до API-функції проводиться перетворення вихідного рядка на її деяке внутрішнє уявлення, а при виході з функції - навпаки. Якщо за часів Win16 ця операція полягала лише у додаванні нульового байта наприкінці рядка, то з появою Win32 до цього додалася трансформація двобайтного кодування Unicode в ANSI і навпаки. (Про це докладно йшлося у статті «Особливості роботи з рядковими змінними в VB», Комп'ютерПрес 10'99 та 01'2000). Зараз же тільки зазначимо, що за допомогою конструкції ByVal... As String можна обмінюватися рядками лише із символьними даними.

    В) ... As Any

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

    Г) ... As UserDefinedType

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

    Форма структури даних визначається конкретною API-функцією, і програміст лежить відповідальність правильним чином описати і зарезервувати їх у зухвалої програмі. Така конструкція завждивикористовується безслова ByVal, тобто в даному випадку виконується передача за посиланням – у стек записується адреса змінної.

Приклад звернення до функції API

Проілюструємо сказане вище з прикладу використання двох корисних функцій роботи з файлами - lopen і lread, які описуються так:

Declare Function lopen Lib “kernel32” _ Alias ​​“_lopen” (_ ByVal lpFileName As String, _ ByVal wReadWrite As Long) As Long Declare Function lread Lib “kernel32” _ Alias ​​“_lread” (_ ByVal hFile As Long, lpBuff _ ByVal wBytes As Long) As Long

У VB їх аналогами - у разі точними - є оператори Open і Get (для режиму Binary). Звернемо відразу увагу використання ключового слова Alias ​​в оголошенні функції - це саме той випадок, коли без нього не обійтися. Ці назви функції в бібліотеці починаються з символу підкреслення (типовий стиль для мови C), що не дозволяється VB.

Операція відкриття файлу може виглядати так:

Const INVALID_HANDLE_VALUE = -1 ' невірне _ значення описувача lpFileName$ = “D:\calc.bas” ' ім'я файлу wReadWrite& = 2 ' режим “читання-запису” hFile& = lopen(lpFileName$, wReadWrite&) _ ' визначаємо = INVALID_HANDLE_VALUE Then _ ' помилка відкриття файлу ' уточнюємо код помилки CodeError& = Err.LastDllError 'CodeError& = GetLastError _ ' ця конструкція не працює End If

Тут слід звернути увагу на два моменти:

  • як значення функції ми отримуємо значення описника файлу. Помилки відповідає значення -1;
  • саме в даному випадку не спрацьовує звернення до функції GetLastError – для отримання уточненого значення помилки ми звернулися до об'єкта Err (про можливість такої ситуації ми говорили вище).

Далі можна читати вміст файлу, але це передбачає, що програміст повинен мати деяке уявлення про його структуру (як і це відбувається при роботі з довільними двійковими файлами). У цьому випадку звернення до функції lread може виглядати так:

Dim MyVar As Single wBytes = lread (hFile&, MyVar, Len(MyVar) ' читання речовинного числа, 4 байти ' wBytes - число фактично прочитаних даних, '-1 - помилка... Type MyStruct x As Single i As Integer End Type Dim MyVar As MyStruct wBytes = lread (hFile&, MyVar, Len(MyVar)) ' читання структури даних, 6 байтів

Ще раз зверніть увагу: другий аргумент функції передається за посиланням, решта – за значенням.

Dim MyVar As String MyVar = Space$(10) 'резервуємо змінну для 10 символів wBytes = lread (hFile&, ByVal MyVar, Len(MyVar)) ' читання символьного рядка, 10 символів

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

Читання вмісту файлу в масиві (для простоти будемо використовувати одновимірний байтовий масив) виконується так:

Dim MyArray(1 To 10) As Byte wBytes = lread (hFile&, MyArray(1), _ Len(MyArray(1))* 10) ‘ читання 10 елементів масиву

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

WBytes = lread (hFile&, MyArray(4), _ Len(MyArray(1))* 5) читання елементів масиву з 4-го по 8-й

Порада 5. Використовуйте Alias ​​для передачіта параметрів As Any

Тут на основі попереднього прикладу ми розкриємо суть четвертої ради Дена Епплмана.

Працюючи з функцією lread, слід пам'ятати, що при зверненні до неї з використанням рядкової змінної необхідно використовувати ключове слово ByVal (інакше повідомлення про нелегальну операцію не уникнути). Щоб убезпечити себе, можна зробити додатковий спеціальний опис цієї функції для роботи тільки з рядковими змінними:

Declare Function lreadString Lib “kernel32” _ Alias ​​“_lread” (_ ByVal hFile As Long, ByVal lpBuffer As String, _ ByVal wBytes As Long) As Long

При роботі з цим описом вказувати ByVal при зверненні вже не потрібно:

WBytes = lreadString (hFile&, MyVarString, _ Len(MyVarString)) ‘

Здавалося б, синтаксис оператора Declare дозволяє зробити такий спеціальний опис для масиву:

Declare Function lreadString Lib “kernel32” Alias ​​“_lread” (_ ByVal hFile As Long, lpBuffer() As Byte, _ ByVal wBytes As Long) As Long

Проте звернення

WBytes = lreadArray (hFile&, MyArray(), 10)

неминуче призводить до фатальної помилки програми.

Це продовження розмови про особливості обробки рядкових змінних Visual Basic: VB використовує двобайтну кодування Unicode, Win API - однобайтну ANSI (причому з форматом, прийнятим в С, - з нульовим байтом в кінці). Відповідно при використанні рядкових змінних як аргумент завжди автоматично проводиться перетворення з Unicode в ANSI при виклику API-функції (точніше, DLL-функції) та зворотне перетворення при поверненні.

Висновок з цього простий: за допомогою змінних String можна обмінюватися символьними даними, але їх не можна використовувати для обміну довільною двійковою інформацією (як це було при роботі з 16-розрядними версіями VB). У разі краще використовувати одновимірний байтовий масив.

Як відомо, тип String можна використовувати для опису структури користувача. У зв'язку з цим слід пам'ятати таке:

  • Категорично не можна використовувати для звернення до Win API конструкцію наступного виду: Type MyStruct x As Single s As String рядок змінної довжини

    У разі рядка змінної довжини у складі структури передається дескриптор рядка з усіма наслідками у вигляді помилки виконання програми.

  • Можна як елемент структури рядок фіксованої довжини: Type MyStruct x As Single s As String*8 ‘ рядок фіксованої довжини End Type

При цьому провадиться відповідне перетворення кодувань.

І останнє зауваження: застосовувати масив рядкових змінних (як фіксованої, так і змінної довжини) при зверненні до функції API не можна в жодному разі. Інакше поява «нелегальної операції» буде гарантованою.

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

Зазначимо у зв'язку з цим, що змішане програмування - це звичайне явище для реалізації досить складного докладання. Дійсно, кожна мова (точніше система програмування на базі мови) має свої сильні і слабкі сторони, тому цілком логічно використовувати переваги різних інструментів для вирішення різних завдань. Наприклад, VB - для створення інтерфейсу користувача, С - для ефективного доступу до системних ресурсів, Fortran - для реалізації чисельних алгоритмів.

Думка автора така: серйозне заняття програмуванням вимагає від розробника володіння принаймні двома інструментами. Зрозуміло, в сучасних умовах чіткого поділу праці дуже складно бути відмінним експертом навіть за двома системами, тому більш логічною є схема «основної та допоміжної мови». Ідея тут полягає в тому, що навіть поверхове знання «допоміжної» мови (написання досить простих процедур) може помітно підвищити ефективність застосування «основної». Зазначимо, що знання VB хоча б як допоміжне є сьогодні практично обов'язковою вимогою для професійного програміста. До речі, за часів DOS для будь-якого програміста, зокрема Basic, було вкрай бажаним знання основ Асемблера.

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

При вивченні міжпроцедурного інтерфейсу слід звернути увагу на такі можливі «підводні камені»:

  • Різні мови можуть використовувати різні угоди про правила написання ідентифікаторів. Наприклад, часто використовується знак підкреслення початку імені процедури, що заборонено в VB. Ця проблема легко вирішується за допомогою ключового слова Alias ​​в операторі Declare (див. приклад поради 2.3).
  • Може бути використана різна послідовність запису аргументів, що передаються в стек. Наприклад, за часів DOS (чесно зізнаюся – не знаю, як це виглядає зараз у середовищі Windows), C записував аргументи з кінця списку, інші мови (Fortran, Pascal, Basic) – з початку.
  • За замовчуванням використовуються різні принципи передачі параметрів - за посиланням або значенням.
  • Різні принципи зберігання рядкових змінних. Наприклад, в C (так само як у Fortran і Pascal) довжина рядка визначається нульовим байтом у її кінці, а в Basic довжина записується у явному вигляді в дескрипторі рядка. Зрозуміло, потрібно пам'ятати можливість використання різних кодувань символів.
  • При передачі багатовимірних масивів слід пам'ятати, що можливі різні варіанти перетворення багатовимірних структур на одновимірні (починаючи з першого індексу або з останнього, стосовно двовимірних масивів - «по рядках» або «по стовпчикам»).

З урахуванням цього можна сформулювати такі рекомендації:

  • Використовуйте найпростіші, перевірені способи передачі аргументів у функції DLL. Стандарти, прийняті для Win API, цілком підходять як зразок.
  • У жодному разі не передавайте масиви рядкових змінних.
  • Дуже уважно використовуйте передачу простих рядкових змінних та багатовимірних масивів.
  • Обов'язково спеціальним чином перевіряйте працездатність механізму передачі аргументів у процедуру, що викликається, і назад. Напишіть спеціальний тест для перевірки даних. Окремо перевірте правильність передачі кожного аргументу. Наприклад, якщо у вас є процедура з кількома аргументами, перевірте спочатку коректність передачі кожного параметра для варіанта з одним аргументом, а потім - для всього списку.

А що робити, якщо DLL-функція вже написана, наприклад, на Фортрані, але її вхідний інтерфейс не дуже добре вписується у наведені вище стандарти VB? Тут можна дати дві поради. Перший: напишіть тестову DLL-функцію і з її допомогою постарайтеся методом спроб та помилок підібрати потрібне звернення з VB-програми. Другий: напишіть процедуру-перехідник на тому ж Фортрані, який би забезпечував простий інтерфейс між VB та DLL-функцією з перетворенням простих структур даних на складні (наприклад, перетворював багатовимірний байтовий масив у рядковий масив).

Отже: використовуйте DLL функції. Але зберігайте пильність.

Комп'ютерПрес 9"2000

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

Перш за все, якщо ви досі не до кінця розумієте, що таке API (Application Programming Interface - інтерфейс програмування додатків), прочитайте пояснення від Skillcrush, а потім першу частину цієї статті, щоб надолужити втрачене.

"API" неймовірно велика концепція - щоразу, коли ваш додаток "спілкується" з іншим додатком, це відбувається через якийсь API. Компоненти всередині вашої власної програми, на зразок різних частин Rails, також спілкуються один з одним через API. Вони є більш менш незалежними субдодатками, які передають дані, необхідні кожному з них для виконання власних специфічних завдань. У світі додатків все є API!

Коли ви створюєте програми з більш динамічною фронтенд-функціональністю (як односторінкові Javascript-додатки, так і прості програми з окремими AJAX-дзвінками), вони будуть спілкуватися з Rails-бекендом через ваш власний API, який насправді просто додаткова пара-трійка рядків коду , що говорить вашим контролерам, як віддати JSON або XML замість HTML.

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

Пункти для роздумів

Перегляньте запитання та перевірте, чи знаєте на них відповіді. Перевірте себе знову після виконання завдання.

  • Як Rails розуміє, який тип файлу ви очікуєте у відповідь, коли надсилаєте HTTP-запит.
  • У чому мета методу #respond_to ?
  • Як повернути об'єкт користувача (User), при цьому вказати атрибути, які не хочете включати до цього об'єкта (тобто, ви не можете просто повернути User.first)?
  • Назвіть 2 кроки, що виконуються "за лаштунками" методу #to_json .
  • Як вказати дії контролера, що потрібно рендерувати лише повідомлення про помилку?
  • Як створити власне повідомлення про помилку?
  • Чому ви не можете використовувати методи автентифікації контролера, які базуються на сесіях, якщо хочете дозволити програмно підключатися до вашого API?
  • Що таке "Сервіс-орієнтована архітектура"?

Основи API

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

Однак, часто ви хочете зробити запит, який не вимагає переживати головний біль від використання браузера. Вас може не турбувати структура сторінки (HTML), але натомість ви хочете отримати чисті дані. Допустимо, ви хочете отримати список усіх користувачів. Ви можете запросити щось на зразок http://yourapplication.com/users , що напевно запустить дію #index і відрендерує список усіх користувачів програми.

Але навіщо морочитися з цією зайвою інформацією, якщо все чого ви хочете - це отримати список користувачів? Найпростішим варіантом буде відправити запит на ту саму URL, вказавши очікування JSON або XML відповіді натомість. Якщо ви правильно налаштуєте ваш Rails-контролер, ви отримаєте простий JSON об'єкт-масив, що містить всіх користувачів. Прекрасно!

Той самий принцип застосовується, коли ви спілкуєтеся із зовнішнім API. Скажімо, ви хочете отримати недавні "твіти" користувача з Twitter. Вам потрібно лише повідомити вашому Rails-додатку як взаємодіяти з API Twitter"а (тобто аутентифікувати себе), відправити запит і обробити набір "твітів", який буде повернутий.

Створення API

Ви можете захотіти зробити ваше Rails-додаток чистим бекенд API для фронтенд веб-сторінок, або просто захочете навчитися посилати JSON, коли фронтенд запитує його. Цей розділ не висвітлить, як створювати повноцінні RESTful API з функціями автентифікації. Це плавне введення у поводження з вашим додатком як з API.

Основи

Якщо ви хочете, щоб ваш Rails-додаток повертав JSON замість HTML, вам потрібно буде сказати вашому контролеру, щоб він це робив. Саме чудове те, що одна і та ж дія контролера може повертати різні типи в залежності від того, чи робить ваш користувач звичайний запит із браузера або звертається до API через командний рядок. Це визначає який тип запиту було зроблено, ґрунтуючись на розширенні запитуваного файлу, наприклад example.xml або example.json .

Ви можете перевірити, що Rails "думає" про очікуваний тип файлу, перевіривши серверний лог:

Started GET "/posts/new" for 127.0.0.1 at 2013-12-02 15:21:08 -0800 Processing by PostsController#new as HTML

Перший рядок каже вам який URL був запрошений, а другий повідомляє, куди він був направлений і як Rails його обробляє. Якби ви використовували розширення.json , це виглядало б так:

Started GET "/posts.json" for 127.0.0.1 at 2013-12-04 12:02:01 -0800 PostsController#index as JSON

Якщо у вас є запущена тестова програма, спробуйте запитати різні URL. Якщо ваш контролер не вміє їх обробляти, ви можете отримати помилку, але все одно повинні бачити, що Rails розуміє під вашими запитами.

Рендеринг JSON або XML

Коли ви вирішите, що хочете відповідати на запити за допомогою JSON або XML, вам потрібно буде повідомити вашого контролера, що потрібно рендерувати JSON або XML замість HTML. Один із способів зробити це – використовувати метод #respond_to:

Class UsersController< ApplicationController def index @users = User.all respond_to do |format| format.html # index.html.erb format.xml { render xml: @users } format.json { render json: @users } end end end

В даному випадку #respond_to передає в блок об'єкт формату, до якого ви можете додати відповідний виклик рендерингу. Якщо ви нічого не зробите, буде рендер html з використанням стандартного Rails-шаблону (в цьому прикладі app/views/index.html.erb).

Функція #render досить розумна, щоб зрозуміти, як рендерувати широкий спектр форматів. Коли ви передаєте їй ключ:json, вона викличе #to_json на значенні, в даному прикладі @users. Це перетворює ваш(і) Ruby-об'єкт(и) в JSON-рядки, які будуть передані додатку, що запитує.

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

Вказівка ​​атрибутів, що повертаються

Допустимо, ви хочете переконатися, що не повертаєте email-адресу користувача разом з об'єктом користувача (User). У цьому випадку ви захочете змінити атрибути, які будуть повертатися, модифікуючи те, що робить метод #to_json .

Раніше ви просто перевизначили б метод #to_json своєю версією, але тепер вам це не знадобиться - насправді, ви натомість перевизначите метод #as_json . Метод #as_json використовується в методі #to_json, так що його модифікація неявно змінений результат #to_json, але досить специфічним способом.

#to_json робить дві речі: запускає #as_json і отримує хеш атрибутів, які будуть відрендеровані в JSON. Потім він проводить рендеринг у JSON, використовуючи ActiveSupport::json.encode. Отже, модифікуючи #as_json, ви більш конкретно вказуєте ту частину методу #to_json, яку насправді хочете змінити.

У нашому випадку ми робимо це модифікуючи #as_json у нашій моделі так, щоб повертати лише необхідні нам атрибути:

# app/models/user.rb class User< ActiveRecord::Base # Вариант 1: Полное переопределение метода #as_json def as_json(options={}) { :name =>self.name ) # НЕ включаємо поле email end # Варіант 2: Використовуємо стандартний метод #as_json def as_json(options=()) super(only: [:name]) end end

Потім, у нашому контролері лише потрібно відрендерити JSON як завжди (у прикладі нижче завжди буде повертатися JSON, незалежно від того, було відправлено HTML-запит чи ні):

# app/controllers/users_controller.rb class UsersController< ApplicationController def index render json: User.all end end

Зауважте, що вам не потрібно самостійно викликати #to_json, коли ви використовуєте #render - він зробить це за вас.

Іноді Heroku може вимагати додаткові кроки для коректного відображення сторінок з помилками. Подивіться. Вам може знадобитися спершу видалити статичні сторінки з директорії app/public.

Забезпечення безпеки ззовні

Допустимо, ви хочете дозволити звертатися до API тільки якщо користувач залогінений. Ваша автентифікація в контролері вже робить цю роботу - просто переконайтеся, що у вас встановлений правильний #before_action (наприклад, before_action:require_login). Може знадобитися функціонал, коли і залогінений користувачі можуть переглядати сторінку, але кожен повинен бачити різні дані. Ви не хочете, щоб незалогінені користувачі мали можливість робити запити до API для отримання важливих даних. Аналогічно, ви не бажаєте давати можливість відвідувати певні HTML-сторінки неавторизованим користувачам.

Якщо ви хочете обробляти запити з програми, яка не є браузером (наприклад, з командного рядка), ви не можете покладатися на браузерні куки для аутентифікації. Саме тому більшість API використовує власні токени як частину процесу аутентифікації. Ми поговоримо трохи більше про токені у наступному уроці.

Наступні кроки

Тепер у вас є навички використання вашого Rails-програми для віддачі не тільки HTML, але й будь-якого іншого формату. Якщо ви хочете піти далі і дозволити іншим розробникам створювати щось із використанням вашої платформи (наприклад, щоб вони могли робити програмні запити замість аутентифікації як користувача), вам знадобиться зробити вашу API-систему набагато надійнішою. Ми не будемо висвітлювати все це тут, але подивіться такі матеріали:

  • Стаття Building Awesome Rails APIs містить опис найкращих підходів для руху від іграшкового додатка у бік стандартів промислових API.

Сервіс-орієнтована архітектура

Настав час представити архітектурний підхід під ім'ям "Сервіс-орієнтована архітектура" (Service-Oriented Architecture, SOA). Основна ідея полягає в тому, що ваш додаток складатиметься з безлічі сервісів, на кшталт системи оплати, реєстрації користувачів, модуля рекомендацій і т.д. Замість того, щоб створювати все це всередині однієї головної програми, ви розбиваєте підсистеми на повністю незалежні шматочки, які взаємодіють один з одним, використовуючи внутрішні API-інтерфейси.

Це добре з багатьох причин. Завдяки тому, що кожен шматочок вашої програми не дбає про те, як працюють інші частини, і знає тільки як запросити дані через їх API, ви можете робити значні зміни в коді сервісу, і решта додатків буде працювати, як і раніше. Ви можете повністю замінити один сервіс на інший, і поки він взаємодіє, використовуючи ті ж API-методи, це пройде дуже гладко. Ви можете використовувати зовнішні API як частину вашої програми (наприклад, платіжні системи) замість написання власного. Ви можете створити PHP-додаток, що взаємодіє з Python-додатком, що взаємодіє з Rails-додатком, і все буде працювати, адже вони спілкуються між собою за допомогою API.

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

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

Одним із найвідоміших випадків переходу на сервіс-орієнтовану архітектуру є Amazon.com. Якось у 2002 році Джефф Безос прямо заявив, що всі робочі групи повинні перейти на СОА, або будуть звільнені. Сумно відомий пост із блогуспівробітника Google, призначений внутрішньокорпоративних цілей, але який випадково став відкритим для публіки, розповідав про потужність Amazon з використанням СОА. Це чудове чтиво, так що обов'язково його оцініть, але основні тези листа Безоса винесені в наступні цитати з посту:

1) Усі команди відтепер надають свої дані та функціональність через інтерфейси сервісів.

2) Команди повинні взаємодіяти один з одним за допомогою цих інтерфейсів.

3) Інші форми міжпроцесної взаємодії заборонені: жодних прямих посилань, жодного безпосереднього читання даних іншої команди, жодних моделей спільної пам'яті, жодних "бекдорів" тощо. Єдиний дозволений спосіб взаємодії – звернення до інтерфейсу сервісів через мережу.

4) Будь-яку технологію вони застосовують. HTTP, Corba, Pubsub, власні протоколи - не має значення. Безоса це не хвилює.

5) Всі інтерфейси сервісів, без винятку, повинні бути спроектовані з можливістю управління ззовні. Тобто команда повинна планувати і проектувати так, щоб бути в змозі надати інтерфейс розробникам поза компанією. Жодних винятків.

6) Будь-який, хто проігнорував ці вимоги, буде звільнений.

СОА – це серйозна справа. Безперечно, є багато проблем, які спливають при її використанні - подивіться цей пост про "отримані уроки" Amazon - але вона має неймовірно багато переваг.

Ви, напевно, не турбуватиметеся про СОА, поки створюєте "іграшкові" додатки для самих себе, але це питання безперечно встане перед вами, коли ви почнете працювати на ІТ компанію, тому знайомство з нею - це хороша практика.

Ваша мета

  1. Прочитайте розділ 7 керівництва Rails по контролерам , щоб вивчити рендеринг JSON та XML.
  2. Вони не обов'язкові для перегляду (бо вони йдуть трохи далі, ніж ми зараз підготовлені), але, якщо вам цікаво, погляньте на Railscasts в розділі Додаткових ресурсів внизу уроку, щоб дізнатися більше про переваги API.

Висновок

Ми щільніше попрацюємо з вашим додатком як з API під час курсу Javascript. У цьому курсі ви створите кілька повноцінних (фулл-стек) додатків, що використовують AJAX-дзвінки для кращого інтерфейсу користувача, що за фактом включає рендеринг XML або JSON даних замість повноцінної HTML-сторінки. Потім ви створите кілька односторінкових Javascript-додатків, які покладаються на API, що надається вашим Rails-додатком, для отримання всіх необхідних даних з БД, а в усьому іншому, що працюють на стороні клієнта (в браузері).

Найкращий спосіб розібратися з API - створити та взаємодіяти з ним, на чому ми сфокусуємось у наших проектах.

Можливо, ви бачили термін «API». Операційна система, веб-браузер та оновлення програм часто оголошують про нові API для розробників. Але що таке API?

Інтерфейс прикладного програмування

Термін API є абревіатурою, і він означає "інтерфейс прикладного програмування".

API це як меню в ресторані. У меню наведено список страв, які Ви можете замовити, а також опис кожної страви. Коли Ви вкажете, які пункти меню Ви хочете, кухня ресторану виконує цю роботу та надає готові страви. Ви точно не знаєте як ресторан готує цю їжу, і Вам це не потрібно.

Аналогічно, API надає множину операцій, які можуть використовувати розробники, а також опис того, що вони роблять. Розробнику необов'язково знати, як, наприклад, створюється операційна система та відображається діалогове вікно «Зберегти як». Їм просто потрібно знати, що він доступний для використання у додатку.

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

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

API спрощують життя для розробників

Припустимо, Ви хочете розробити програму для iPhone. Операційна система Apple iOS надає велику кількість інтерфейсів API, як і будь-яка інша операційна система, щоб зробити це простіше для Вас.

Наприклад, якщо Ви бажаєте вбудувати веб-браузер для відображення однієї або декількох веб-сторінок, Вам не потрібно програмувати власний веб-браузер з нуля лише для Вашої програми. Ви
Ви можете використовувати WKWebView API для вбудовування веб-браузера WebKit (Safari) у програму.

Якщо Ви хочете знімати фотографії або відео з камери iPhone, Вам не потрібно писати власний інтерфейс камери. Ви можете використовувати API-інтерфейс камери для вбудовування камери iPhone у свою програму. Якби API не існувало, розробникам програм довелося б створювати власне програмне забезпечення камери та інтерпретувати входи апаратного забезпечення камери. Але розробники операційної системи Apple зробили всю цю важку роботу, тому розробники можуть просто використовувати інтерфейс API камери для вбудовування камери, а потім продовжити написання своєї програми. І коли Apple покращить API-інтерфейс камери, всі програми, які використовують його, автоматично скористаються цим покращенням.

Це стосується всіх платформ. Наприклад, Ви хочете створити діалогове вікно Windows? Для цього є API. Бажаєте підтримувати аутентифікацію відбитків пальців на Android? Для цього є API, тому Вам не потрібно тестувати кожен датчик відбитків пальців будь-якого виробника Android. Розробникам не потрібно повторно винаходити колесо знову та знову.

API-інтерфейси керують доступом до ресурсів

API-інтерфейси також використовуються для керування доступом до апаратних пристроїв і функцій програмного забезпечення, на використання яких програма може не мати дозволу. Ось чому API часто відіграють велику роль у безпеці.

Наприклад, якщо Ви коли-небудь відвідували веб-сайт і бачили у своєму браузері повідомлення про те, що веб-сайт запитує Ваше точне розташування, цей веб-сайт намагається використовувати геолокацію API у Вашому веб-браузері. Веб-браузери надають API-інтерфейси, щоб веб-розробникам було легко отримати доступ до Вашого розташування - вони можуть просто запитати «де ви?», і браузер зробить важку роботу з доступу до GPS або сусідніх мереж Wi-Fi, щоб знайти Ваше фізичне місцезнаходження.

Однак браузери також надають цю інформацію через API, тому що можна контролювати доступ до неї. Коли веб-сайт хоче отримати доступ до Вашого точного розташування, єдиний спосіб отримати його через API розташування. І, коли веб-сайт намагається використовувати його, Ви, користувач, можете дозволити або відхилити цей запит. Доступ до апаратних ресурсів, таких як датчик GPS, можливий лише через API, тому браузер може контролювати доступ до апаратних засобів та обмежувати можливості програм.

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

Файлові системи, які використовують дозволи, як і Windows, Mac і Linux, мають права, які застосовуються API файлової системи. Типова програма не має прямого доступу до необробленого фізичного жорсткого диска. Натомість програма має отримати доступ до файлів через API.

API використовуються для зв'язку між службами

API також використовуються з інших причин. Наприклад, якщо ви коли-небудь бачили об'єкт Google Карти, вбудований на веб-сайт, цей веб-сайт використовує API Карт Google для вбудовування цієї карти. Google надає API-інтерфейси, подібні до цих, для веб-розробників, які потім можуть використовувати API-інтерфейси, щоб збирати складні об'єкти прямо на своєму веб-сайті. Якщо таких API немає, розробникам, можливо, доведеться створювати свої власні карти та надавати свої власні карти, щоб розмістити невелику інтерактивну картку на веб-сайті.

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

Це стосується багатьох різних онлайн-сервісів. Існують API для запиту на переклад тексту з Google Translate або відображення коментарів Facebook або твітів з Twitter на веб-сайті.

Стандарт OAuth також визначає ряд API, які дозволяють Вам входити на сайт через інший сервіс, наприклад, використовувати облікові записи Facebook, Google або Twitter для входу на новий веб-сайт без створення нового облікового запису користувача тільки для цього сайту. API – це стандартні контракти, які визначають, як розробники взаємодіють із сервісом, та вид продукції, яку розробники повинні очікувати отримати.

Якщо Ви прочитали цю статтю, то у Вас буде найкраще уявлення про те, що таке API. Зрештою, Вам не потрібно знати, що таке API, якщо Ви не розробник. Але якщо Ви бачите, що програмна платформа або служба додали нові API для різних апаратних засобів або послуг, розробникам має бути простіше використовувати такі функції.