Apigility – Agile APIs



Apigility – Agile APIs

0 1


2015-10-21-Apigility-Agile-APIs


On Github weierophinney / 2015-10-21-Apigility-Agile-APIs

Apigility

Agile APIs

Matthew Weier O'Phinney@mwop 21 October 2015

Terminology

API

Application Programming Interface

How software should interact.

Web API

APIs delivered over HyperText Transfer Protocol (HTTP)

REST

REpresentational State Transfer

An architecture designed around the HTTP specification.

RESTful APIs

Defined in terms of the Richardson Maturity Model:

REST: Level 0

  • The usage of HTTP as communication layer…
  • for implementing Remote Procedure Calls (RPC)

REST: Level 1

  • URIs as unique identifiers
  • Example: reference the "User" resource viahttp://example.com/api/user[/:user_id]

REST: Level 2

  • Usage of HTTP verbs for operations on resources:
    • POST => create a new entity
    • GET => retrieve a collection or entity
    • PATCH => update an entity
    • etc.

REST: Level 3

Linking between resources to indicate relationships (hypermedia controls)

GET /api/user/mwop

{
	"_links": {
		"self": {
			"href": "http://domain/api/user/mwop"
		},
		"contacts": [
			{ "href": "http://domain/api/user/andi" },
			{ "href": "http://domain/api/user/zeevs" }
		]
	},
	"id": "mwop",
	"name": "Matthew Weier O'Phinney"
}

JSON-HAL format

tl;dr

REST is characterized by:

  • Usage of HTTP as the transport protocol
  • URIs as unique identifiers for resources
  • Full usage of HTTP verbs for operations on resources
  • Linking between resources (hypermedia controls)

HATEOAS

Hypermedia As The Engine Of Application State

Why REST?

  • Discoverability
  • Reduced client/server coupling

REST in PHP

header('Content-Type: application/json');
echo json_encode([
	'id'   => 'mwop',
	'name' => 'Matthew Weier O\'Phinney'
]);

Quite simple, right?

Wrong!

What about:

  • Honoring the client's requested format?
  • Resource linking? (what can you do from here?)
  • HTTP status?
  • It looks easy, until you start thinking of the bigger picture.
  • Little details matter, even for small examples!

RESTful in practice?

Issues

  • Which representation format should you use?
  • How will you provide error messages?
  • Will you support authentication? What kind?
  • How will you version the API?
  • Where will you link between resources?
  • What about API documentation?

Possible answers

  • Representation format: JSON
  • Error representation: application/problem+json
  • Authentication: OAuth2
  • API versioning: Accept and Content-Type headers, URI
  • Resource linking: JSON HAL
  • API documentation: HTML, Swagger, API Blueprint

Apigility

  • API builder and engine.
  • Open source project by Zend Technologies
  • Built on top of ZF2; use it standalone, add it to an existing ZF2 application, or incorporate it as part of another PHP application!
  • Admin UI is built using AngularJS.
  • Latest stable version is 1.3.1
  • Official website: apigility.org

Main features

  • Offers RPC and REST services.
  • JSON (HAL) as default format.
  • Error handling (Problem Details for HTTP APIs).
  • Content negotiation.
  • Versioning (via URI and Accept header, and for backing code).
  • Data validation.
  • Authentication (HTTP Basic/Digest, OAuth2).
  • Interactive documentation (HTML, Swagger, Blueprint).
  • Deployment; build production package files.

JSON HAL

  • JSON Hypertext Application Language (internet draft)
  • Example:
    GET /api/user/mwop
    
    {
      "_links": {
        "self": {
          "href": "http://domain/api/user/mwop"
        }
      }
      "id": "mwop",
      "name": "Matthew Weier O'Phinney"
    }

Embedded Entities

{
  "_embedded": {
    "contacts": [
      {
        "_links": {
          "self": {
            "href": "http://domain/api/user/zeevs"
          }
        },
        "id": "zeevs",
        "name": "Zeev Suraski"
      }
    ]
  }
}

Collections

{
    "_links": {
        "self": {
            "href": "http://domain/api/user?page=3"
        },
        "first": {
            "href": "http://domain/api/user"
        },
        "prev": {
            "href": "http://domain/api/user?page=2"
        },
        "next": {
            "href": "http://domain/api/user?page=4"
        },
        "last": {
            "href": "http://domain/api/user?page=133"
        }
    }
    "count": 3,
    "total": 498,
    "_embedded": {
        "users": [ /* ... */ ]
    }
}

Problem Details for HTTP APIs

AKA API Problem

  • ietf-appsawg-http-problem (internet draft)
  • Example:
    HTTP/1.1 405 Method Not Allowed
    Content-Type: application/problem+json
    
    {
        "detail": "The GET method has not been defined for entities",
        "status": 405,
        "title": "Method Not Allowed",
        "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
    }

Content negotiation

Request and provide different mediatypes for the same resource.
  • Clients indicate what mediatype they want:
    Accept: application/hal+json, application/json
  • or submit data using a mediatype:
    Content-Type: application/vnd.conference+json
  • and servers respond with a mediatype:
    Content-Type: application/hal+json
    (hopefully one the client accepts!)

API Versioning

Agility uses three approaches:

  • In the URL, as the first segment:
    /v1/api/user
  • Via Accept header:
    Accept: application/vnd.example.v1+json
  • In PHP namespaces:
    namespace Conference\V1\Rest\Speaker

Authentication

Apigility officially supports three authentication systems:

  • Note that we unofficially support arbitrary authentication, as the authentication system is event-driven, allowing users to supply their own listeners.

Authorization

  • Public API by default (configurable!)
  • Enable/disable authentication gateway per-method of any service.
  • Allows providing your own ACLs (zend-permissions-acl).
  • Listen to the authorization event for custom assertions.

Installation

Web-based installer:

$ curl -sS https://apigility.org/install | php

Or, if you don't have CURL installed:

$ php -r "readfile('https://apigility.org/install');" | php

Or just use Composer!

$ composer create-project zfcampus/zf-apigility-skeleton apigility

Apigility UI

Open the browser to http://localhost:8888

  • Demo time: ping API

Thanks!

Rate this talk: https://joind.in/15564

More information on apigility.org

@Apigility

Apigility Agile APIs Matthew Weier O'Phinney @mwop 21 October 2015