Giter Site home page Giter Site logo

absinthe-graphql / absinthe_plug Goto Github PK

View Code? Open in Web Editor NEW
252.0 17.0 157.0 503 KB

Plug support for Absinthe, the GraphQL toolkit for Elixir

Home Page: https://hex.pm/packages/absinthe_plug

License: MIT License

Elixir 94.39% HTML 5.61%
plug absinthe absinthe-graphql phoenix graphql graphiql

absinthe_plug's Introduction

Absinthe.Plug

Build Status Version Hex Docs Download License Last Updated

Plug support for Absinthe, the GraphQL toolkit for Elixir.

Please see the website at http://absinthe-graphql.org.

Installation

Install from Hex.pm:

def deps do
  [{:absinthe_plug, "~> 1.5"}]
end

Note: Absinthe.Plug requires Elixir 1.10 or higher.

Absinthe.Plug also requires a JSON codec. Jason and Poison work out of the box.

def deps do
  [
    ...,
    {:absinthe_plug, "~> 1.5"},
    {:jason, "~> 1.0"}
  ]
end

Upgrading

See CHANGELOG for upgrade steps between versions.

You may want to look for the specific upgrade guide in the Absinthe documentation.

Documentation

See "Usage," below, for basic usage information and links to specific resources.

Related Projects

See the GitHub organization.

Usage

In your MyAppWeb.Router module add:

plug Plug.Parsers,
  parsers: [:urlencoded, :multipart, :json, Absinthe.Plug.Parser],
  pass: ["*/*"],
  json_decoder: Jason

plug Absinthe.Plug,
  schema: MyAppWeb.Schema

If you want Absinthe.Plug to serve only a particular route, configure your MyAppWeb.Router like:

plug Plug.Parsers,
  parsers: [:urlencoded, :multipart, :json, Absinthe.Plug.Parser],
  pass: ["*/*"],
  json_decoder: Jason

forward "/api",
  to: Absinthe.Plug,
  init_opts: [schema: MyAppWeb.Schema]

For more information, see the API documentation for Absinthe.Plug.

Phoenix.Router

If you are using Phoenix.Router, forward expects different arguments:

Plug.Router

forward "/graphiql",
  to: Absinthe.Plug.GraphiQL,
  init_opts: [
    schema: MyAppWeb.Schema,
    interface: :simple
  ]

Phoenix.Router

forward "/graphiql",
  Absinthe.Plug.GraphiQL,
  schema: MyAppWeb.Schema,
  interface: :simple

For more information see Phoenix.Router.forward/4.

GraphiQL

To add support for a GraphiQL interface, add a configuration for Absinthe.Plug.GraphiQL:

forward "/graphiql",
  to: Absinthe.Plug.GraphiQL,
  init_opts: [schema: MyAppWeb.Schema]

See the API documentation for Absinthe.Plug.GraphiQL for more information.

Community

The project is under constant improvement by a growing list of contributors, and your feedback is important. Please join us in Slack (#absinthe-graphql under the Elixir Slack account) or the Elixir Forum (tagged absinthe).

Please remember that all interactions in our official spaces follow our Code of Conduct.

Contributing

Please follow contribution guide.

License

See LICENSE.md.

absinthe_plug's People

Contributors

aleqsio avatar avitex avatar ayrat555 avatar benwilson512 avatar binaryseed avatar bruce avatar cesarandreu avatar craig-day avatar derrickreimer avatar dolfinus avatar eamontaaffe avatar fishcakez avatar griffitr avatar jayjun avatar jfrolich avatar jparise avatar kianmeng avatar maartenvanvliet avatar mgwidmann avatar nitingupta910 avatar paulo-ferraz-oliveira avatar petejkim avatar rafaelgaspar avatar rphuber avatar rzane avatar skosch avatar steffkes avatar tlvenn avatar uri avatar yury-dymov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

absinthe_plug's Issues

Return arbitrary status codes

Is it possible to return arbitrary HTTP status codes, e.g. a 401 Unauthorized when a particular field requires authentication?

I'm currently using a custom private function to wrap resolver functions, which returns {:error, "Must be logged in"} if the user is not authenticated:

query do
  field :posts, list_of(:post) do
    resolve private &App.PostResolver.all/2
  end
end

defp private(fun) do
  fn args, %{context: context} = info ->
    case context do
      %{current_user: user} when not is_nil(user) -> fun.(args, info)
      _ -> {:error, "Must be logged in"}
    end
  end
end

This results in a 200 status code even when an error is returned, which complicates error handling. It would be nice if we could return, e.g. {:error, message: "...", plug_status: 401}.

You can use Plug's exception protocol for this, but it feels kind of wrong:

case context do
  %{current_user: user} when not is_nil(user) -> fun.(args, info)
  _ -> raise App.Unauthorized
end

defmodule App.Unauthorized do
  defexception [message: "Must be logged in", plug_status: 401]
end

DocumentProvider.Compiled macro defines fxn with wrong args

Relatively new to the library, and trying to create my first compiled doc provider.

What happened:

  1. Tried defining a module with use Absinthe.Plug.DocumentProvider.Compiled
  2. Wrote a test to use the provided doc
  3. Ran into this error
Attempted function clauses (showing 1 out of 1):
         defp do_process(%{params: %{"id" => document_key}} = request)
  1. Thought, "that is strange", looks like the macro defines two function clauses for do_process

Conclusion
The second definition is expecting two args, but it will only every have 1. Currently looks like do_process(request, _) and it should look like do_process(request).

That could be intentional, sorry if it is! Just a little confused about it.

Use GraphiQL tool offline

I notice that all the assets are being pull up from the CDN. Is there any way to add that locally so it can work on offline connections?

There is only one reason I am asking and it's that some countries (Cuba in this case) can't access to the internet 24/7 so use GraphiQL is kind of impossible if it loads from the CDN. Also, working from a place that I can't access to the internet (like airplanes)

Do you have any suggestion in how to fix this? I am thinking that the only way is to download GraphiQL tool and run it locally and do not use this one I guess, but I am wondering if there if we could add offline support.

GraphiQL doesn't show (1.3.0-rc.0)

select_mode is expecting a document: nil when it's given a list containing queries.

I patched it on my side with:

defp select_mode(%{queries: [%Absinthe.Plug.Request.Query{document: nil}]}), do: :start_interface

I can create a PR if you like.

Batching with Apollo

I'm not sure whether this is an issue with Apollo or Absinthe, but figured I would start here in case batched responses don't match the Apollo expectations.

I have a very basic query:
{ users { id name } }

and am using {:absinthe_plug, git: "https://github.com/absinthe-graphql/absinthe_plug.git"}, in my mix.deps file.

This query works fine when I have batching switched off in Apollo, but I get an error with I switch it on (note I'm not even trying to send multiple queries at once, just one query):

Network error: Error writing result to store for query { users { id name } } /nCannot read property 'users' of undefined

The response from Absinthe is:
[{"operationName":null,"payload":{"data":{"users":[]}}}]

Custom error handeling

Hi!

I'm experiencing issues while using Absinthe.Plug in conjunction with Sentry (an error logging service). I can't get Sentry to report an error (neither through a Plug nor through :error_logger).

I've managed to find a similar issue on their issue tracker and after some digging figured out that this line causes the same problem as the one outlined in the issue.

My question is, is there a way to implement custom error handling with this library? Or o way to get the described integration to work?

(KeyError) key :no_query_message not found

Using

absinthe 1.2.5
absinthe_plug 1.2.2

When I run the following introspection query

query IntrospectionQuery {
    __schema {
      queryType { name }
      mutationType { name }
      subscriptionType { name }
      types {
        ...FullType
      }
      directives {
        name
        description
        locations
        args {
          ...InputValue
        }
      }
    }
  }

  fragment FullType on __Type {
    kind
    name
    description
    fields(includeDeprecated: true) {
      name
      description
      args {
        ...InputValue
      }
      type {
        ...TypeRef
      }
      isDeprecated
      deprecationReason
    }
    inputFields {
      ...InputValue
    }
    interfaces {
      ...TypeRef
    }
    enumValues(includeDeprecated: true) {
      name
      description
      isDeprecated
      deprecationReason
    }
    possibleTypes {
      ...TypeRef
    }
  }

  fragment InputValue on __InputValue {
    name
    description
    type { ...TypeRef }
    defaultValue
  }

  fragment TypeRef on __Type {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
                ofType {
                  kind
                  name
                }
              }
            }
          }
        }
      }
    }
  }

I get the following error

 ** (KeyError) key :no_query_message not found in: %{adapter: nil, context: %{}, interface: :advanced, json_codec: %{module: Poison, opts: []}, pipeline: {Absinthe.Plug, :default_pipeline}, schema_mod: Core.GraphQL.Schema}
        lib/absinthe/plug.ex:146: Absinthe.Plug.execute/2
        lib/absinthe/plug.ex:115: Absinthe.Plug.call/2
        (phoenix) lib/phoenix/router/route.ex:154: Phoenix.Router.Route.forward/4
        (webapp) lib/phoenix/router.ex:261: Webapp.Router.dispatch/2
        (webapp) web/router.ex:1: Webapp.Router.do_call/2
        (webapp) lib/webapp/endpoint.ex:1: Webapp.Endpoint.phoenix_pipeline/1
        (webapp) lib/plug/debugger.ex:123: Webapp.Endpoint."call (overridable 3)"/2
        (webapp) lib/webapp/endpoint.ex:1: Webapp.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

At this moment I couldn't run other query because I'm using the require('graphql/utilities').introspectionQuery from Javascript to start my babelRelayPlugin. I'll see if I can generate the schema with mix absinthe.schema.json so I can try other queries.

Introspection or GraphiQL don't like interface types

After upgrading to v1.4, it seems that GraphiQL does not like interface types anymore. The type is missing from the schema docs and the IDE claims the type doesn't exist, but the query will successfully execute.

ticket schema:

object :ticket do
  field :id, :integer

  field :test_iface, :iface_test do
    resolve fn _, _ ->
      {:ok, %{type: "one", name: "foo", email: "bar", custom: "custom"}}
    end
  end
end

iface_test schema:

object :one do
  field :name, :string
  field :email, :string

  field :custom, :string

  interface :iface_test
end

object :two do
  field :name, :string
  field :email, :string

  field :unique, :string

  interface :iface_test
end

interface :iface_test do
  field :name, :string
  field :email, :string

  resolve_type fn
    %{type: "one"}, _ -> :one
    %{type: "two"}, _ -> :two
    _, _ -> :one
  end
end

I don't think I'm missing anything, and this same schema worked on v1.3. Let me know if you need anything else!

Git merge issue in README?

def deps do
  [
<<<<<<< HEAD
    ...,
=======
    {:absinthe_plug, "~> 1.2.3"},
>>>>>>> master
    {:poison, "~> 1.3.0"}
  ]
end

Access to Plug.Conn in a processing pipeline

Hi! I'm trying to find a way of modifying http response returned by Absinthe Plug depending on results of a query (mutation) execution. For example, I want to put a new cookie into the response if mutation resolver has successfully returned some value (User model). I'm trying to build such workflow:

  1. Login mutation resolver should return a User model;
  2. Middleware function (which works after resolver) should found this model and add some additional data into a resolution context, for example – add user ID;
  3. Custom phase handler added into a pipeline (for example, after Absinthe.Phase.Document.Result) should look for that additional data and (if found) – generate JWT token and put it into a response as a cookie.

In such case I don't mix transport level with the logic and all transport-related stuff encapsulated in a Pipeline Phase.

Is this workflow even possible? Now I have several issues:

  1. I return modified Resolution (with custom data added into the context) from a field middleware function, but this data never appears in a context object of a Phase handler;
  2. Phase handlers also don't have an access to a Plug.Conn instance, so I can't modify it.

Maybe there is another way of doing this and I'm doing something wrong. Please help.

"No schema available" in graphiql

I've got graphiql mounted in dev and I'm able to make mutations as per my schema. But, the "docs" tab only shows "NO SCHEMA AVAILABLE".

I'm wondering if this is supposed to work (indicating I probably have it misconfigured), or if this is not a feature of absinthe_plug.

Thanks!

  if Mix.env == :dev do
    forward "/graphiql",
      Absinthe.Plug.GraphiQL,
      schema: DeviceService.Api.Factory.Schema,
      interface: :simple
  end

Fails to load body when the Content-Type encoding is set

When receiving a GraphQL query document (Content-Type: application/graphql) if the the encoding is also passed (or any other parameters for that matter), the plug will assume it's not a GraphQL document.

e.g. Content-Type: application/graphql; charset=UTF-8 will not work.

The issue is because of this line https://github.com/absinthe-graphql/absinthe_plug/blob/master/lib/absinthe/plug.ex#L169 the match here is matching exactly the string "application/graphql". So any other combination of parameters or encodings will obviously not match and fall through to the empty body case ({conn, ""}).

A simple fix is to just match [<<"application/graphql", _ :: binary>>] instead (though this is most likely wrong as any result as long as it contains that prefix will pass). However I'm unsure what the appropriate fix should be. I assume the GraphQL spec states the encoding should implicitly be UTF-8 (like JSON). So maybe the correct scenario should be a Content-Type whose parameters are either application/graphql only, or application/graphql with an explicit encoding set to UTF-8. While any other parameters/combination of (or other encodings) would be a failure.

I'm happy to submit a fix, just wondering what the ideal solution should cover.

Ensure Query

In the event the query document is in a GET body this just pushes a blank document on to Absinthe, which is wrong.

Update package info in mix file

Right now we have:

[description: "A plug for Absinthe, an experimental GraphQL toolkit",
     files: ["lib", "mix.exs", "README*"],
     maintainers: ["Ben Wilson", "Bruce Williams"],
     licenses: ["BSD"],
     links: %{github: "https://github.com/CargoSense/absinthe_plug"}]

I believe the description could get rid of the 'experimental' word and the links need to be updated.

GraphiQL seems to want to post to /graphiql even if that isn't where it's mounted

I'd like to mount GraphiQL to /api, which will also be the GraphQL API endpoint, to make it just a bit easier to discover and experiment with the API.

Even if I mount the GraphiQL plug at /api, it still wants to post to /graphiql. I have a hacky workaround in that I mount the plain GraphQL API at /graphiql, then point everything else at /api.

Any idea why this is happening? A quick glance through the source isn't hugely revealing. I'm wondering if it is a GraphiQL default that isn't being updated via the plug? If so, seems like it would fail if mounted anywhere else.

As an aside, is there any reason why doing this would be a bad idea? I'm explicitly trying to make this API as easy to discover and use as possible, but maybe there are gotchas of which I'm not aware.

Thanks.

GraphiQL ignores `default_url` value

Here is where I specified my default_url:

 forward "/graphiql",
      Absinthe.Plug.GraphiQL,
      schema: Eggl.Schema,
      default_headers: {__MODULE__, :graphiql_headers},
      default_url: "/graphql"

But when I visit /graphiql, the URL is always http://localhost:4000/graphiql (notice the i). I would have expected it to be http://localhost:4000/graphql.

This persists across different browsers and even different machines so its not a local storage cache issue.

See also: absinthe-graphql/absinthe#354 (comment)

Batching and upload

Hi guys, first of all, thank you for the great library!

I am not sure if it is an issue rather than a question but I would like to be able to upload files and use batching at the same time.

I was playing around with CURL to build the working request first and then to implement a plugin for the apollo-client library to make things work.

For the single request everything works great

curl -X POST \
-F query="mutation createPost(\$text: String, \$image: String){createPost(image: \$image, text:\$text, locked: false) { id }}" \
-F operationName="createPost" \
-F variables="{\"text\":\"hello\",\"image\":\"me_jpg\"}" \
-F [email protected] \
localhost:4000/graphql

The question is, how can I convert this single request in a batched one?

Thank you in advance!

Batching and file upload using a multipart form

Loving absinthe so far!
Just ran in an edge case (I think) when converting my app to support batching. I use a multipart form for submitting the queries and variables when one of the queries contains a file upload. That worked great when I didn't have a batching network interface, but now with batching applied I get the following error: 'no query document found'. I guess it is because normally absinthe expects the body of the document to be an array. However with multipart forms & batching the operations are part of the "operations" field.

v1.2: Support for pipeline modification

In Absinthe v1.2, we have a processing pipeline that can be customized. The pipeline built by the plug (see setup_pipeline) needs to be exposed for modification by users.

Unable to upload file via mutation using Apollo

I'm trying to upload a picture to a Phoenix application from my React Native app, using a GraphQL mutation that sends the picture as an argument. Unfortunately, Absinthe throws an error when receiving the mutation, possibly because of a malformed request.

Server: absinthe 1.4.0-rc.2, absinthe_plug 1.4.0-rc.0
Client: react-native 0.49.3, apollo-upload-client 5.1.1

In my schema.ex:

field :update_profile_picture, type: :string do
  arg :picture, non_null(:upload)

  resolve fn args, _ ->
    {:ok, "success"}
  end
end

My mutation:

mutation UpdateProfilePicture($picture: Upload!) {
  updateProfilePicture(picture: $picture)
}

and I run it from the client like this:

const image = … // my image object
const file = new ReactNativeFile({
  uri: image.path,
  type: 'image/jpeg',
  name: 'test.jpg'
})

this.props.updateProfilePicture({
  variables: {
    picture: file,
  },
})

After submitting, I see the following in my server logs:

[error] #PID<0.10558.0> running MyApp.Endpoint terminated
Server: api.myapp.local:4000 (http)
Request: POST /graphql
** (exit) an exception was raised:
    ** (BadMapError) expected a map, got: {"operationName", "UpdateProfilePicture"}
        (elixir) lib/map.ex:424: Map.get({"operationName", "UpdateProfilePicture"}, "query", "")
        lib/absinthe/plug/request/query.ex:131: Absinthe.Plug.Request.Query.extract_raw_document/2
        lib/absinthe/plug/request/query.ex:51: Absinthe.Plug.Request.Query.parse/3
        (elixir) lib/enum.ex:1259: anonymous fn/3 in Enum.map/2
        (stdlib) lists.erl:1263: :lists.foldl/3
        (elixir) lib/enum.ex:1828: Enum.map/2
        lib/absinthe/plug/request.ex:54: Absinthe.Plug.Request.build_request/4
        lib/absinthe/plug/request.ex:49: Absinthe.Plug.Request.parse/2
        lib/absinthe/plug.ex:217: Absinthe.Plug.execute/2
        lib/absinthe/plug.ex:155: Absinthe.Plug.call/2
        (phoenix) lib/phoenix/router/route.ex:161: Phoenix.Router.Route.forward/4
        (phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
        (myapp) lib/myapp/endpoint.ex:1: MyApp.Endpoint.plug_builder_call/2
        (myapp) lib/plug/debugger.ex:99: MyApp.Endpoint."call (overridable 3)"/2
        (myapp) lib/myapp/endpoint.ex:1: MyApp.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /Users/richeterre/Code/MyApp/myapp-phoenix/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

Is this something that could be fixed by making minor adjustments on the client side, as suggested by @confiks in #98? As I understand it, apollo-upload-client has sparked the interest of the Apollo core team and might become more "official" in the future: apollographql/apollo#65

CORS

Hello.

How should I setup my route in a router.ex to accept OPTIONS requests from a client?

Thanks!

Should Absinthe.Plug.GraphiQL serve the API requests, too?

I'm a little confused on how the GraphiQL feature is intended.

I assumed it's just to serve a separate JS app for GraphiQL. Thus, we had this configuration in our router:

  # The API endpoint
  scope "/api/v1" do
    pipe_through :api
    forward "/graphql", Absinthe.Plug, schema: Myapp.Schema
  end

  # The GraphiQL app
  if Mix.env == :dev do
    forward "/graphiql", Absinthe.Plug.GraphiQL, schema: Myapp.Schema
  end

The problem we have with this setup is that /graphiql also serves the GraphQL API. Two other people tried using the GraphiQL app, entering its own URL - /graphiql - instead of the API URL - /api/v1/graphql. Surprisingly for me, it worked. Except since the second endpoint is not piped through API, the GraphQL resolvers didn't get receive proper context and the API failed in various subtle and not so subtle ways. This was fixed by explaining the guys they should use the correct API endpoint.

Please explain, are we doing something idiomatically wrong?

Support for formats other than JSON

Hi!

With GraphQL being data format agnostic and all it might be nice to be able to use absinthe_plug with a custom serializer like msgpax or maybe just :erlang.term_to_binary

plug Absinthe.Plug,
  schema: MyApp.Schema,
  serializer: MyApp.Serializer

where MyApp.Serializer would implement callbacks similar to those for phoenix channels.

Router pipeline only works with graphiql socket endpoint, not api socket

Expected behavior

pipeline Context plug fires

Actual behavior

fires for graphiql but not from client client hitting socket

defmodule HyrWeb.Router do
  use Phoenix.Router
  import Plug.Conn
  import Phoenix.Controller
  
  pipeline :api do
    plug :accepts, ["json"]
    plug HyrWeb.Context
  end

  scope "/" do
    pipe_through :api

    forward "/socket", Absinthe.Plug,   # <- does NOT hit Context
      schema: HyrWeb.Schema,
      socket: HyrWeb.Channels.ShiftSocket

    forward "/graphiql", Absinthe.Plug.GraphiQL, # <- DOES hit Context
      schema: HyrWeb.Schema,
      interface: :simple,
      socket: HyrWeb.Channels.ShiftSocket

  end
end

the pipeline is just ignored for all my client calls. I don't see the IO.inspect that is shown below. I suspect it has something to do with Absinthe.Plug as that's the only thing that's different between the two endpoints. Don't know how it could be preventing pipe_through. Probably a socket issue but graphiql with sockets is getting the context pipe fine.

Here is my Context.ex but I am running the graphiql calls fine and can 100% confirm that Context.ex is doing what it is supposed to there.

defmodule HyrWeb.Context do
  @behaviour Plug
  import Plug.Conn

  def init(opts), do: opts
  def call(conn, _) do
    context = build_context(conn)
    IO.inspect [context: context]
    put_private(conn, :absinthe, %{context: context})
  end

  defp build_context(conn) do

    with %{} = user <- Hyr.Repo.get_by(Hyr.Accounts.User, phone: "+1-212-555-5555") do
      %{current_user: user} 
    else
      _ -> %{}
    end
  end

end

Log filtering

Sensitive parameters such as password should be filtered from the logs. This works easily with variables, I'm not so sure how it would work with logging the schema document itself.

Add Prettify button

In previous versions of absinthe_plug, we had a sweet prettify button:

screen shot 2017-04-10 at 8 41 35 am

But as of 3cc4889 we do not :(

screen shot 2017-04-10 at 8 45 27 am

I always found that to be super helpful, and would like to add it back in. It worked well where it was before, right next to the Run button above the query input.

The loss may be related to v0.9.3 of GraphiQL they removed the hardcoded prettify button. Perhaps the graphiql-workspace project didn't get the memo.

Log Variables

Debug logging on logs the query at the moment, it should also log variables.

Optionally support CSRF tokens in GraphiQL page

I like to keep access tokens in Secure, HttpOnly cookies (as opposed to localStorage) to ensure tokens are not vulnerable to XSS attacks. I combine that with the X-CSRF-Token header to mitigate CSRF attacks.

It would be great to have a way to inject <%= csrf_meta_tag() %> and have the X-CSRF-Token header set by default.

Unused variables throws exceptions

Query with unused variable:

query($userId: String!, $test: String!) {
    user(id: $userId) {
        id
    }
}

throws:

Server: localhost:4000 (http)
Request: POST /graphql
** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in Absinthe.Phase.Document.Result.format_location/1
        (absinthe) lib/absinthe/phase/document/result.ex:116: Absinthe.Phase.Document.Result.format_location(nil)
        (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
        (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
        (absinthe) lib/absinthe/phase/document/result.ex:111: Absinthe.Phase.Document.Result.format_error/1
        (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
        (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
        (absinthe) lib/absinthe/phase/document/result.ex:42: Absinthe.Phase.Document.Result.format_result/1
        (absinthe) lib/absinthe/phase/document/result.ex:12: Absinthe.Phase.Document.Result.run/2```

Multiple files upload

Hey guys!
Does the library support multiple file uploading? If so could you please provide with an example of schema and especially an example of a request. Thanks.

Support `operationName` selecting an operation definition to use

  • Use Absinthe.Language.Document.get_operation/2 to get the right Absinthe.Language.OperationDefinition.t
  • Verify the HTTP verb is appropriate for the .operation (ie, non-:query requires POST)
  • Pass the operation name to Absinthe.run/3 (as the :operation_name option)

GraphiQL integration with phoenix returns an error response

Following the documentation and inserting the following in the router:

get "/graphiql", Absinthe.Plug.GraphiQL, schema: MyApp.Schema

When I visit the url "/graphiql" the response I receive is No query document supplied. What I expected to see was the graphiql UI here.

After providing a query the graphiql UI renders, however the response doesn't seem quite right. It returns what appears to be the graphiql.html.eex file.

Support root_value option

Right now it appears that we're not supporting passing in a root_value option, which could be used to mock out data for rapid prototyping.

Boilerplate MyApp.Web.PageControllerTest fails with AbsinthePlug + Phoenix 1.3.0-rc.0

This may very well be user error :)

I'm trying to set up a 1.3 project with absinthe. However, as soon as I add the plug, my default Page controller test stops passing.

1) test GET / (MyApp.Web.PageControllerTest)
   test/my_app/web/controllers/page_controller_test.exs:4
   ** (Plug.Conn.AlreadySentError) the response was already sent
   stacktrace:
     (plug) lib/plug/conn.ex:950: Plug.Conn.register_before_send/2
     (my_app) lib/my_app/web/router.ex:4: MyApp.Web.Router.browser/2
     (my_app) lib/my_app/web/router.ex:1: anonymous fn/1 in MyApp.Web.Router.__match_route__/4
     (phoenix) lib/phoenix/router.ex:273: Phoenix.Router.__call__/1
     (my_app) lib/my_app/web/endpoint.ex:1: MyApp.Web.Endpoint.plug_builder_call/2
     (my_app) lib/my_app/web/endpoint.ex:1: MyApp.Web.Endpoint.call/2
     (phoenix) lib/phoenix/test/conn_test.ex:224: Phoenix.ConnTest.dispatch/5
     test/my_app/web/controllers/page_controller_test.exs:5: (test)

It seems like as soon I add the plug to the endpoint, the "/" url starts returning early.
Possibly I've missed a step, but I'm not sure where to start looking. Any help would be appreciated

Steps to Reproduce!

1.) phx.new my_app
2.) add schema file in lib/my_app/web/schema.ex

defmodule MyApp.Web.Schema do
  use Absinthe.Schema

  @fake_db %{
  "foo" => %{id: "foo", name: "Foo", value: 4},
  "bar" => %{id: "bar", name: "Bar", value: 5}
  }

  @desc "A valuable Item"
  object :item do
    field :id, :id

    @desc "The item's name"
    field :name, :string

    field :value, :integer, description: "Recently appraised value"
  end

  query do
    @desc "Get an item by ID"
    field :item, :item do

      @desc "The ID of the item"
      arg :id, type: :id

      resolve fn %{id: id}, _ ->
        {:ok, Map.get(@fake_db, id)}
      end
    end
  end

end
  1. As per absinthe-graphql.org/guides/plug-phoenix/ , update endpoint.ex as follows
plug Plug.Parsers,
  parsers: [:urlencoded, :multipart, :json, Absinthe.Plug.Parser],
  json_decoder: Poison

plug Absinthe.Plug,
  schema: MyApp.Schema

this is the point the tests fail

  1. Update the router to forward to the absinthe plug, router file now looks like
defmodule MyApp.Web.Router do
  use MyApp.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

    scope "/", MyApp.Web do
      pipe_through :browser # Use the default browser stack

      get "/", PageController, :index
    end

    forward "/api", Absinthe.Plug, schema: MyApp.Web.Schema

  # Other scopes may use custom stacks.
  # scope "/api", MyApp.Web do
  #   pipe_through :api
  # end
end

I tried putting the plug line in a few locations but it made no difference.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.