Introdução: Por que GraphQL e C++ são uma combinação poderosa
GraphQL se tornou um padrão para APIs modernas, oferecendo flexibilidade e eficiência em comparação com REST. Mas como implementá-lo em C++ — uma linguagem conhecida por seu desempenho e rigor? Neste tutorial, vamos analisar a criação de uma API GraphQL completa em C++ usando a biblioteca cppgraphqlgen. Você aprenderá como definir o schema, escrever resolvers, processar queries e mutations. Os exemplos de código serão práticos para que você possa aplicá-los imediatamente em seus projetos.
Ao final do artigo, você será capaz de criar um servidor GraphQL simples, mas funcional, em C++ que aceita requisições e retorna dados. Vamos lá!
Instalação e configuração do ambiente
Para trabalhar, precisaremos de:
- Compilador com suporte a C++17 (por exemplo, GCC 8+ ou Clang 7+)
- CMake (versão 3.14+)
- Biblioteca
cppgraphqlgen(geração de código a partir do schema GraphQL) - Servidor HTTP (por exemplo,
cpp-httplibpara simplicidade)
Instalaremos as dependências via vcpkg ou compilaremos manualmente. Para este tutorial, usamos vcpkg:
git clone https://github.com/Microsoft/vcpkg.gitcd vcpkg./bootstrap-vcpkg.sh./vcpkg install cppgraphqlgen cpp-httplibCriaremos a estrutura do projeto:
graphql-cpp-tutorial/├── schema.graphql├── CMakeLists.txt├── src/│ ├── main.cpp│ ├── resolver.cpp│ └── resolver.hPasso 1: Definindo o schema GraphQL
Criaremos o arquivo schema.graphql com um schema simples para gerenciamento de tarefas (Todo):
type Query { todos: [Todo!]! todo(id: ID!): Todo}
type Mutation { addTodo(title: String!): Todo! completeTodo(id: ID!): Todo}
type Todo { id: ID! title: String! completed: Boolean!}Este schema descreve:
- Query — obter lista de tarefas ou uma tarefa por ID
- Mutation — adicionar nova tarefa e marcar como concluída
- Type Todo — objeto com campos id, title, completed
O schema é o contrato da nossa API. Em seguida, geraremos o código C++ a partir dele.
Passo 2: Geração de código C++ a partir do schema
Usaremos a ferramenta graphqlgenerategen do pacote cppgraphqlgen:
graphqlgenerategen schema.graphql --output-dir ./generatedApós a execução, na pasta generated aparecerão os arquivos:
TodoObject.h— classe para o tipo TodoQueryObject.h— classe base para resolvers de QueryMutationObject.h— classe base para resolvers de Mutationschema.h— integração do schema
Estes arquivos contêm as interfaces geradas que devemos implementar.
Passo 3: Implementação dos resolvers
Criaremos o arquivo resolver.h com as declarações:
#include "generated/QueryObject.h"#include "generated/MutationObject.h"#include <vector>#include <memory>
struct Todo { std::string id; std::string title; bool completed;};
class QueryResolver : public graphql::todo::QueryObject {public: std::vector<std::shared_ptr<graphql::todo::TodoObject>> getTodos() const override; std::shared_ptr<graphql::todo::TodoObject> getTodo(const std::string& id) const override;
private: static std::vector<Todo> todos_;};
class MutationResolver : public graphql::todo::MutationObject {public: std::shared_ptr<graphql::todo::TodoObject> applyAddTodo(const std::string& title) override; std::shared_ptr<graphql::todo::TodoObject> applyCompleteTodo(const std::string& id) override;};Agora implementaremos a lógica em resolver.cpp:
#include "