artemis
artemis copied to clipboard
Support for adding middleware in adapters
Hello,
Thanks for this project, after struggling a day with various other GraphQL ruby clients I finally got recommended this one. The only part I'm fighting with is how I can add middleware concepts right before the request is send (like in Faraday).
What I need to add is HMAC authentication so I need the raw json body and be able to set new headers (while also accepting some global config)
Any advise on how to tackle this? Right now I'm going for the before_execute but that seems a bit to early since I have to structure the body again to take the MD5 for example
Regards
For now I've added my own adapter, copy pasting Net HTTP adapter and changing the following lines
# Only changes are in here
signed_request = ApiAuth.sign!(request, context[:access_id], context[:hmac_api_key], digest: 'sha256')
response = connection.request(signed_request)
It would be cool if right before the request was made you would have a hook that receives the request object, context and you return it a request object which is then used to make the request
Right now there isn't a great way to capture raw HTTP request/response, but I'm happy to add a hook that looks like:
class YourClient < Artemis::Client
before_request do |headers, body, context|
headers[:Authorization] = generate_signature(body, context[:access_id], context[:hmac_api_key])
end
after_request do |status, headers, body, context|
...
end
# Or with different names:
intercept_request do |...|
...
end
received_response do |...|
...
end
end
Right now, a more structured way to customize the adapter is to add your own adapter to the Artemis::Adapters
namespace so Artemis will be able to look up the adapter:
# lib/artemis/adapters/signed_net_http_adapter.rb
module Artemis::Adapters
class SignedNetHttpAdapter < NetHttpAdapter
def execute(document:, operation_name: nil, variables: {}, context: {})
...
signed_request = ApiAuth.sign!(request, context[:access_id], context[:hmac_api_key], digest: 'sha256')
response = connection.request(signed_request)
...
end
end
end
# config/initializers/artemis.rb
require 'artemis/adapters/signed_net_http_adapter'
# config/graphql.yml
development:
your_service:
adapter: :signed_net_http
This seems a little over-engineering since all you want to add is basically just a single line of code you already use. We could make it simpler if this is more common. Let me know what you think.
Hello,
Yes the before request / after request seem very helpful and might indeed solve almost all typical cases. Another idea that comes to mind is using Faraday (https://github.com/lostisland/faraday). It has support for all the adapters you currently are supporting (except for test / curb but faraday-curb exists) and allows to easily plugin middleware.
Our authentication right now is a Faraday Middleware.
I'll try to take a stab at that before_request
and after_request
hooks
Regards,