RESTful API development:
problems and solutions

by Enrico Zimuel / @ezimuel
Senior Software Engineer - Zend Technologies

About me

I'm a Software Engineer since 1996. I work in the R&D department of Zend Technologies, the PHP Company. I'm an open source contributor: Apigility and Zend Framework. I did research in computer science at the Informatics Institute of the University of Amsterdam. I wrote a couple of books: "PHP best practices" and "Javascript best practices". I'm the co-founder of PUG Torino.

API

API stands for "Application Programming Interface" and as a term, specifies how software should interact.

Generally speaking, when we refer to APIs today, we are referring more specifically to web APIs, those delivered over HyperText Transfer Protocol (HTTP).

REST

REpresentational State Transfer (REST) is not a specification, but an architecture designed around the HTTP specification.

RESTful

REST leverages HTTP's strengths, and builds on:

  • URIs as unique identifiers for resources
  • Rich set of HTTP verbs for operations on resources
  • The ability for clients to specify representation formats they can render
  • Linking between resources to indicate relationships

Glory of REST

When talking about REST, the Richardson Maturity Model is often used to describe the concerns necessary when implementing a well-designed REST API

REST in practice?

All of this theory helps tell us how REST services should act, but tell us very little about how to implement them. This is somewhat by design; REST is more of an architectural consideration.

Some questions

  • What representation formats will you expose?
  • How will you report errors?
  • How will you advertise which HTTP methods are available for a given resource?
  • How will you handle features such as authentication?
  • How will you handle hypermedia linking?
  • How will you document what resources are available?

Possible answers

  • What representation formats will you expose? JSON
  • How will you report errors? application/problem+json
  • How will you advertise which HTTP methods are available for a given resource? OPTIONS
  • How will you handle features such as authentication? OAuth2
  • How will you handle hypermedia linking? Hypermedia Application Language (HAL)
  • How will you document what resources are available? Swagger, Apiary.io, API Blueprint, etc

Apigility

Main features

  • RPC and REST
  • JSON (HAL) as default format
  • Error handling (API Problem)
  • Content negotiation
  • Versioning (via URI and Accept header)
  • Filtering and validation
  • Authentication (HTTP Basic/Digest, OAuth2)
  • Documentation (HTML, Swagger)

RPC

  • "A remote procedure call (RPC) is an inter-process communication that allows a computer program to cause a subroutine or procedure to execute in another address space" (Wikipedia)
  • A RPC over HTTP is actually any kind of API request provided using a specific data format (e.g. RPC-XML, RPC-JSON).

RESTful

  • REST is a simple stateless architecture that generally runs over HTTP.
  • It uses URI and HTTP methods to map the different actions (GET, POST, PUT, DELETE).
  • A typical RESTful API url:
    
    http://domain/api/user[/:user_id]
    

JSON

  • JSON (JavaScript Object Notation), is an open standard format used to transmit data between a server and web application, expressed using Javascript syntax.
  • Example of JSON:
    
    {
        "firstName": "John",
        "lastName": "Smith",
        "age": 25,
        "address": {
            "streetAddress": "21 2nd Street",
            "city": "New York"
        },
        "emails" : [
    	'john.smith@gmail.com',
    	'john@smith.com'
        ]
    }
    

JSON HAL

  • JSON Hypertext Application Language, is a RFC draft proposal (draft-kelly-json-hal-06)
  • Example:
    
    {
        "_links": {
            "self": {
                "href": "http://domain/api/user/ezimuel"
            }
        }
        "id": "ezimuel",
        "name": "Enrico Zimuel"
    }
    

_embedded


{
    "_links": {
        "self": {
            "href": "http://domain/api/user/ezimuel"
        }
    }
    "id": "ezimuel",
    "name": "Enrico Zimuel",
    "_embedded": {
        "contacts": [
            {
                "_links": {
                    "self": {
                        "href": "http://domain/api/user/mwop"
                    }
                },
                "id": "mwop",
                "name": "Matthew Weier O'Phinney"
            },
            {
                "_links": {
                    "self": {
                        "href": "http://domain/api/user/ralphschindler"
                    }
                },
                "id": "ralphschindler",
                "name": "Ralph Schindler"
            }
        ]
    }
}

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": [
            {
                "_links": {
                    "self": {
                        "href": "http://domain/api/user/mwop"
                    }
                },
                "id": "mwop",
                "name": "Matthew Weier O'Phinney"
            },
            {
                "_links": {
                    "self": {
                        "href": "http://domain/api/user/mac_nibblet"
                    }
                },
                "id": "mac_nibblet",
                "name": "Antoine Hedgecock"
            },
            {
                "_links": {
                    "self": {
                        "href": "http://domain/api/user/spiffyjr"
                    }
                },
                "id": "spiffyjr",
                "name": "Kyle Spraggs"
            }
        ]
    }
}

API Problem

  • API Problem is a RFC draft proposal (draft-nottingham-http-problem-06)
  • Example:
    
    Content-Type: application/problem+json
    
    {
        "detail": "The GET method has not been defined for individual",
        "status": 405,
        "title": "Method Not Allowed",
        "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
    }
    

Content negotiation

  • Content negotiation is a mechanism defined in the HTTP specification that makes it possible to serve different versions of a document at the same URI.
  • Example:
    
    Accept: application/hal+json, application/json
    

API Versioning

Agility uses two approaches:

  • In the URL, e.g. /api/v1/user
  • By Accept header, e.g. Accept:application/vnd.example.v1+json

Authentication

"Authentication is the act of confirming the identity of a person or software program" (Wikipedia)

Apigility supports 3 different authentication systems:

  • HTTP Basic
  • HTTP Digest
  • OAUth2

Use Apigility for

Create RESTful/RPC API for an existing PHP application:
code-connected

Expose a database table as RESTful API:
db-connected

Installation

Super easy, just one command:


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

Or, if you don't have CURL installed:


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

Apigility UI

Open the browser to http://localhost:8888

DEMO time

Apigility in action!

Thanks!


More information on apigility.org



Creative Commons License
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.