It is very important to avoid String.to_atom on data that comes from users. If the user can set fields_title or fields_type then they have an ability to crash your server. Atoms are not garbage collected, so as more users send different fields you will eventually run out of memory.
Hello @benwilson512, the suggested middleware works great, but unfortunately it is global.
What would be the recommended to do this just for a few objects?
You can obviously define a custom middleware for each field in the object, but for that you can just write a resolver for each field and it would look cleaner.
Is there any way to replace the Absinthe.Middleware.MapGet for all fields, or even add a middleware before it that would resolve each field differently? (defined in a per object basis)
Nope! The first bit does talk about globally replacing middleware, but you can scope it to just individual fields or objects. There is an example here with the query object Absinthe.Middleware — absinthe v1.7.6
Basically, the def middleware callback is given both the field and the object one at a time, so you can apply any middleware you like at whatever granularity you like.
Rather than specifying for each field which type of parent object to expect, something I’ve done is just clone the default MapGet middleware but have it check for both atom and string keys.
defmodule MyAppSchema.Middleware.MapGet do
@behaviour Absinthe.Middleware
@impl Absinthe.Middleware
def call(resolution, key) do
with %{state: :unresolved, source: source} <- resolution do
value = Map.get(source, key, Map.get(source, Atom.to_string(key)))
%{resolution | state: :resolved, value: value}
end
end
end
@brettbeatty
My question was precisely how would I avoid doing the exact same code as you posted, as it modifies the behaviour for all schema. I should have mentioned that in my post, it might be helpful for viewers finding it. So, thank you, it might not be a bad solution at the end for some use cases