I’m building an GraphQL(using Absinthe) API. And I would like to use this API for powering both the mobile app and a website. Is that possible to do it?
My other question is, how to authenticate the user through this same absinthe api on both the platforms(cookies for web app and token based I.e., access and refresh tokens for mobile app)… right now, I’m very confused. I would be grateful, if someone could shed some light on this topic. Are there any particular libraries that could help me?
Yes, this works great. With GraphQL each client can ask for exactly what they want. With REST, sharing APIs can be problematic because as you add fields to the response JSON to support the web you increase the size of data sent to mobile, even if mobile isn’t using that data. With GraphQL you don’t have this issue, because clients are only sent what they ask for.
Absinthe itself doesn’t generally care about the authentication mechanism, rather this is usually handled earlier in a plug, which sets the current user in the context. This gives you two options:
Have a plug which can support both sessions as well as access / refresh tokens
Mount the same schema at two different endpoints, and have each endpoint handle auth differently.
Here is an example of (2):
# in your router
pipeline :api do
# other api plugs
plug MyAppWeb.Api.Context
end
pipeline :mobile do
plug MyAppWeb.Mobile.Context
end
scope "/api" do
pipe_through :api
forward "/graphql", Absinthe.Plug, schema: MyAppWeb.Schema
end
scope "/mobile" do
pipe_through :mobile
forward "/graphql", Absinthe.Plug, schema: MyAppWeb.Schema
end
You have one schema, MyAppWeb.Schema and you just mount it in two places.
This misconception really has to die. You can achieve the same with both. In fact, most people end up querying the data with GraphQL even if they don’t need them. You can prevent querying and sending with both, of course, you just have to do the work.
You are right in the sense that GraphQL does not prevent API consumers from querying data that they do not need. You are also right in that, you can put in work as an API designer to build an ad hoc field requesting format in REST.
I’m not sure those points are enough to undermine the overall point. If I add a response key and value to a REST JSON response, this now goes out to every client that makes that request. Definitionally they don’t need it, they were already able to operate without it. However they now get that field anyway. In GraphQL, adding additional queryable fields to an object does not automatically push those fields out to querying users.
What work do you as a server author have to do to achieve this with GraphQL?
I don’t think that sending an extra field or two is the biggest problems for most APIs. But when it is, it’s very easy to solve in a typical JSON API. That’s all.
What work do you as a server author have to do to achieve this with GraphQL?
You have to make sure you only select the right fields in your SQL query. GraphQL is just interface.
My proposition wasn’t that GraphQL (or Absinthe specifically) lets you sub-select only specific fields from the database for free. My proposition was that only the fields an end client asks for are the fields that they receive. This is a valuable property even if the application server is still over-fetching at the column level, and this is a property that requires zero effort on the part of the application author.
This can be a critical issue on mobile, as every field incurs a bandwidth cost. Regardless, arguing that a feature isn’t valuable is moving the goal posts. You called my statement, that clients only get what they ask for, a misconception. I’m happy to discuss whether certain features are or aren’t valuable, but that’s separate from whether they are or aren’t true.
Definitely the conversation is muddied because there isn’t really just one REST spec. I’m curious then, which REST spec / library do you use that enables, without custom application developer code, end clients to specify which fields, associations, and associated fields they would like back, such that adding new fields does not automatically add additional response key / values?
Yup JSON:API as a spec on top of the basics of REST does provide that capability. This sort of proves my point though. Regular RESTful APIs, without the additional of a supplemental spec, don’t tend to work this way unless the application developer writes an ad hoc / custom implementation, and clients / application authors are generally tired enough of dealing with ad hoc implementations of this thing that it’s been worth writing large secondary specs like JSON:API or GraphQL.
The existence of supplemental specs to solve this problem highlights the value of this capability. They also highlight the fact that in the absence of such specs REST APIs generally either don’t implement these features, or they implement it in an ad hoc way where documentation and implementation varies by API, and depends on the developer. That is sometimes just fine. But clearly there is strong interest in the API space to do better. JSON:API and GraphQL are both efforts to do better, and they have their own pros / cons beyond field selection that could be looked at.
Hi Ben, I know this is an old question, but I’m still stuck at setting a cookie for my api, how can we set a cookie for web interface…? I mean, how do I set a cookie using plug MyAppWeb.Api.Context