Введение в REST API
Подходы к генерации API документации


               Oleg Zinchenko
             oleg@exercise.com
О себе

Symfony разработчик с 2009 года

TeamLead в Exercise.com

Продвигаю Symfony2 в массы




https://twitter.com/1cdecoder
https://github.com/cystbear
http://cystbear.tumblr.com/
Exercise.com
 Программы    Видео
 Питание      Советы тренера
 Упражнения   Френды, лайки




                               Oleg Zinchenko
REST

  REpresentational State Transfer
                           Передача состояний

   Over HTTP
   State-less
   Кеширование




                                                Oleg Zinchenko
REST

  ACTIONS (HTTP METHODS)
   GET
   POST
   PUT/PATCH
   DELETE




                           Oleg Zinchenko
REST

  RESTful web API

  GET      /api/v1/orders
  POST     /api/v1/orders
  GET      /api/v1/orders/12
  PUT      /api/v1/orders/12
  DELETE   /api/v1/orders/12
  GET      /api/v1/orders/12/delete   forbidden




                                              Oleg Zinchenko
Задача




         Oleg Zinchenko
Задача
{
    "firstName": "Иван",
      "lastName": "Иванов",
      "address": {
      "streetAddress": "Московское ш., 101, кв.101",
        "city": "Ленинград",
        "postalCode": 101101
    },
      "phoneNumbers": [
      "812 123-1234",
      "916 123-4567"]
}

<person>
 <firstName>Иван</firstName>
 <lastName>Иванов</lastName> <address>
  <streetAddress>Московское ш., 101, кв.101</streetAddress>
  <city>Ленинград</city>
  <postalCode>101101</postalCode>
 </address>

 <phoneNumbers>
  <phoneNumber>812 123-1234</phoneNumber>
  <phoneNumber>916 123-4567</phoneNumber>
 </phoneNumbers>
</person>

                                                              Oleg Zinchenko
Bundles


  FOSRestBundle
   FOSRest

  JMSSerializerBundle
    jms/metadata




                        Oleg Zinchenko
2 Kernels


 AppKernel
 ApiKernel
   Разный набор конфигов
   Разный набор бандлов




                           Oleg Zinchenko
authentication + authorization



        authentication + authorization




                                         Oleg Zinchenko
Authentication




                 http://www.xml.com/pub/a/2003/12/17/dive.html

                                                     Oleg Zinchenko
Serialization

 Serializer map
  DemoAcmeDocumentFood:
    exclusion_policy: ALL
    properties:
      calories:
         expose: true
      caloriesPerServing:
         expose: true
      caloriesPerGram:
         expose: true
      caloriesPerFluidOunce:
         expose: true
      measurement:
         expose: true
      servingOptions:
         expose: true
    callback_methods:
      pre_serialize: [prepareMeasurement, prepareServingOptions]




                                                                   Oleg Zinchenko
Serialization

 Object Handlers
  {
      "id": "4fb1fb87944c4c0e240004de",
      "slug": "minimalist-article",
      "title": "Minimalist article",
      "updated_at": "2012-05-15T09:45:26+0300",
      "summary": "Minimalist summary",
      "body": "Minimalist body",
      "main_image": "http://e.com/upl/art/thum/parrot.mobile_client_medium.v1.jpg"
  }




                                                                                     Oleg Zinchenko
Тестирование

Behat
Buzz + aka WebApiContext
 Scenario: /foods get list of food. Pagination supported.
   Given I authorized as: "fred"
   When I make "GET" request to the "/api/v1/foods"
   Then the response status code should be: "200"
   And the response body should be similar to JSON:
     """
     [{"id":"4fb1fb8f944c4c0e24000622","slug":"bittermelon-cooked-a… }]
     """




                                                                          Oleg Zinchenko
Документация

Hippo doc
Swagger
NelmioApiDocBundle




                     Oleg Zinchenko
Документация
Hippo doc




http://api.jirafe.com/

                         Oleg Zinchenko
Документация
Swagger
 apis: [{
   path: "/pet.{format}/{petId}",
   description: "Operations about pets",
   operations: [{
     httpMethod: "GET",
     nickname: "getPetById",
     responseClass: "Pet",
     parameters: [...]
     summary: "Find pet by its unique ID"
     notes: "Only Pets which you have permission to see will be returned",
     errorResponses: [...]
   }]
 }




http://swagger.wordnik.com/
                                                                             Oleg Zinchenko
Документация
Swagger




http://swagger.wordnik.com/
                              Oleg Zinchenko
Документация
   NelmioApiDocBundle
/**
 * This the documentation description of your method, it will appear
 * on a specific pane. It will read all the text until the first
 * annotation.
 *
 * @ApiDoc(
 * resource=true,
 * description="This is a description of your API method",
 * filters={
 *      {"name"="a-filter", "dataType"="integer"},
 *      {"name"="another-filter", "dataType"="string", "pattern"="(foo|bar) ASC|DESC"}
 * }
 * )
 */
public function getAction()
{
}




https://github.com/nelmio/NelmioApiDocBundle
                                                                             Oleg Zinchenko
Документация
 NelmioApiDocBundle




https://github.com/nelmio/NelmioApiDocBundle
                                               Oleg Zinchenko
Спасибо




          Вопросы?




                     Oleg Zinchenko

Введение в REST API

  • 1.
    Введение в RESTAPI Подходы к генерации API документации Oleg Zinchenko oleg@exercise.com
  • 2.
    О себе Symfony разработчикс 2009 года TeamLead в Exercise.com Продвигаю Symfony2 в массы https://twitter.com/1cdecoder https://github.com/cystbear http://cystbear.tumblr.com/
  • 3.
    Exercise.com Программы Видео Питание Советы тренера Упражнения Френды, лайки Oleg Zinchenko
  • 4.
    REST REpresentationalState Transfer Передача состояний Over HTTP State-less Кеширование Oleg Zinchenko
  • 5.
    REST ACTIONS(HTTP METHODS) GET POST PUT/PATCH DELETE Oleg Zinchenko
  • 6.
    REST RESTfulweb API GET /api/v1/orders POST /api/v1/orders GET /api/v1/orders/12 PUT /api/v1/orders/12 DELETE /api/v1/orders/12 GET /api/v1/orders/12/delete forbidden Oleg Zinchenko
  • 7.
    Задача Oleg Zinchenko
  • 8.
    Задача { "firstName": "Иван", "lastName": "Иванов", "address": { "streetAddress": "Московское ш., 101, кв.101", "city": "Ленинград", "postalCode": 101101 }, "phoneNumbers": [ "812 123-1234", "916 123-4567"] } <person> <firstName>Иван</firstName> <lastName>Иванов</lastName> <address> <streetAddress>Московское ш., 101, кв.101</streetAddress> <city>Ленинград</city> <postalCode>101101</postalCode> </address> <phoneNumbers> <phoneNumber>812 123-1234</phoneNumber> <phoneNumber>916 123-4567</phoneNumber> </phoneNumbers> </person> Oleg Zinchenko
  • 9.
    Bundles FOSRestBundle FOSRest JMSSerializerBundle jms/metadata Oleg Zinchenko
  • 10.
    2 Kernels AppKernel ApiKernel Разный набор конфигов Разный набор бандлов Oleg Zinchenko
  • 11.
    authentication + authorization authentication + authorization Oleg Zinchenko
  • 12.
    Authentication http://www.xml.com/pub/a/2003/12/17/dive.html Oleg Zinchenko
  • 13.
    Serialization Serializer map DemoAcmeDocumentFood: exclusion_policy: ALL properties: calories: expose: true caloriesPerServing: expose: true caloriesPerGram: expose: true caloriesPerFluidOunce: expose: true measurement: expose: true servingOptions: expose: true callback_methods: pre_serialize: [prepareMeasurement, prepareServingOptions] Oleg Zinchenko
  • 14.
    Serialization Object Handlers { "id": "4fb1fb87944c4c0e240004de", "slug": "minimalist-article", "title": "Minimalist article", "updated_at": "2012-05-15T09:45:26+0300", "summary": "Minimalist summary", "body": "Minimalist body", "main_image": "http://e.com/upl/art/thum/parrot.mobile_client_medium.v1.jpg" } Oleg Zinchenko
  • 15.
    Тестирование Behat Buzz + akaWebApiContext Scenario: /foods get list of food. Pagination supported. Given I authorized as: "fred" When I make "GET" request to the "/api/v1/foods" Then the response status code should be: "200" And the response body should be similar to JSON: """ [{"id":"4fb1fb8f944c4c0e24000622","slug":"bittermelon-cooked-a… }] """ Oleg Zinchenko
  • 16.
  • 17.
  • 18.
    Документация Swagger apis: [{ path: "/pet.{format}/{petId}", description: "Operations about pets", operations: [{ httpMethod: "GET", nickname: "getPetById", responseClass: "Pet", parameters: [...] summary: "Find pet by its unique ID" notes: "Only Pets which you have permission to see will be returned", errorResponses: [...] }] } http://swagger.wordnik.com/ Oleg Zinchenko
  • 19.
  • 20.
    Документация NelmioApiDocBundle /** * This the documentation description of your method, it will appear * on a specific pane. It will read all the text until the first * annotation. * * @ApiDoc( * resource=true, * description="This is a description of your API method", * filters={ * {"name"="a-filter", "dataType"="integer"}, * {"name"="another-filter", "dataType"="string", "pattern"="(foo|bar) ASC|DESC"} * } * ) */ public function getAction() { } https://github.com/nelmio/NelmioApiDocBundle Oleg Zinchenko
  • 21.
  • 22.
    Спасибо Вопросы? Oleg Zinchenko