Header Ads Widget

Ticker

6/recent/ticker-posts

Cómo envolver una API REST en GraphQL

 

Cómo envolver una API REST en GraphQL

GraphQL es una herramienta poderosa que hemos discutido anteriormente en las API nórdicas . Sin embargo, al igual que con cualquier herramienta emergente en el espacio de API, existe cierto desacuerdo sobre cómo implementarla exactamente y cuáles son las mejores prácticas para su implementación y escenarios de casos de uso.

No tengas miedo, querido lector, estamos aquí para solucionar todo esto. Vamos a discutir GraphQL , de dónde vino, hacia dónde se dirige y por qué debería considerar implementarlo. Nos centraremos en cómo envolver una API RESTful con GraphQL y cómo funciona esto en el uso diario.

¿Qué es GraphQL?

Para aquellos que no están familiarizados, GraphQL es un lenguaje de consulta de capa de aplicación Interpreta una cadena de un servidor o cliente, devolviendo los datos en un esquema predefinido según lo dictado por el solicitante. Como dice el sitio oficial de GraphQL: “ Describe tus datos, pide lo que quieres, obtén resultados predecibles. "

La forma en que se solicitan los datos es bastante limpia y elegante. El siguiente es un descriptor de datos válido:

type Project {
  name: String
  tagline: String
  contributors: [User]
}

Cuando esto se solicita como tal:

project(name: "GraphQL") {
tagline } }

Devuelve un resultado limpio, fácil y simple:

{
"project": { "tagline": "A query language for APIs" }
}

Una implementación de GraphQL da como resultado una recuperación de datos más elegante, una mayor estabilidad de backend, consultas más eficientes y una organización mejorada con un lenguaje que tiene una baja sobrecarga de adopción. Dicho esto, entremos en la carne de cómo exactamente podemos implementar GraphQL en una API RESTful.

Definición de un esquema

El primer paso para envolver una API RESTful es definir un esquema . Los esquemas son esencialmente como guías telefónicas: una metodología común establecida para reconocer y organizar sus datos y las interacciones relacionadas con dichos datos.

Cuando se envuelve correctamente, una API RESTful canalizará toda la afluencia y salida de datos a través del esquema en sí; este es el poder principal del sistema GraphQL y es donde obtiene su universalidad .

Siguiendo con la documentación oficial de GraphQL , la implementación que vamos a mostrar hoy se simplifica, con algunos problemas en términos de rendimiento frente a implementaciones alternativas más complejas y que requieren más tiempo. Esta solución, sin embargo, no requiere mejoras en la arquitectura o el servidor, y es un punto de partida perfecto que podemos tomar para seguir adelante.

La implementación sugerida por la documentación de GraphQL es la siguiente:

import {
  GraphQLList,
  GraphQLObjectType,
  GraphQLSchema,
  GraphQLString,
} from 'graphql';

const BASE_URL = 'https://myapp.com/';

function fetchResponseByURL(relativeURL) {
  return fetch(`${BASE_URL}${relativeURL}`).then(res => res.json());
}

function fetchPeople() {
  return fetchResponseByURL('/people/').then(json => json.people);
}

function fetchPersonByURL(relativeURL) {
  return fetchResponseByURL(relativeURL).then(json => json.person);
}

const PersonType = new GraphQLObjectType({
  /* ... */
  fields: () => ({
    /* ... */
    friends: {
      type: new GraphQLList(PersonType),
      resolve: person => person.friends.map(getPersonByURL),
    },
  }),
});

const QueryType = new GraphQLObjectType({
  /* ... */
  fields: () => ({
    allPeople: {
      type: new GraphQLList(PersonType),
      resolve: fetchPeople,
    },
    person: {
      type: PersonType,
      args: {
        id: { type: GraphQLString },
      },
      resolve: (root, args) => fetchPersonByURL(`/people/${args.id}/`),
    },
  }),
});

export default new GraphQLSchema({
  query: QueryType,
});

Lo que básicamente hace este esquema es adjuntar métodos JavaScript a las variables y establecer la metodología mediante la cual se devuelven los datos. El principio y el final es una declaración necesaria: la importación de las restricciones GraphQL y la exportación del esquema GraphQL propiamente dicho:

import { GraphQLSchema } from 'graphql';
export default new GraphQLSchema({ query: QueryType, });

Al establecer dos constantes, un tipo de datos y un tipo de consulta , los datos se recopilan internamente a través de la API, al tiempo que permiten obtener un conjunto específico de argumentos proporcionados por el solicitante:

const PersonType = new GraphQLObjectType({
/* ... */
fields: () => ({
/* ... */
friends: {
type: new GraphQLList(PersonType),
resolve: person => person.friends.map(getPersonByURL),
},
}),
});

const QueryType = new GraphQLObjectType({
/* ... */
fields: () => ({
allPeople: {
type: new GraphQLList(PersonType),
resolve: fetchPeople,
},
person: {
type: PersonType,
args: {
id: { type: GraphQLString },
},
resolve: (root, args) => fetchPersonByURL(`/people/${args.id}/`),
},
}),
});

esto funcionalmente hace es establecer los datos y la metodología de consulta aceptada para emailidusername, y resuelve los datos accediendo a las propiedades del personobjeto como se adjunta en el código. Si bien esta técnica se basa en alguna funcionalidad en Relay , un complemento de GraphQL que a menudo se considera inseparable, el principio sigue siendo el mismo: datos predecibles y consultables.

Sin embargo, para este enfoque es de destacar el hecho de que los tipos en cuestión se definieron a mano. Si bien esto funciona para sistemas pequeños, no es una solución sostenible para API más grandes. En tal caso, soluciones como Swagger pueden definir definiciones de tipo automáticamente, que luego se pueden "tipificar" para el esquema GraphQL con relativa facilidad.

Lea también: Principales formatos de especificación para API REST

Alternativas a este método

Afortunadamente, hay algunos desarrolladores muy emprendedores que han llevado GraphQL a su extensión lógica, automatizando el proceso de creación del esquema en sí. Una de esas soluciones es graphql-rest-wrapper . Diseñada para crear fácilmente API REST empaquetadas, esta técnica es fácil de emplear:

const wrapper = new gqlRestWrapper('http://localhost:9090/restapi', {
name: 'MyRestAPI',
generateSchema: true,
saveSchema: true,
graphiql: true
})
app.use('/graphql', wrapper.expressMiddleware())

Esta solución es bastante simple, pero elegante en la forma en que maneja la producción de esquemas. La clase "gqlRestWrapper" crea un esquema GraphQL a partir de la respuesta REST. En cierto modo, esto es similar a un juego de teléfono, en el que el intermediario toma los datos que se transmiten y los define en un esquema utilizable para interacciones futuras.

Es necesario seguir algunos pasos. Primero, se debe instalar el paquete npm. Luego, debe importarse. Finalmente, se debe crear una instancia de la función de código como se indicó anteriormente:

npm i graphql-rest-wrapper


var gqlRestWrapper = require(graphql-rest-wrapper)


new gqlRestWrapped([apiEndpoint], [variableOptions])

Luego, el middleware, o el intérprete en el juego telefónico, debe adjuntarse a la ruta propiamente dicha:

app.use([ROUTE], wrapper.expressMiddleware())

Y finalmente, se puede realizar una solicitud HTTP GET / POST:

fetch("http://localhost:9090/graphql",
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: "{'query': 'query { MyRestAPI { id, name } }'}"
})
.then(function (res) {
console.log(res);
})

El beneficio de este estilo de envoltura es que está completamente automatizado cuando se organiza correctamente. Mientras que el primer proceso es totalmente manual, el segundo proceso se realiza en su totalidad mediante un sistema automático y eficaz. Esto se presta a problemas que, por supuesto, el método codificado a mano pasa por alto, principalmente, el hecho de que se puede pasar por alto un código más complejo o dar como resultado esquemas rotos.

Además: las herramientas de desarrollo GraphQL se traducen fácilmente en entornos sandbox o áreas de juego API

Envolver o no envolver

Por supuesto, esto plantea la pregunta: ¿deberíamos realmente envolver una API RESTful en GraphQL en primer lugar? Esto supone que la API en cuestión se deja en REST con el único propósito de que el desarrollo de un punto final compatible con GraphQL sobre una serie de cientos de casos de uso sería un desperdicio de tiempo indigno.

Sin embargo, es posible que eso no sea cierto cuando se consideran los extremos a los que debe llegar un proveedor para obtener lo que quieren de su API. Simplemente puede ser más útil codificar una serie de puntos finales compatibles con GraphQL en lugar de intentar envolver una API en una nueva máscara.

Esta tampoco es una propuesta de todo o nada. En la Cumbre de Plataformas de 2016 de las API nórdicas, Zane Claes habló sobre el movimiento de una API monolítica, heredada e interna, a un grupo más consistente de funcionalidades de API que sirvieron datos dados dispositivos específicos, casos de uso específicos y requisitos específicos.

Es completamente posible utilizar una API heredada durante un tiempo y migrar lentamente a una API compatible con GraphQL, en lugar de incluir una API existente como un "recurso provisional". De lo que estamos hablando aquí es de la diferencia entre una curita y un reemplazo de cadera completo: es posible que no se conozca el grado de dificultad hasta que se intente realmente.

Conclusión: envolver o recodificar

Afortunadamente, la metodología de empaquetar una API existente se reduce a lo complicada que es la situación. Para la mayoría de los proveedores de API, una simple envoltura como se indicó anteriormente funcionaría, siendo la solución automatizada totalmente aceptable.

Sin embargo, para otros, especialmente las API que son simplemente monolíticas, el proceso de volver a codificar una API para que sea compatible con GraphQL es una opción más eficaz.

Publicar un comentario

0 Comentarios