Guida Introduttiva a GraphQL: Cos'è, Come Funziona e Come Creare API Moderne




GraphQL è un linguaggio di query per API e un runtime per l'esecuzione di tali query con i tuoi dati. Creato da Facebook nel 2012 e reso open source nel 2015, GraphQL è stato progettato per fornire ai client esattamente i dati di cui hanno bisogno, niente di più, niente di meno.

A differenza delle REST API tradizionali, che espongono molteplici endpoint per risorse differenti, GraphQL espone un singolo endpoint e consente al client di definire esattamente la forma della risposta desiderata.

🔗 Ti piace Techelopment? Dai un’occhiata al sito per tutti i dettagli!


🚀 Cos'è GraphQL?

GraphQL è un linguaggio di interrogazione per API che consente ai client di specificare esattamente quali dati vogliono ricevere. È stato sviluppato da Facebook per superare i limiti delle REST API tradizionali.

  • Over-fetching: ottenere più dati del necessario.
  • Under-fetching: dover fare più chiamate per ottenere i dati completi.

Con GraphQL, invii una query ad un solo endpoint e ricevi solo i dati richiesti.


📐 I Principi Fondamentali di un’API GraphQL (con esempi)

1. Single Endpoint

Tutte le operazioni passano da un unico endpoint, ad esempio /graphql.

In REST:

  • /api/users, /api/products, ecc. → tanti endpoint.

In GraphQL:

  • Uno solo: ad esempio /graphql.

💡 Esempio (POST su /graphql):

POST /graphql
Content-Type: application/json

{
  "query": "{ listUsers { name age } }"
}

2. Schema Tipizzato

Ogni API ha uno schema tipizzato che definisce i dati disponibili e le operazioni consentite. Lo schema definisce i tipi, le query (dati disponibili) e le mutation disponibili (operazioni consentite):

type User {
  id: Int
  name: String
  age: Int
}

3. Query Precise

Il client decide quali campi vuole ricevere:

{
  listUsers {
    name
  }
}

Risposta:

{
  "data": {
    "listUsers": [
      { "name": "Alice" },
      { "name": "Bob" }
    ]
  }
}

4. Introspezione

Lo schema è auto-descrivente. Puoi chiederlo con una query speciale:

{
  __schema {
    types {
      name
    }
  }
}

5. Tipizzazione Forte

Ogni campo e argomento ha un tipo specifico. Errori come questo sono bloccati:

{
  getUser(id: "not-a-number") {
    name
  }
}

🚫 Errore: id deve essere un intero.


🔍 Cosa sono le Query in GraphQL?

In GraphQL, le Query sono l’equivalente delle richieste GET nelle API REST. Servono a leggere dati dal server senza modificarli.

✨ Caratteristiche delle Query:

  • Non causano effetti collaterali (sono "safe").
  • Il client specifica esattamente i campi che vuole.
  • Sono il punto di partenza per leggere relazioni complesse tra entità.

🧪 Esempio di Query

{
  listUsers {
    name
    age
  }
}

Chiamata in Postman:

{
  "query": "{ listUsers { name age } }"
}

Risposta:

{
  "data": {
    "listUsers": [
      { "name": "Alice", "age": 30 },
      { "name": "Bob", "age": 25 }
    ]
  }
}

🎯 Query con Argomenti

{
  getUser(id: 2) {
    name
    age
  }
}

Postman:

{
  "query": "{ getUser(id: 2) { name age } }"
}

Risposta:

{
  "data": {
    "getUser": {
      "name": "Bob",
      "age": 25
    }
  }
}


✏️ Cos’è una Mutation e Quando Si Usa?

In GraphQL, Mutation viene usato per modificare i dati: creare, aggiornare o eliminare. È l’equivalente di POST, PUT o DELETE nelle REST API.

📦 Quando è necessaria?

Ogni volta che vuoi scrivere o modificare qualcosa nel server.

🔨 Esempio Completo: Mutation

1. Definizione nello schema

type Mutation {
  createUser(name: String!, age: Int!): User
}

2. Esempio di chiamata client

mutation {
  createUser(name: "Charlie", age: 40) {
    id
    name
  }
}

📦 Risposta:

{
  "data": {
    "createUser": {
      "id": 3,
      "name": "Charlie"
    }
  }
}

🔄 Differenza tra Query e Mutation

TipoScopoEffetti collaterali?Esempio
QueryLeggere dati❌ NogetUser, listUsers
MutationModificare dati✅ SìcreateUser, deleteUser


🧪 Come Chiamare una API GraphQL con Postman

📖 Chiamata di Query

  • Metodo: POST
  • URL: http://localhost:4000/graphql

Headers:

Content-Type:application/json

Body:

{
  "query": "{ listUsers { id name age } }"
}

Risposta:

{
  "data": {
    "listUsers": [
      { "id": 1, "name": "Alice", "age": 30 },
      { "id": 2, "name": "Bob", "age": 25 }
    ]
  }
}

✏️Chiamata di Mutation

  • Metodo: POST
  • URL: http://localhost:4000/graphql

Headers:

Content-Type:application/json

Body:

{
  "query": "mutation { createUser(name: \"Charlie\", age: 40) { id name age } }"
}

Risposta:

{
  "data": {
    "createUser": {
      "id": 3,
      "name": "Charlie",
      "age": 40
    }
  }
}

Usare Postman ti permette di esplorare le API GraphQL in modo chiaro e visuale, anche se sei abituato al paradigma REST. La cosa importante da ricordare è che:

  • Tutto avviene su un solo endpoint

  • Query per leggere, Mutation per scrivere

  • Il client decide cosa ricevere: il server risponde solo con i dati richiesti

Per approfondimenti sull'utilizzo di Postman con GraphQL puoi dare un'occhiata a https://blog.postman.com/how-to-implement-a-graphql-mutation/.

🛠️ Codice Completo di un Server GraphQL

Vediamo ora come esporre una API GraphQL su un server locale.

Installa le dipendenze:

npm install express express-graphql graphql

Codice completo (server.js):

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

// Define GraphQL schema
const schema = buildSchema(`
  type User {
    id: Int
    name: String
    age: Int
  }

  type Query {
    listUsers: [User]
    getUser(id: Int!): User
  }

  type Mutation {
    createUser(name: String!, age: Int!): User
  }
`);


// Sample in-memory data
let users = [
  { id: 1, name: 'Alice', age: 30 },
  { id: 2, name: 'Bob', age: 25 }
];

// Root resolver
const root = {
  listUsers: () => users,
  getUser: ({ id }) => users.find(u => u.id === id),
  createUser: ({ name, age }) => {
    const newUser = { id: users.length + 1, name, age };
    users.push(newUser);
    return newUser;
  }
};

const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: root,
  graphiql: true  // Enables GraphiQL UI
}));

app.listen(4000, () => console.log('GraphQL API running at http://localhost:4000/graphql'));

Ecco il codice del server con spiegazione punto per punto:

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

🔹 Importiamo le librerie necessarie: Express per il server HTTP, GraphQL e il middleware express-graphql.


// Define GraphQL schema
const schema = buildSchema(`
  type User {
    id: Int
    name: String
    age: Int
  }

  type Query {
    listUsers: [User]
    getUser(id: Int!): User
  }

  type Mutation {
    createUser(name: String!, age: Int!): User
  }
`);

🔹 Qui definiamo lo schema GraphQL, che è il contratto che descrive:

  • i tipi (User)

  • le query disponibili (listUsers, getUser)

  • le mutation disponibili (createUser)


// Sample in-memory data
let users = [
  { id: 1, name: 'Alice', age: 30 },
  { id: 2, name: 'Bob', age: 25 }
];

🔹 Una lista di utenti in memoria (non c'è un database per ora). Usiamo questo array per simulare dati reali.


// Root resolver
const root = {
  listUsers: () => users,
  getUser: ({ id }) => users.find(u => u.id === id),
  createUser: ({ name, age }) => {
    const newUser = { id: users.length + 1, name, age };
    users.push(newUser);
    return newUser;
  }
};

🔹 Il resolver è l'oggetto che implementa la logica per ogni operazione dello schema:

  • listUsers: restituisce tutti gli utenti.

  • getUser: cerca un utente per ID.

  • createUser: crea un nuovo utente con ID incrementale e lo aggiunge alla lista.


const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: root,
  graphiql: true  // Enables GraphiQL UI
}));

🔹 Creiamo l’app Express e definiamo un solo endpoint /graphql dove gestiamo tutte le richieste usando il middleware graphqlHTTP.
L'opzione graphiql: true attiva l'interfaccia grafica integrata per provare le query da browser.


app.listen(4000, () => console.log('GraphQL API running at http://localhost:4000/graphql'));

🔹 Il server parte sulla porta 4000. Aprendo http://localhost:4000/graphql si accede a GraphiQL, una UI utile per testare query e mutation.


🔹 Per lanciare server.js esegui il comando:

node server.js 

✅ Best Practice nella Progettazione di API GraphQL

  1. Definisci chiaramente lo schema: è il contratto tra client e server.

  2. Evita over-fetching e under-fetching: è uno dei maggiori vantaggi di GraphQL.

  3. Autorizzazione e autenticazione: implementa middleware per proteggere i dati sensibili.

  4. Rate Limiting: utile per evitare query troppo costose.

  5. Versionamento: GraphQL non ha versioni di API. Usa il deprecating dei campi quando necessario.


🧪 Strumenti Utili

  • GraphiQL / Apollo Studio: IDE per esplorare le API.

  • Apollo Server: alternativa a express-graphql, più completa.

  • GraphQL Code Generator: per generare tipi e query a partire dallo schema.


✅ Conclusione

GraphQL offre una modalità moderna, flessibile e potente per costruire API. I suoi vantaggi principali sono:

  • 🛂 Maggiore controllo lato client
  • 🔍 Evita over-fetching e under-fetching
  • 💪 Schema fortemente tipizzato
  • 🥇 Un solo endpoint per tutto

Puoi testare facilmente la tua API con Postman o GraphiQL e sviluppare rapidamente interfacce interattive e performanti.




Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment