14 Connecting the Schema and Resolver to the HTTP Handler
title: 14 Connecting the Schema and Resolver to the HTTP Handler date: 2024-06-15 author: Gede Eka Pradipta
In the previous articles, we discussed how to design a schema and build a resolver for a GraphQL application. Now it’s time to take the next crucial step: connecting the schema and resolver to the HTTP handler, so that they can be accessed through client requests such as Apollo, Postman, or even a browser.
This is the stage where your backend code can start to “talk” to the outside world over HTTP. This article will walk through the wiring between the schema, the resolver, and the handler layer. We’ll also simulate a request-response cycle, look at real code, a component table, and a data flow diagram drawn with mermaid.
What Is an HTTP Handler in the Context of GraphQL?
In a GraphQL-based web application, the HTTP handler is the main gateway that receives incoming requests from the client in the form of a query/mutation, then forwards those requests to the schema to be processed by the resolver, before finally sending the response back to the client.
If you’re already familiar with REST, the HTTP handler in REST is analogous to a controller or routing handler. In GraphQL, however, the handler is usually just a single endpoint (for example /graphql), where every query/mutation is parsed and executed based on the schema and resolvers.
Data Flow: Diagram from Schema to HTTP Handler
Let’s first take a look at the following flow diagram:
flowchart TD
subgraph Client
A[GraphQL Request]
end
subgraph Server
B[HTTP Handler / Endpoint ("/graphql")]
C[Parse Query]
D[Validasi ke Schema]
E[Resolver]
F[Generate Response]
end
A --> B
B --> C
C --> D
D --> E
E --> F
F --> A
Flow explanation:
- The client sends a query/mutation to the HTTP handler
/graphql. - The handler receives and parses the query.
- The query is validated against the registered schema.
- Each field in the query is executed by its resolver.
- The data returned by the resolvers is collected, formatted (usually into JSON), and sent back to the client.
Components Required
| Component | Description | Example Package (Go) |
|---|---|---|
| HTTP Server | Provides the HTTP endpoint to receive requests | net/http |
| Schema | Definition of the Query, Mutation, etc. structure | github.com/99designs/gqlgen/graphql |
| Resolver | Implementation functions for the fields in the schema | Manual (Go struct) |
| GraphQL Handler | Adapter from the HTTP request to the schema & resolver | github.com/99designs/gqlgen/handler |
Practical Example: Go, gqlgen, and net/http
Let’s apply this in a Go environment using gqlgen , one of the popular GraphQL libraries. The schema below will be very similar to implementations in other languages, with minor adjustments.
1. Define the Schema (schema.graphqls)
1type Query {
2 hello: String!
3 user(id: ID!): User
4}
5
6type User {
7 id: ID!
8 name: String!
9 email: String!
10}2. Create the Resolver
Suppose we already have a simple resolver:
1type Resolver struct{}
2
3func (r *queryResolver) Hello(ctx context.Context) (string, error) {
4 return "Hello, World!", nil
5}
6
7func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) {
8 // Simulation: hardcoded user
9 if id == "1" {
10 return &model.User{ID: "1", Name: "Eka", Email: "eka@mail.com"}, nil
11 }
12 return nil, errors.New("user not found")
13}3. Connect It to the HTTP Handler
This is where the “wiring” between the schema, resolver, and HTTP handler takes place.
1package main
2
3import (
4 "log"
5 "net/http"
6 "github.com/99designs/gqlgen/graphql/handler"
7 "github.com/99designs/gqlgen/graphql/playground"
8 "github.com/yourrepo/yourproject/graph"
9 "github.com/yourrepo/yourproject/graph/generated"
10)
11
12func main() {
13 srv := handler.NewDefaultServer(generated.NewExecutableSchema(
14 generated.Config{Resolvers: &graph.Resolver{}},
15 ))
16
17 http.Handle("/graphql", srv)
18 http.Handle("/", playground.Handler("GraphQL playground", "/graphql"))
19
20 log.Fatal(http.ListenAndServe(":8080", nil))
21}Explanation:
handler.NewDefaultServer: Creates a GraphQL handler that is already connected to the schema & resolver.Resolversconfig: Registers the resolver function implementations with the server.http.Handle: One endpoint for the playground, and another for the actual handler.
Request & Response Simulation
Let’s simulate a request from the client:
Request
1POST /graphql
2{
3 "query": "{ user(id: \"1\") { id name email } }"
4}Handler Flow
- Receives the POST
/graphql. - The payload is parsed.
- Finds the root field
user. - Looks up the
Userresolver. - Executes the function with the argument
id="1". - Gets the data and formats it into JSON.
Response
1{
2 "data": {
3 "user": {
4 "id": "1",
5 "name": "Eka",
6 "email": "eka@mail.com"
7 }
8 }
9}Table: How the Components Relate
| Endpoints | Handler | Schema | Resolver |
|---|---|---|---|
/graphql | srv | schema.graphqls | Implemented in a Go struct |
/playground | Playground tool | - | - |
Schema & Handler Connectivity Checklist
| Step | Done | Notes |
|---|---|---|
| Schema definition | ✅ | .graphqls file |
| Resolver implementation | ✅ | Data logic functions |
| Registration with the server | ✅ | handler initialized with the schema + resolver |
| Route configuration | ✅ | /graphql endpoint |
| Testing | ✅ | Test queries from the playground or another tool |
Best Practices
- Validate the schema and resolvers: gqlgen binds the schema to the resolvers at build time, avoiding mismatches.
- Context-aware handler: The handler can inject context (auth/session) for every request.
- Middleware: Auth/logging/metrics layers can be intercepted before the handler calls the resolver.
Conclusion
Connecting the schema and resolver to the HTTP handler is the foundation of a GraphQL application’s architecture, whether in Go, Node.js, or any other platform. This process integrates all of the back-end logic layers into a single, centralized endpoint, making maintainability, debugging, and testing easier.
Once you understand this fundamental principle, you can explore various patterns such as custom middleware, batching, and efficient error handling—all of which start from a single point: the connection between the schema, the resolver, and the HTTP handler.
Happy coding! 🚀