GraphQL
Características de GraphQL
- Declarativo. En GraphQL el cliente especifica los campos en los que está interesado y el servidor se asegura de que en la respuesta solo se devuelvan dichos campos.
- Jeráquico. Las consultas en GraphQL son jerárquicas.
- Fuertemente tipado.
Arquitectura
GraphQL comprende dos partes principales: el servidor y el cliente.
Básicamente, un servidor implementa las especificaciones GraphQL. Puede estar escrito en cualquier lenguaje de programación.
El trabajo del servidor es exponer las capacidades de la API. Normalmente habrá un único endpoint /graphql
que los clientes pueden usar para enviar consultas y recibir respuestas. GraphQL es independiente de la base de datos, pueden usar bases de datos SQL, no SQL o incluso usar como fuentes de datos endpoints REST.
GraphQL pertenece a la capa de aplicación actuando como una interfaz entre el cliente y los datos. Al pertenecer a la capa de aplicación se puede utilizar cualquier protocolo en la capa de transporte, aunque normalmente se use HTTP.
Los clientes tienen un mayor control en la arquitectura GraphQL. Hacen peticiones al servidor GraphQL, estas peticiones se conocen como documentos. Las peticiones pueden ser consultas (para leer datos) o modificaciones (para escribir datos); en el caso de consultas los clientes solo piden los datos que necesitan.
Comparación de GraphQL con REST
- Datos excesivos o insuficientes en REST.
Un problema común en REST es que se obtienen más o menos datos de los necesarios; esto es porque cada endpoint tiene un diseño específico, devolviendo siempre la misma estructura de datos, la necesite el cliente o no. En GraphQL el cliente controla la petición para recibir exactamente los datos que necesita. - Tráfico de red.
Las APIs REST necesitan múltiples llamadas ineficientes para recibir un conjunto de datos. Es posible obtener los mismos datos en GraphQL con una única llamada usando consultas jerárquicas, lo que ahorra mucho tráfico de red. - Mejor análisis del backend.
Con las APIS REST el servidor no es capaz de saber qué datos está usando el cliente. Tiene la información de alto nivel, pero no a nivel de campo.
Con GraphQL cada cliente especifica exactamente qué necesita. - Manejo de errores.
Aunque GraphQL suele usar HTTP no es obligatorio, por lo que los códigos de error estándar no se aplican en GraphQL. Por eso los endpoints GraphQL devuelven normalmente un código de estado 200. En GraphQL se incluyen los errores junto con los datos. Esto es muy distinto de las APIS REST donde los códigos de estado HTTP juegan un papel muy importante junto con la respuesta.
Schema Definition Language (SDL)
GraphQL tiene su propio sistema de tipado. Este sistema se usa para definir el esquema de una API.
La sintaxis para escribir esquemas se conoce como Schema Definition Language (SDL).
Un esquema es de la forma:
type Autor {
nombre: String!
pais: Int!
}
El símbolo !
indica que el campo es obligatorio.
También se pueden expresar relaciones entre tipos. Por ejemplo, un autor puede escribir un libro:
type Libro {
titulo: String!
annoPublicacion: Int!
autor: Autor!
}
O se puede expresar la relación en la otra parte haciendo:
type Autor {
nombre: String!
pais: Int!
libros: [Libro!]!
}
Básicamente, esto es una relación uno-a-varios entre autor y libro. Aquí el campo libros es un array del tipo Libro.
Consultas
Las consultas son la principal razón para utilizar GraphQL.
En GraphQL en vez de tener múltiples endpoints, como en REST API, lo habitual es que el servidor exponga un único endpoint. La estructura de la respuesta no está fijada, siendo muy flexible. Básicamente el cliente especifica qué datos quiere y el servidor responde con dichos datos.
Esto significa que el cliente debe aportarle más información al servidor, esta información es la query o consulta.
Un ejemplo de una consulta es:
allLibros{
titulo
}
Aquí allLibros
es la parte principal, o raíz, de la consulta. Lo que sigue a la raíz es el payload de la query; en este caso un único campo: título
.
La consulta devolverá algo del tipo:
{
"allLibros": [
{ "titulo": "Eye of the World" },
{ "titulo": "The Way of Kings" },
{ "titulo": "The Mistborn" }
]
}
En la respuesta, cada libro solo tiene el campo titulo
en la respuestas, aunque en la definición del esquema haya otros campos.
También se puede hacer una consulta jerárquica. Por ejemplo si se quiere obtener los libros por cada autor se puede hacer la consulta:
allLibros{
nombre
libros {
titulo
}
}
Mutaciones
GraphQL admite la modificación de datos mediante el concepto de mutaciones. Podemos crear, actualizar y borrar datos usando mutaciones.
Las mutaciones tienen una estructura similar a las consultas; la única diferencia es el uso del comando mutation
.
Por ejemplo, para crear un autor:
mutation {
createAutor(name: 'Brandon Sanderson', pais: "USA") {
nombre
pais
}
}
Una mutación también tiene un campo raíz, en este caso createAutor
; este campo toma dos argumentos: el nombre del autor y el país. Como con las consultas también se pueden solicitar parámetros de retorno, en este caso nombre y país.
Suscripciones
Las suscripciones no siguen el típico ciclo petición-respuesta. Cuando un cliente se suscribe a un evento mantendrá la conexión; cuando ocurra un evento en particular el servidor enviará los datos al cliente.
Las suscripciones se escriben usando el mismo formato que las consultas y las mutaciones:
subscription {
newAutor {
nombre
pais
}
}
Cuando el cliente envía la suscripción anterior al servidor se abre una conexión entre ellos. En cuanto ocurra una mutación que cree un nuevo autor el servidor enviará la siguiente información al cliente:
{
"newAutor": {
"nombre": "Robert Jordan",
"pais": "USA"
}
}