Las llamadas al API se implementan como peticiones HTTP, en las que:
id
http://api.ua.es/asignaturas/ADI_34039/anuncios
http://api.change.org/peticiones/2/firmas
{"caducidad":"2014-12-12",
"autor":"otto@ua.es",
"texto":"mañana no hay clase de teoría"}
Igual que antes, pero
id
http://api.ua.es/alumnos/123456J
http://api.biblioteca.ua.es/libros/978-3-16-148410-0
Location
de la respuesta
201 CREATED HTTP/1.1
Location: http://api.ua.es/asignaturas/ADI_3409/anuncios/1245
...
{"id":"1245",
"caducidad":"2014-12-12",
"autor":"otto@ua.es",
"texto":"mañana no hay clase de teoría"}
Tiene su origen en la tesis de Roy Fielding
Implica 6 condiciones:
http://api.mapas.com/calcularRuta?inicio=Alicante&fin=Madrid
http://api.change.org/peticiones/buscar?titulo=salvemos&ordenarPor=fecha
http://api.ua.es/estudiantes/acb34/enviar-sms
Esto podría haber sido un "create" del recurso SMS, pero supongamos que hemos decidido no representar los SMS como recurso
https://graph.facebook.com/10150146071791729/photos?offset=5&limit=2
https://graph.facebook.com/10150146071791729/photos?fields=id,picture
http://api.linkedin.com/v1/companies/1337:(id,name,description,logo-url)
Es una práctica común que la versión del API forme parte de la URL del recurso
http://www.example.org/v1/customer/1234
http://www.example.org/v2/customer/1234
http://www.example.org/customer/1234?version=v3
http://v4.example.org/customer/1234
Aunque en la actualidad JSON es el formato dominante, no hace mucho lo era XML. En realidad se puede usar cualquier formato estándar, por ejemplo Atom/RSS
en
http://creativecommons.org/licenses/by-nc-sa/2.0/uk/
Mon, 9 Dec 2013 16:33:02 +0000
Mon, 9 Dec 2013 16:33:02 +0000
5
http://www.audioscrobbler.net/data/webservices
RJ's Recently Played Tracks
http://www.last.fm/user/RJ
Last 10 tracks submitted to Last.fm
-
Xzibit – Paparazzi Live And Video
http://www.last.fm/music/Xzibit/_/Paparazzi+Live+And+Video
Mon, 9 Dec 2013 16:33:02 +0000
http://www.last.fm/user/RJ#1386606782
http://www.last.fm/music/Xzibit
...
Ejemplo del API de last.fm
Paginación: se aconseja incluir enlaces a la página anterior/siguiente
{
"total":"150",
"contenido": [
{"titulo":"Juego de tronos", "autor":"George R.R. Martin"},
{"titulo":"El nombre del viento", "autor":"Patrick Rothfuss"},
{"titulo":"El mundo del río", "autor":"Philip Jose Farmer"}
...
]
"link": {
"rel":"prev"
"href":"http://miapi.com/libros?inicio=1&cantidad=10"
}
"link": {
"rel":"next"
"href":"http://miapi.com/libros?inicio=21&cantidad=10"
}
"link": {
"rel":"self"
"href":"http://miapi.com/libros?inicio=11&cantidad=10"
}
}
{
"data": [
... Endpoint data is here
],
"paging": {
"cursors": {
"after": "MTAxNTExOTQ1MjAwNzI5NDE=",
"before": "NDMyNzQyODI3OTQw"
},
"previous": "https://graph.facebook.com/me/albums?limit=25&before=NDMyNzQyODI3OTQw",
"next": "https://graph.facebook.com/me/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
}
}
Accept
q
indica el "quality value" o valor de preferencia: (1.0 el preferido, 0.0 no aceptado)Accept-Charset
y Accept-Language
especifican las preferencias de codificación de caracteres e idioma, resp.Accept-encoding
permite usar compresión (el servidor debe enviar los datos comprimidos). En Ruby, use Rack::Deflater
Accept: application/xml;q=1.0, application/json;q=0.5, */*;q=0.0
Accept-Language: es;q=1.0, en;q=0.5
Accept-Charset: utf-8
Accept-Encoding: gzip
Podríamos analizar manualmente las cabeceras, pero varios frameworks, p.ej. Rails, implementan "negociación automática". Para algo parecido en Sinatra necesitamos alguna librería adicional (como rack-conneg
)
get '/hello' do
response = { :message => 'Hello, World!' }
respond_to do |wants|
wants.json { response.to_json }
wants.xml { response.to_xml }
wants.other {
content_type 'text/plain'
error 406, "Not Acceptable"
}
end
end
Aunque la visión ortodoxa es que se debe usar la cabecera HTTP Accept
, los APIs "de ahí fuera" usan métodos más heterodoxos
flickr.com/services/api/flickr.photos.search?tags=gatitos&format=xml
#Esta es la Versión antigua (v1). Twitter ya solo genera JSON (v1.1)
https://api.twitter.com/1/statuses/user_timeline.json?user_id=UA_Universidad
En la actualidad varios APIs ya solo generan JSON (p.ej. Facebook, Foursquare, Twitter)
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Cache-Control: public, max-age=3600
Expires: Mon, 09 Dec 2013 09:57:27 GMT #esto es de HTTP/1.0
Content-Length: 163
...
30 segundos después llega otra petición de otro cliente a la misma URL
If-modified-since
)If-none-match
)304 Not modified
pero no enviará los datos en síCache con expiración
get ‘/usuarios/:login’ do
usuario = UsuarioBD.get(params[:login])
expires 3600
#también se podría haber hecho "manualmente" con
#headers ‘Cache-Control’ => ‘max-age=3600’
usuario.to_json
end
Imitar el funcionamiento de la web, en la que para seguir los pasos en un flujo vamos saltando entre enlaces, sin necesidad de conocer previamente las URL
En cada respuesta debemos incluir enlaces con las operaciones posibles y los recursos directamente relacionados
{
"id":"1",
"items": [
{"id":"12", "cantidad":"1"},
{"id":"1123", "cantidad":"2"}
]
"link": {
"rel": "self",
"href": "http://miapi.com/pedidos/1"
},
"link": {
"rel": "items",
"href": "http://miapi.com/pedidos/1/items"
},
"link": {
"rel": "pagar",
"href": "http://miapi.com/pagos/pedidos/1"
}
}