Elixir Functions

 

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.

Building a GraphQL Server with Elixir and Absinthe

 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:

  1. Absinthe Documentation
  2. Phoenix Framework Guide
  3. GraphQL Official Documentation

Previously at
Flag Argentina
Brazil
time icon
GMT-3
Tech Lead in Elixir with 3 years' experience. Passionate about Elixir/Phoenix and React Native. Full Stack Engineer, Event Organizer, Systems Analyst, Mobile Developer.