Les consultes persistents són una tècnica avançada en GraphQL que permet millorar el rendiment i la seguretat de les aplicacions. En lloc d'enviar consultes de GraphQL directament des del client al servidor, les consultes es guarden (persisten) al servidor i el client només envia un identificador de la consulta. Això redueix la càrrega de treball del servidor i minimitza els riscos de seguretat associats amb l'execució de consultes arbitràries.
Avantatges de les consultes persistents
-
Millora del rendiment:
- Redueix la mida de les peticions HTTP, ja que només s'envia un identificador en lloc de la consulta completa.
- Permet la precompilació i optimització de les consultes al servidor.
-
Seguretat:
- Evita l'execució de consultes arbitràries, ja que només es poden executar les consultes predefinides.
- Redueix el risc d'injecció de codi maliciós.
-
Gestió de versions:
- Facilita la gestió de versions de les consultes, ja que es poden actualitzar les consultes persistents sense canviar el codi del client.
Implementació de consultes persistents
Pas 1: Definir les consultes
Primer, definim les consultes que volem persistir. Aquestes consultes es poden escriure en fitxers separats o en un sol fitxer JSON.
# Fitxer: queries.graphql query GetUser { user(id: 1) { id name email } } query GetPosts { posts { id title content } }
Pas 2: Assignar identificadors a les consultes
Assignem identificadors únics a cada consulta. Això es pot fer manualment o utilitzant una eina automatitzada.
{ "GetUser": "query GetUser { user(id: 1) { id name email } }", "GetPosts": "query GetPosts { posts { id title content } }" }
Pas 3: Emmagatzemar les consultes al servidor
Les consultes es guarden al servidor en una estructura de dades adequada, com ara un objecte JavaScript o una base de dades.
const persistedQueries = { "GetUser": "query GetUser { user(id: 1) { id name email } }", "GetPosts": "query GetPosts { posts { id title content } }" };
Pas 4: Configurar el servidor per utilitzar consultes persistents
Modifiquem el servidor GraphQL per acceptar identificadors de consultes en lloc de consultes completes.
const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type User { id: ID! name: String! email: String! } type Post { id: ID! title: String! content: String! } type Query { user(id: ID!): User posts: [Post] } `; const resolvers = { Query: { user: (_, { id }) => ({ id, name: "John Doe", email: "[email protected]" }), posts: () => [ { id: 1, title: "Post 1", content: "Content 1" }, { id: 2, title: "Post 2", content: "Content 2" } ] } }; const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { const queryId = req.headers['x-query-id']; if (queryId && persistedQueries[queryId]) { req.body.query = persistedQueries[queryId]; } } }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
Pas 5: Enviar peticions des del client
El client envia peticions utilitzant els identificadors de les consultes en lloc de les consultes completes.
const fetch = require('node-fetch'); const queryId = "GetUser"; const response = await fetch('http://localhost:4000/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-query-id': queryId }, body: JSON.stringify({ variables: { id: 1 } }) }); const data = await response.json(); console.log(data);
Exercici pràctic
Exercici
- Defineix una nova consulta
GetComments
que recuperi una llista de comentaris amb els campsid
,text
iauthor
. - Assigna un identificador únic a la consulta
GetComments
i emmagatzema-la al servidor. - Modifica el servidor per acceptar l'identificador de la consulta
GetComments
. - Envia una petició des del client utilitzant l'identificador de la consulta
GetComments
.
Solució
- Definició de la consulta
GetComments
:
- Assignació d'identificador:
{ "GetUser": "query GetUser { user(id: 1) { id name email } }", "GetPosts": "query GetPosts { posts { id title content } }", "GetComments": "query GetComments { comments { id text author } }" }
- Emmagatzematge al servidor:
const persistedQueries = { "GetUser": "query GetUser { user(id: 1) { id name email } }", "GetPosts": "query GetPosts { posts { id title content } }", "GetComments": "query GetComments { comments { id text author } }" };
- Modificació del servidor:
const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type Comment { id: ID! text: String! author: String! } type Query { comments: [Comment] } `; const resolvers = { Query: { comments: () => [ { id: 1, text: "Comment 1", author: "Author 1" }, { id: 2, text: "Comment 2", author: "Author 2" } ] } }; const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { const queryId = req.headers['x-query-id']; if (queryId && persistedQueries[queryId]) { req.body.query = persistedQueries[queryId]; } } }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
- Petició des del client:
const fetch = require('node-fetch'); const queryId = "GetComments"; const response = await fetch('http://localhost:4000/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-query-id': queryId } }); const data = await response.json(); console.log(data);
Conclusió
Les consultes persistents són una tècnica poderosa per millorar el rendiment i la seguretat de les aplicacions GraphQL. En aquest tema, hem après com definir, emmagatzemar i utilitzar consultes persistents tant al servidor com al client. Aquesta tècnica és especialment útil en entorns de producció on la seguretat i l'eficiència són crucials.
Curs de GraphQL
Mòdul 1: Introducció a GraphQL
- Què és GraphQL?
- GraphQL vs REST
- Configuració d'un servidor GraphQL
- Conceptes bàsics de l'esquema de GraphQL
Mòdul 2: Conceptes bàsics
Mòdul 3: Disseny avançat d'esquemes
Mòdul 4: Treballant amb dades
- Connexió a una base de dades
- Estratègies de recuperació de dades
- Agrupació i emmagatzematge en memòria cau
- Gestió d'errors
Mòdul 5: Rendiment i seguretat
Mòdul 6: Eines i ecosistema
Mòdul 7: Proves i desplegament
- Proves unitàries de resolvers
- Proves d'integració
- Integració contínua
- Desplegament de servidors GraphQL