`fetch': key not found: "data" (KeyError) : graphql-client error - ruby

I was trying to use the graphql query within ruby to fetch github repositories. Before writing the query, I was working on getting the graphql-client working. I'm facing issues with graphql client.
I was following this link for graphql client:
https://github.com/github/graphql-client
require 'graphql'
require 'graphql/client'
require 'graphql/client/http'
module MyGraphQL
HTTP = GraphQL::Client::HTTP.new('https://github.com/graphql') do
def client_context
{ access_token: 'xxxxxxxxxxxxxxxxxx' }
end
def headers(_context)
client_context
end
end
Schema = GraphQL::Client.load_schema(HTTP)
Client = GraphQL::Client.new(schema: Schema, execute: HTTP)
end
I'm getting the following errors in a terminal:
'fetch': key not found: "data" (KeyError)
'load'
'load_schema'
'load_schema'

This error appears due to response you receive via fetching https://github.com/graphql.
You can use binding.pry (this gem), for example, to see what happening, when you try to run load_schema method.
It tries to fetch data from response here: http://i.imgur.com/9T9WRUu.png
But there is no data attribute, because you get {"errors"=>[{"message"=>"422 Unprocessable Entity"}]}
Try to fetch http://graphql-swapi.parseapp.com/, for example, worked for me.

Also faced with same problem. Replacing body method to this helped:
def headers(context)
{
"Authorization" => "bearer #{TOKEN}"
}
end
Where is the TOKEN is the Personal access token gotten from here: https://github.com/settings/tokens

Related

Every error in the book from google-api-ruby-client but no data

I have been attempting to work on a request from my boss this week that requires using the google admin directory api.
At this point I am questioning if what I am trying to do is even possible.
Can I retrieve data from the scope "https://www.googleapis.com/auth/admin.directory.device.mobile.readonly" with a service account? Is it even possible?
The errors I have seen in the past hour are below...
Many of them sound the same and I have no idea what is going on or why this is such a difficult journey for such basic information.
PERMISSION_DENIED: Request had insufficient authentication scopes. (Google::Apis::ClientError)
`check_status': Unauthorized (Google::Apis::AuthorizationError)
Authorization failed. Server message: (Signet::AuthorizationError)
{
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
`check_status': permission_denied: request had insufficient authentication scopes
`check_status': badRequest: Bad Request
My current test script is below...
require "google/apis/admin_directory_v1"
require "googleauth"
require "googleauth/stores/file_token_store"
require "fileutils"
APPLICATION_NAME = "Directory API Ruby Quickstart".freeze
CREDENTIALS_PATH = "credentials.json".freeze
CUSTOMER_ID = "thasgunnabeanopefrommedawg".freeze
SCOPE = ["https://www.googleapis.com/auth/admin.directory.device.mobile.readonly"].freeze
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io:
File.open('credentials.json'),
scope: SCOPE)
authorizer.update!(sub: "fullbl00m#citadelny.com")
authorizer.fetch_access_token!
# puts authorize
# Initialize the API
service = Google::Apis::AdminDirectoryV1::DirectoryService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = Google::Auth.get_application_default(SCOPE)
response = service.list_mobile_devices(customer_id: CUSTOMER_ID)
puts response.to_json
EDITS BELOW *** [27th, MAY, 2022]
I have been trying with ruby, python, and postman for two weeks at this point :/
Last night I took the ruby snippet that was posted by user:Daimto below.
I was able to return a token with the following modified version of the ruby snippet provided in the answer below.
require 'googleauth'
require 'google/apis/admin_directory_v1'
creds = {
"type": "service_account",
"project_id": "MYPROJECTNAME",
"private_key_id": "MYPRIVATEKEYID",
"private_key": "-----BEGIN PRIVATE KEY-----\n-MY PRIVATE KEY
WILL BE HERE BUT REMOVED FOR SECURITY-----END PRIVATE KEY-----\n",
"client_email": "emailfromserviceaccount-compute#developer.gserviceaccount.com",
"client_id": "MYCLIENTIDISACTUALLYHERE",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/compute%40developer.gserviceaccount.com"
}
creds_json = creds.to_json
creds_json_io = StringIO.new(creds_json)
auth = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: creds_json_io,
scope["https://www.googleapis.com/auth/admin.directory.device.mobile.readonly","https://www.googleapis.com/auth/admin.directory.device.chromeos.readonly","https://www.googleapis.com/auth/admin.directory.device.mobile"]
)
auth.sub = "emailfrommyserviceaccount-
compute#developer.gserviceaccount.com"
puts auth.fetch_access_token
Please excuse the formatting.
I took the service account out of the env variable for now to make sure I can get it to work without adding extra layers of abstraction at this time.
When trying to add the additional code from the Directory Api Quickstart to the above snip I STILL RETURN THE ERROR
/var/lib/gems/2.7.0/gems/google-apis-core-0.5.0/lib/google/apis/core/http_command.rb:224:in `check_status': Unauthorized (Google::Apis::AuthorizationError)
The additional code added is below...
The last line of the previous snip gets changed to the first line of the snip that comes after this. This is to properly pass the token to the example after modifying user:Daimto's response.
authorize = auth.fetch_access_token
# Initialize the API
service = Google::Apis::AdminDirectoryV1::DirectoryService.new
service.client_options.application_name = "my-application-name"
service.authorization = authorize
# List the first 10 users in the domain
response = service.list_users(customer: "my_customer",
max_results: 10,
order_by: "email")
puts "Users:"
puts "No users found" if response.users.empty?
response.users.each { |user| puts "- #{user.primary_email} (#{user.name.full_name})" }
The method Method: mobiledevices.list requires one of the following scopes.
So to answer your first question yes you can use the https://www.googleapis.com/auth/admin.directory.device.mobile.readonly scope.
Error number 1
PERMISSION_DENIED: Request had insufficient authentication scopes.
You were probably getting this error when you had supplied a different scope.
Error 3;
Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.
There are three types of clients you can create on google cloud console.
web client
native client
service account
The json file you get from creating these clients is all different. The code that uses them is also different. The error is telling you that you have a client.json file that you are using which does not match the type of code you are using.
How to create service account credetinals
The code for a service account would be like this Not tested you may need to fix the scope. Remember that the service account needs to be configured properly on your workspace domain for the sub to work.
require 'googleauth'
require 'google/apis/admin_v1'
creds = ENV['GOOGLE_SERVICE_ACCOUNT'] # JSON downloaded from cloud console
# is saved in this ENV variable
creds_json = JSON.parse(creds)
creds_json_io = StringIO.new(creds_json.to_json)
auth = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: creds_json_io,
scope: [Google::Apis::ADMINV1::ADMIN_DIRECTORY_MOBILE_READONLY]
)
auth.sub = 'admin#yourdomain.com'
auth.fetch_access_token
Tip: You have a lot of errors there, I feel that you have been struggling with this for a while. Advice step back, have a look at the sample on the readme for the Google-api-ruby-client. Start over. Just get your auth to work. Once you get the code right and the client right all the pieces will fit into place.

Ruby gRPC server authentication SSL/TLS and a custom header with token

I need to connect to a server with authentication and a custom header.
The official gRPC docs show how to do it in Python but not in Ruby:
https://grpc.io/docs/guides/auth/#with-server-authentication-ssltls-and-a-custom-header-with-token
How can this be achieved in ruby ? There doesn't seem to be a metadata call credentials method.
I have tried the following but I'm getting Permission Denied.
channel_creds = GRPC::Core::ChannelCredentials.new()
auth_proc = proc { { 'authorization' => 'Plain ****' } }
call_creds = GRPC::Core::CallCredentials.new(auth_proc)
combined_creds = channel_creds.compose(call_creds)
#stub = Stub.new('host:port', combined_creds)
Nevermind, it was an error because of protection from the server that needed to be disabled, the above code works fine.

How to prevent error filtering the request via Rack Middleware

Hi I am having an issue in my current project, often we are receiving an error, Current application is running on Rails2.3.5 and Ruby 1.8.7
(ActionController::MethodNotAllowed) "Only getrequests are allowed."
For that I have found few options like
prevent the error blocking non GET/POST/HEAD requests using your webserver
prevent the error filtering the request via Rack Middleware
So would like to know how to prevent it via Rack Middleware.
Please some one suggest/assist me to get rid of this problem.
TIA.
You would need to create custom middleware and insert it before or after as per the requirement in application.rb.
I would need to handle json parse error in one of the projects and I have created the middle ware as below:
class CatchJsonParseErrors
def initialize(app)
#app = app
end
def call(env)
begin
#app.call(env)
rescue ActionDispatch::ParamsParser::ParseError => error
if env['HTTP_ACCEPT'] =~ /application\/json/
error_output = "There was a problem in the JSON: #{error}"
return [
400, { "Content-Type" => "application/json" },
[ { status: 400, error: error_output }.to_json ]
]
else
raise error
end
end
end
end
And added below line in application.rb file :
config.middleware.insert_before ActionDispatch::ParamsParser, "CatchJsonParseErrors"

savon-multipart - How to obtain attachments

I am using savon-multipart https://github.com/savonrb/savon-multipart to request a SOAP multipart response with an attachment (PDF). So far, this is my code:
require "savon-multipart"
client = Savon.client(
wsdl: "http://something.de?wsdl",
wsse_auth: [username: "uu", password: "??"]
)
reponse = client.call(:get_report, message: {
pdfId: 1
})
response.attachments
Authentication works fine. I can also fetch the XML-reponse. What I can't do is extract the attachment. There does not seem to exist a method for it.
According to savon-multipart's documentation
response.attachments
should contain the attachment(s). Unfortunately ruby tells me that this method is not defined.
I could't find an example implementation of savon-multipart so I'm coming to you guys :) Hope you can help me.
We had this same problem in some code. I hope this saves someone else some time in finding the solution.
When using savon-multipart, we had to add multipart: true to the parameters in call. When that parameter was added the response returned was of type Savon::Multipart::Response which has the attachments and parts methods.
reponse = client.call(:get_report, message: {
pdfId: 1
}, multipart: true)
Without that parameter, or with it set to false, the returned response is a Savon::Response object which does not have those methods.

Simple POST request failing with em-http-request

The following query works with requestmaker:
URI:
http://www.cleverbot.com/webservicemin/
Query:
start=y&icognoid=wsf&fno=0&sub=Say&islearning=1&cleanslate=false&stimulus=!!!%20there%20was%20an%20error%20!!!&icognocheck=af71393ce00d9126a247df2f53948e79
But it does not work with em-http-request:
require 'eventmachine'
require 'em-http-request'
uri = 'http://www.cleverbot.com/webservicemin/'
query = 'start=y&icognoid=wsf&fno=0&sub=Say&islearning=1&cleanslate=false&stimulus=!!!%20there%20was%20an%20error%20!!!&icognocheck=af71393ce00d9126a247df2f53948e79'
EM.run do
http = EM::HttpRequest.new(uri).post(query: query)
http.callback { puts http.response; EM.stop }
http.errback { puts 'There was an error'; EM.stop }
end
which prints There was an error. I feel stumped because this simple example works with any other method of sending a request and I've checked around to see if my usage was wrong but it doesn't seem to be.
Edit: Just for reference, this is not the correct way to use cleverbot. I made a second mistake by sending the data under :query. If you use http.post(body: query) it will work
Looks like a badly implemented server: it aborts the TCP connection without returning a proper HTTP status code, which is why you see "connection closed by server" when you query http.error.
If you change the default user agent to curl's UA string, you get a response:
http = EM::HttpRequest.new(uri).post({
:query => query,
:head => {'User-Agent' => 'curl/7.30.0'}
})

Resources