Plug and Phoenix Setup
First, install Absinthe.Plug and a JSON codec of your choice, eg, Jason:
# filename: mix.exs
def deps do
[
{:absinthe_plug, "~> 1.5"},
{:jason, "~> 1.0"},
]
end
Plug
To use, simply plug
Absinthe.Plug in your pipeline.
plug Absinthe.Plug,
schema: MyAppWeb.Schema
If you are going to support content types other than simply application/graphql
you should plug Absinthe.Plug after Plug.Parsers.
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json, Absinthe.Plug.Parser],
json_decoder: Jason
plug Absinthe.Plug,
schema: MyAppWeb.Schema
For more information on how the content types work, see General Usage.
Phoenix
If your entire API is going to be based on GraphQL, we recommend simply plugging Absinthe.Plug in at the bottom of your endpoint, and removing your router altogether.
defmodule MyApp.Endpoint do
use Phoenix.Endpoint, otp_app: :my_app
plug Plug.RequestId
plug Plug.Logger
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Jason
plug Absinthe.Plug,
schema: MyAppWeb.Schema
end
If you want only Absinthe.Plug
to serve a particular route, configure your router
like:
defmodule MyAppWeb.Router do
use Phoenix.Router
resource "/pages", MyAppWeb.PagesController
forward "/api", Absinthe.Plug,
schema: MyAppWeb.Schema
end
Now Absinthe.Plug will only serve GraphQL from the /api
url.
Absinthe Context
Absinthe.Plug
will pass any values found inside conn.private[:absinthe][:context]
on to Absinthe.run
as the context. This is how you should handle logic that
uses headers -- most notably, Authentication.
For more information, see the Context guide.
GraphiQL
See the absinthe_plug
project and the GraphiQL portion of the Introspection guide to
learn how to use the built-in Absinthe.Plug.GraphiQL
plug.
General Usage
This plug supports requests in a number of ways:
Via a GET
With a query string:
?query=query+GetItem($id:ID!){item(id:$id){name}}&variables={id:"foo"}
Due to varying limits on the maximum size of URLs,
we recommend using one of the POST options below instead, putting the query
into the body of the request.
Via an application/json
POST
With a POST body:
{
"query": "query GetItem($id: ID!) { item(id: $id) { name } }",
"variables": {
"id": "foo"
}
}
(We could also pull either query
or variables
out to the query string, just
as in the GET example.)
Via an application/graphql
POST
With a query string:
?variables={id:"foo"}
And a POST body:
query GetItem($id: ID!) {
item(id: $id) {
name
}
}
HTTP API
How clients interact with the plug over HTTP is designed to closely match that of the official express-graphql middleware.
In the example above, we went over the various ways to make a request, but here are the details:
Once installed at a path, the plug will accept requests with the following parameters:
query
- A string GraphQL document to be executed.variables
- The runtime values to use for any GraphQL query variables as a JSON object.operationName
- If the providedquery
contains multiple named operations, this specifies which operation should be executed. If not provided, a 400 error will be returned if thequery
contains multiple named operations.
The plug will first look for each parameter in the query string, eg:
/graphql?query=query+getUser($id:ID){user(id:$id){name}}&variables={"id":"4"}
If not found in the query string, it will look in the POST request body, using
a strategy based on the Content-Type
header.
For content types application/json
and application/x-www-form-urlencoded
,
configure Plug.Parsers
(or equivalent) to parse the request body before Absinthe.Plug
, eg:
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Jason
For application/graphql
, the POST body will be parsed as GraphQL query string,
which provides the query
parameter. If variables
or operationName
are
needed, they should be passed as part of the
Configuration Notes
As a plug, Absinthe.Plug
requires very little configuration. If you want to support
application/x-www-form-urlencoded
or application/json
you'll need to plug
Plug.Parsers
first.
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Jason
plug Absinthe.Plug,
schema: MyApp.Linen.Schema
Absinthe.Plug
requires a schema:
config.
It also takes several options. See the documentation for the full listing.
Inside Phoenix controllers
You can use GraphQL as the datasource for your Phoenix controllers. For this
you'll need to add absinthe_phoenix
to your dependencies. See Absinthe Phoenix for installation instructions.
@graphql """
query ($filter: UserFilter) {
users(filter: $filter, limit: 10)
}
"""
def index(conn, %{data: data}) do
render conn, "index.html", data
end
The results of the query are now available in the "index.html" template. For
more information, see Absinthe.Phoenix.Controller