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

  1. 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.
  2. 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.
  3. 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

  1. Defineix una nova consulta GetComments que recuperi una llista de comentaris amb els camps id, text i author.
  2. Assigna un identificador únic a la consulta GetComments i emmagatzema-la al servidor.
  3. Modifica el servidor per acceptar l'identificador de la consulta GetComments.
  4. Envia una petició des del client utilitzant l'identificador de la consulta GetComments.

Solució

  1. Definició de la consulta GetComments:
# Fitxer: queries.graphql
query GetComments {
  comments {
    id
    text
    author
  }
}
  1. 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 } }"
}
  1. 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 } }"
};
  1. 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}`);
});
  1. 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.

© Copyright 2024. Tots els drets reservats