I am trying to access an internal graphQL schema bet kept hitting the error above. So, I tried accessing the free SWAPI API just to be sure I was implementing the client properly. I am still getting these errors however:
KeyError: key not found: "data"
from /Users/me/.rvm/gems/ruby-2.4.0/gems/graphql-1.8.11/lib/graphql/schema/loader.rb:16:infetch'`
And my client implementation:
module YetiAPI
HttpAdapter = GraphQL::Client::HTTP.new("http://graphql.org/swapi-graphql/") do
def headers(context)
{
"User-Agent" => "Ruby"
}
end
end
Schema = GraphQL::Client.load_schema(HttpAdapter)
Client = GraphQL::Client.new(schema: Schema, execute: HttpAdapter)
end
I'm not sure if there is something I'm doing wrong, though I was previously access these APIs with a similar setup just fine (a couple months ago).
Gemfile.lock
```GEM
remote: https://rubygems.org/
specs:
activesupport (5.2.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
coderay (1.1.2)
concurrent-ruby (1.1.3)
diff-lcs (1.3)
graphql (1.8.11)
graphql-client (0.14.0)
activesupport (>= 3.0, < 6.0)
graphql (~> 1.6)
httparty (0.16.2)
multi_xml (>= 0.5.2)
i18n (1.1.1)
concurrent-ruby (~> 1.0)
method_source (0.9.1)
mini_portile2 (2.3.0)
minitest (5.11.3)
multi_xml (0.6.0)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
pry (0.12.0)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rspec (3.2.0)
rspec-core (~> 3.2.0)
rspec-expectations (~> 3.2.0)
rspec-mocks (~> 3.2.0)
rspec-core (3.2.3)
rspec-support (~> 3.2.0)
rspec-expectations (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-mocks (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-support (3.2.2)
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
PLATFORMS
ruby
DEPENDENCIES
graphql-client
httparty (~> 0.16.2)
nokogiri (~> 1.8.3)
pry
rspec (~> 3.2.0)
BUNDLED WITH
1.16.1```
same problem
It sounds like it's getting an error response from SWAPI, in that case there's no data field. Can you see the response from SWAPI?
Not from SWAPI specifically. I'm just using it so I don't expose private endpoints etc. But, if you go to the https://graphql.org/swapi-graphql/ client, you can test out the API data, and they are giving back a response.
Here is a testing query that currently gives me JSON response.
``query allPlanets {
allPlanets {
planets {
name
terrains
id
gravity
}
}
}
Yet, using the gem no longer sees the data. Let me know if there's any more debugging I can do on my own
I recommend:
pry to your gemfile, or gem install pry if you aren't using a Gemfile bundle open graphql to open GraphQL-Ruby's source binding.pry right _before_ the line where the error is raised binding.pry call opens a debugger, inspect the hash where .fetch("data") is called "errors" key of that hash: it's probably populated with some kind of an error The real _fix_ would probably be to add some error handling to graphql-client or graphql-ruby, but for some quick debugging, that might get you unstuck! Feel free to share what you find.
@rmosolgo So, this is the full error when running from RSpec:
/Users/EdwardMcCarthy/.rvm/gems/ruby-2.4.0/gems/graphql-1.8.11/lib/graphql/schema/loader.rb:16:in `fetch': key not found: "data" (KeyError)
from /Users/EdwardMcCarthy/.rvm/gems/ruby-2.4.0/gems/graphql-1.8.11/lib/graphql/schema/loader.rb:16:in `load'
from /Users/EdwardMcCarthy/.rvm/gems/ruby-2.4.0/gems/graphql-client-0.14.0/lib/graphql/client.rb:52:in `load_schema'
from /Users/EdwardMcCarthy/.rvm/gems/ruby-2.4.0/gems/graphql-client-0.14.0/lib/graphql/client.rb:61:in `load_schema'
Let me try what you suggested above. Apologies for the delay in response
OK, I found the problem. When inspecting the instrospection_result, I am getting:
{"errors"=>[{"message"=>"403 Forbidden"}]}
Basically, the problem is the Authorization headers I require, have a key that is dynamically created based on a Secret key and some JS hashing functions (crypto.js). It ends up looking like this:
AUTH_HEADER = "HMAC-SHA256, Credential=#{ACCESS_KEY}, SingedHeaders=host;x-date, Signature=#{HMAC_DIGEST}"
HMAC_DIGEST is the one dynamically created.
I use it within the initialization as such:
```module MY_API
include HTTParty
URI = "my_api_uri"
ACCESS_KEY = "EEGHMT247LYTLL2AS4F6YKV3HI8STF8KIS52W09ZRY3YZEWV"
HMAC_DIGEST = "185aa2c0edb953342be683958de0b937afc4cb0073c46d35185a6cc97b8b5d49"
AUTH_HEADER = "HMAC-SHA256, Credential=#{ACCESS_KEY}, SingedHeaders=host;x-date, Signature=#{HMAC_DIGEST}"
REQUEST_TIME = Time.new
HttpAdapter = GraphQL::Client::HTTP.new(URI) do
def headers(context)
{
"Content-Type": "application/json",
"Authorization": AUTH_HEADER,
"X-Date": REQUEST_TIME
}
end
end
Schema = GraphQL::Client.load_schema(HttpAdapter)
Client = GraphQL::Client.new(schema: Schema, execute: HttpAdapter)
end
```
I think I am going to have to create helper functions that hash the secret key and store within the module, or look for alternative solution since I do know how to do this with JS.
I'm going to close this issue probably. Thank you @rmosolgo for all the guidance!
Most helpful comment
OK, I found the problem. When inspecting the instrospection_result, I am getting:
{"errors"=>[{"message"=>"403 Forbidden"}]}Basically, the problem is the Authorization headers I require, have a key that is dynamically created based on a Secret key and some JS hashing functions (crypto.js). It ends up looking like this:
AUTH_HEADER = "HMAC-SHA256, Credential=#{ACCESS_KEY}, SingedHeaders=host;x-date, Signature=#{HMAC_DIGEST}"HMAC_DIGEST is the one dynamically created.
I use it within the initialization as such:
```module MY_API
include HTTParty
URI = "my_api_uri"
ACCESS_KEY = "EEGHMT247LYTLL2AS4F6YKV3HI8STF8KIS52W09ZRY3YZEWV"
HMAC_DIGEST = "185aa2c0edb953342be683958de0b937afc4cb0073c46d35185a6cc97b8b5d49"
AUTH_HEADER = "HMAC-SHA256, Credential=#{ACCESS_KEY}, SingedHeaders=host;x-date, Signature=#{HMAC_DIGEST}"
REQUEST_TIME = Time.new
HttpAdapter = GraphQL::Client::HTTP.new(URI) do
end
Schema = GraphQL::Client.load_schema(HttpAdapter)
Client = GraphQL::Client.new(schema: Schema, execute: HttpAdapter)
end
```
I think I am going to have to create helper functions that hash the secret key and store within the module, or look for alternative solution since I do know how to do this with JS.
I'm going to close this issue probably. Thank you @rmosolgo for all the guidance!