Статьи

Создавайте API с помощью Napa

API — одна из самых горячих тем в веб-разработке. С увеличением числа SPA (одностраничных приложений) и увлечением микросервисами API станут еще более популярными. Как разработчики Ruby on Rails, в нашем распоряжении есть удивительная среда, способная создавать API. Хотя Rails является мощным, он также более сложный. Иногда нам нужна более простая, более гибкая структура, которая делает только одну вещь и делает это хорошо. Я думаю, что нашел такую ​​основу. Позвольте мне представить вам структуру, специально разработанную для создания API: Napa .

Napa объединяет такие гемы, как Grape , Roar и ActiveRecord, что позволяет нам создавать мощные API с минимальными усилиями. В этом уроке мы узнаем, как создать API с аутентификацией токена, используя Napa и Devise .

Установка Напа

Напа доступен как драгоценный камень, для которого требуется Ruby 2.0. Сначала нам нужно будет установить его, используя RVM или rbenv. Переключитесь на Ruby 2.0 и установите Napa:

gem install napa --no-ri --no-rdoc

Создание проекта

Сначала создайте проект с помощью генератора Напа:

 napa new contact-service -d=pg

По умолчанию Napa генерирует настроенный проект MySQL. -d=pg

Napa создаст каталог проектов с именем contact-service и сгенерирует все необходимые каталоги и файлы. Проект структурирован следующим образом:

 contact-service
- app
  - apis
  - models
  - representers
- config
- db
- lib
- log
- spec
- Gemfile
- Rakefile

Структура очень похожа на Rails-приложение, но немного проще. Большая часть кода приложения попадает в каталог приложения . Наши API будут в ( apis ) каталоге apis . Модели попадут в каталог моделей , как и Rails. Один из новых битов здесь — это каталог представительств , в котором будут храниться представители рева. Представители преобразуют модели в желаемый вывод JSON. Другие каталоги служат той же цели, что и в приложении Rails.

Перейдите в каталог проекта и установите все гемы:

 cd contact-service
bundle install

После установки гемов мы добавим детали базы данных в .env . Сначала создайте базу данных:

 rake db:create

Давайте перейдем к следующему шагу.

Создание API

Время для хороших вещей, создавая актуальный API. Для этого нам сначала потребуется модель. Создайте модель контакта с некоторыми основными атрибутами, такими как имя, адрес электронной почты и номер телефона:

 napa generate model Contact name:string email:string phone:string

Перенос базы данных:

 rake db:migrate

Хорошо, теперь давайте создадим конечную точку API:

 napa generate api contact

Napa сгенерирует класс API — app / apis / contacts_api.rb и класс представителя — app / представительс / contact_representer.rb . Класс contacts_api.rb должен выглядеть следующим образом:

 class ContactsApi 

По умолчанию Napa предоставляет пустое объявление параметров, которые должны быть приняты API. Это предусмотрено для защиты API от атак. Мы обновим блоки paramspostput

 ...
desc 'Create an contact'
params do
  optional :name, type: String, desc: 'The Name of the contact'
  optional :phone, type: String, desc: 'The Phone of the contact'
  optional :email, type: String, desc: 'The Email Address of the contact'
end
...

...
desc 'Update a contact'
params do
  optional :name, type: String, desc: 'The Name of the contact'
  optional :phone, type: String, desc: 'The Phone of the contact'
  optional :email, type: String, desc: 'The Email Address of the contact'
end
...

Теперь мы обновим класс contact_representer.rb . Добавьте поля модели Contact в классе, который должен быть частью ответов JSON. Обновите класс contact_representer.rb следующим образом:

 class ContactRepresenter 

Последняя оставшаяся часть — добавить API в application_api.rb , который монтирует API:

 class ApplicationApi  '/contacts'

  add_swagger_documentation
end

Увольнение некоторых запросов

Наш API почти готов. Давайте проверим это, используя curl Сначала запустите сервер разработки:

 napa server

Теперь откройте другой терминал, чтобы мы могли запускать запросы в API. Сначала создайте контакт:

 curl -X POST -d name="Devdatta Kane" -d email="[email protected]" -d phone="25451512544" http://localhost:9393/contacts

Ответ Напы всегда заключен в элемент data

 {
  "data": {
    "object_type": "contact",
    "id": "1",
    "name": "Devdatta Kane",
    "email": "[email protected]",
    "phone": "25451512544"
  }
}

Теперь, когда мы создали контакт, давайте попробуем получить все контакты:

 curl -X GET http://localhost:9393/contacts

Ответом будет массив элементов.

 {
  "data": [
    {
      "object_type": "contact",
      "id": "1",
      "name": "Devdatta Kane",
      "email": "[email protected]",
      "phone": "25451512544"
    }
  ]
}

Мы можем получить один контакт, передав идентификатор контакта:

 curl -X GET http://localhost:9393/contacts/1

Который отвечает:

 {
  "data": {
    "object_type": "contact",
    "id": "1",
    "name": "Devdatta Kane",
    "email": "[email protected]",
    "phone": "25451512544"
  }
}

Попробуйте обновить контактные данные:

 curl -X PUT -d email="[email protected]" http://localhost:9393/contacts/1

Напа возвращает обновленный объект:

 {
  "data": {
    "object_type": "contact",
    "id": "1",
    "name": "Devdatta Kane",
    "email": "[email protected]",
    "phone": "25451512544"
  }
}

Защита API

У нас есть полностью рабочий API. Ура! Но это совершенно небезопасно. БУ! Мы разрешаем доступ API без какой-либо аутентификации. Одним из наиболее простых используемых методов аутентификации для защиты API-интерфейсов является Token Authentication. Мы внедрим простую аутентификацию токена в нашем API, используя Devise . Мы могли бы также реализовать аутентификацию самостоятельно, но использование проверенной в битве библиотеки, такой как Devise, имеет свои преимущества.

Сначала добавьте Devise в наш Gemfile:

 gem 'devise'

И обновите комплект:

 bundle install

Devise теперь установлен, но нуждается в файле конфигурации. В Rails мы можем сгенерировать файл с помощью генератора Devise, но в Napa это не сработает. Поэтому мы вручную создадим файл в каталоге config / initializers . Создайте файл с именем devise.rb в этом каталоге и добавьте следующее:

 Devise.setup do |config|
  config.secret_key = '6e059f15248c9c26e7208a4a1129029c13f4a0fcef629562c34a4b3f0b1bbcbb8ed1431728cdbc6fe6e6bc4ed0f90cc9fc701c962e63be107e0bfd021eb70f08'
  config.mailer_sender = '[email protected]'
  require 'devise/orm/active_record'
  config.authentication_keys = [:email] 
  config.case_insensitive_keys = [:email ]
  config.strip_whitespace_keys = [:email ]
  config.skip_session_storage = [:http_auth]
  config.stretches = Rails.env.test? ? 1 : 10
  config.password_length = 8..128
end

Замените config.secret_key Теперь мы создадим модель User, используя генератор моделей Napa.

 napa generate model User

Напа создаст модельный класс и миграцию. Откройте класс миграции и добавьте следующее:

 ...
def change
  create_table :users do |t|
    t.string :email,              null: false, default: ""
    t.string :encrypted_password, null: false, default: ""
    t.string :authentication_token
    t.timestamps
  end
  add_index :users, :email, unique: true
  add_index :users, :authentication_token, :unique => true
end
...

Откройте app / models / user.rb и добавьте следующее:

 class User 

Теперь, когда у нас есть модель и миграция, перенесите базу данных:

 rake db:migrate

Мы создадим пользователя, используя консоль Napa, которую вы можете запустить:

 napa console

pry(main)> User.create!(email:'[email protected]', password:'abcdabcd', password_confirmation:'abcdabcd')

Вы должны получить следующий вывод:

 
=> #<user id: 1, email: "[email protected]", encrypted_password: "$2a$10$vdRAL.CusK3IEBTopa1cau5WTLihyNDdssuAtU3otieq...", authentication_token: "yFjgn5cwsFAfKhvU1R_t", created_at: "2015-08-08 11:41:05", updated_at: "2015-08-08 11:41:05">
</user>

Существует authentication_token Выходите из консоли.

Мы должны добавить поддержку аутентификации в наш API. Обновите app / apis / application_api.rb следующим образом:

 class ApplicationApi  '/contacts'

  add_swagger_documentation
end

Теперь снова запустите napa server

 curl -X GET http://localhost:9393/contacts

Это должно привести к ошибке, так как мы не передали токен доступа с запросом:

 {"error":{"code":"api_error","message":"401 Unauthorized"}}

Попробуйте тот же запрос, но с токеном доступа:

 curl -X GET http://localhost:9393/contacts\?access_token\=yFjgn5cwsFAfKhvU1R_t

И вы получите успешный ответ:

 {
  "data": {
    "object_type": "contact",
    "id": "1",
    "name": "Devdatta Kane",
    "email": "[email protected]",
    "phone": "25451512544"
  }
}

Заворачивать

Сегодня мы узнали, как быстро создавать API с помощью Napa. Napa предлагает дополнительную функциональность через промежуточное ПО, такое как ведение журнала и очистка конфиденциальных данных, которые вы можете изучить в репозитории Napa GitHub . Наше решение для аутентификации также может быть улучшено с помощью чего-то вроде OAuth и Access Grants, но я оставляю это упражнение для вас.

Комментарии и отзывы приветствуются, как всегда.