Building a GraphQL Server with Elixir and Absinthe
GraphQL has revolutionized the way APIs are designed by providing a flexible and efficient query language. When combined with Elixir’s concurrency model and Absinthe’s powerful GraphQL toolkit, you can build scalable and performant APIs. This article will guide you through building a GraphQL server using Elixir and Absinthe, complete with practical examples.
Understanding GraphQL and Elixir
GraphQL is a query language that allows clients to request specific data from an API, offering more flexibility than RESTful APIs. Elixir, with its scalability and concurrency model, is an excellent choice for building high-performance GraphQL servers. Absinthe is a GraphQL toolkit for Elixir that simplifies creating and managing GraphQL schemas and queries.
Setting Up Your Elixir Project
To begin, you’ll need to set up a new Elixir project with Absinthe. Here’s how to do it:
Step 1: Install Elixir and Phoenix
If you haven’t already, install Elixir and Phoenix, as Phoenix will be used to handle HTTP requests.
```bash mix archive.install hex phx_new ```
Step 2: Create a New Phoenix Project
Create a new Phoenix project and add Absinthe to your dependencies.
```bash mix phx.new graphql_server --no-ecto cd graphql_server ```
Add `:absinthe` and `:absinthe_plug` to your `mix.exs` dependencies:
```elixir
defp deps do
[
{:phoenix, "~> 1.6.0"},
{:absinthe, "~> 1.6.0"},
{:absinthe_plug, "~> 1.6.0"}
]
end
```
Run `mix deps.get` to install the dependencies.
Defining Your GraphQL Schema
A GraphQL schema defines the types and queries available in your API. Let’s create a simple schema with a query to fetch user data.
Step 1: Create a Schema Module
In your `lib/graphql_server_web` directory, create a new file `schema.ex` and define your schema:
```elixir
defmodule GraphqlServerWeb.Schema do
use Absinthe.Schema
query do
field :user, :user do
arg :id, non_null(:id)
resolve &Resolvers.UserResolver.find/3
end
end
object :user do
field :id, :id
field :name, :string
field :email, :string
end
end
```
Step 2: Create a Resolver
Resolvers handle the logic for your GraphQL queries. Let’s create a simple resolver to fetch user data.
```elixir
defmodule GraphqlServerWeb.Resolvers.UserResolver do
alias GraphqlServer.Users
def find(_, %{id: id}, _) do
case Users.get_user(id) do
nil -> {:error, "User not found"}
user -> {:ok, user}
end
end
end
```
Setting Up a Phoenix Controller for GraphQL
To expose your GraphQL API, set up a Phoenix controller to handle the GraphQL queries.
Step 1: Create a GraphQL Controller
In `lib/graphql_server_web/controllers/graphql_controller.ex`, create a controller:
```elixir
defmodule GraphqlServerWeb.GraphqlController do
use GraphqlServerWeb, :controller
use Absinthe.Phoenix.Controller
def query(conn, params) do
schema = GraphqlServerWeb.Schema
result = Absinthe.run(params["query"], schema)
json(conn, result)
end
end
```
Step 2: Set Up Routing
In `lib/graphql_server_web/router.ex`, add a route for the GraphQL queries:
```elixir scope "/api" do post "/graphql", GraphqlServerWeb.GraphqlController, :query end ```
Testing Your GraphQL API
With everything set up, you can now test your GraphQL API. Start your Phoenix server:
```bash mix phx.server ```
Use a GraphQL client like [GraphiQL](https://github.com/graphql/graphiql) or [Postman](https://www.postman.com/) to send a query:
```graphql
query {
user(id: "1") {
id
name
email
}
}
```
Advanced Topics: Authentication and Authorization
To enhance your GraphQL API, consider adding authentication and authorization. Absinthe provides middleware for these purposes.
Example: Adding a Simple Authentication Middleware
```elixir
defmodule GraphqlServerWeb.Middleware.Authenticate do
def call(resolution, _) do
case resolution.context[:current_user] do
nil -> resolution |> Absinthe.Resolution.put_result({:error, "Not authenticated"})
_ -> resolution
end
end
end
```
Use this middleware in your schema:
```elixir field :user, :user do arg :id, non_null(:id) middleware GraphqlServerWeb.Middleware.Authenticate resolve &Resolvers.UserResolver.find/3 end ```
Conclusion
Building a GraphQL server with Elixir and Absinthe combines the best of both worlds—GraphQL’s flexibility and Elixir’s performance. By following this guide, you’ve learned how to set up a GraphQL server, define schemas, create resolvers, and integrate with Phoenix. As you delve deeper, explore advanced topics like authentication, subscriptions, and optimizing queries for more robust and secure GraphQL APIs.
Further Reading:
Table of Contents


