How to do a simple GraphQL query in a native Ruby script - ruby

I'm trying to figure out how to do a simple GraphQL query without using gems. The following cURL commands works
curl -X POST "https://gql.example.com/graphql/public" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{ "query": "query { user { id defaultEmail } }", "variables": {} }'
and the corresponding javascript code is
fetch('https://gql.example.com/graphql/public', {
method: 'POST',
headers: {
'Authorization': 'Bearer <ACCESS_TOKEN>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: 'query { user { id defaultEmail } }',
variables: {}
})
})
.then(r => r.json())
.then(data => console.log(data));
Is it possible to do this easily in Ruby without using the graphql gem? I only need to do simple queries like the examples above so I'm hoping it's easy to do them in a single Ruby script.

You can use Ruby core lib Net/HTTP and build your requests like so:
require 'net/http'
uri = URI('https://gql.example.com/graphql/public')
params = {'query': 'query { user { id defaultEmail } }', 'variables': {} }
headers = {
"Authorization'=>'Bearer #{ENV['MY_ACCESS_TOKEN']}",
'Content-Type' =>'application/json',
'Accept'=>'application/json'
}
https = Net::HTTPS.new(uri.host, uri.port)
response = https.post(uri.path, params.to_json, headers)
See this answer as well

Related

Spring Boot WebClient Sending Basic GraphQL POST Request As a Raw String

I'm trying to get even a basic query to send to my graphql server using WebClient, I have the following:
String query = "{ query: 'query testQuery { testData }' }";
String response = WebClient.builder().build().post().uri("http://localhost:4020/graphql")
.bodyValue(query).retrieve().bodyToMono(String.class).block();
This is always producing a 400 Bad Request from POST response.
On the sever side, however, I am not seeing anything in the request body, here is the debugging output from my node server (ApolloServer):
[1] headers: {
[1] 'accept-encoding': 'gzip',
[1] 'user-agent': 'ReactorNetty/1.0.20',
[1] host: 'localhost:4020',
[1] accept: '*/*',
[1] 'content-type': 'text/plain;charset=UTF-8',
[1] 'content-length': '49'
[1] }
[1] baseUrl: /graphql
[1] body: {}
I have tried a number of different combinations to get this to work, to no avail.
In order to ensure the API is functioning for this call, the following curl command works:
curl --request POST \
--header 'content-type: application/json' \
--url http://localhost:4020/graphql \
--data '{"query":"query testQuery { testData }" }'
[1] headers: {
[1] host: 'localhost:4020',
[1] 'user-agent': 'curl/7.79.1',
[1] accept: '*/*',
[1] 'content-type': 'application/json',
[1] 'content-length': '41'
[1] }
[1] baseUrl: /graphql
[1] body: { query: 'query testQuery { testData }' }
Edit
So this seems to be related to the this github issue, there are 2 things, 'application/json' is required and rawbytes must be used to send strings. The following code works:
String query = "{ \"query\": \"query testQuery { testData }\" }";
String response = WebClient.builder().build().post().uri("http://localhost:4020/graphql")
.contentType(MediaType.APPLICATION_JSON).bodyValue(query.getBytes()).retrieve()
.bodyToMono(String.class).block();

Users_not_found in HTTParty request to SlackAPI when curl works

I'm trying to use GET request using httparty gem to have info about specific user from SlackAPI. From curl it works well
curl --data "token=SLACK_TOKEN&email=user#example.com" https://slack.com/api/users.lookupByEmail
But my code below seems to be broken because I received an error {"ok":false,"error":"users_not_found"}
module Slack
class GetUserId
def call
response = HTTParty.get("https://slack.com/api/users.lookupByEmail", payload: payload, headers: headers)
end
def headers
{
'Content-Type' => 'application/json',
'Authorization' => 'Bearer SLACK_TOKEN'
}
end
def payload
{
email: "user#example.com"
}.to_json
end
end
end
If you check their documentation, it seems that API do not accept JSON-form but rather "application/x-www-form-urlencoded.
So something like:
headers: {
'Authorization' => 'Bearer SLACK_TOKEN,
"Content-Type" => "application/x-www-form-urlencoded"
},
body: {
"token=SLACK_TOKEN”,
”email=user#example.com"
...
Reference: https://api.slack.com/methods/users.lookupByEmail

Ruby RestClient GET request with payload

Please help me with the following:
I have a number of application and associated records.
app with id 1 has: record1, record2 and record3.
app with id 2 has: record1 ... record1000
To filter out records for app 1 Im using curl. I can get records with the following command:
curl -i -H "accept: application/json" -H "Content-type: application/json" -X GET -d '{ "filters": { "app_id":"1" }}' http://[rails_host]/v1/records?token=[api_token]
How can I do the same but with ruby RestClient (gem 'rest-client' '1.7.2')
To get all records I do the following:
RestClient.get("http://[rails_host]/v1/records?token=[api_token]", { :content_type => 'application/json', :accept => 'application/json'})
The Problem is that app ids are not returned so I cannot parse response and take records that has app id = 1
Any ideas how can I add payload to Restclient.get to filter out records?
You can see in the docs here that the only high level helpers that accept a payload argument are POST, PATCH, and PUT. To make a GET request using a payload you will need to use RestClient::Request.execute
This would look like:
RestClient::Request.execute(
method: :get,
url: "http://[rails_host]/v1/records?token=[api_token]",
payload: '{ "filters": { "app_id":"1" } }',
headers: { content_type: 'application/json', accept: 'application/json'}
)

Microsoft Azure get access token API not working with cURL/Ruby but works with powershell

I am simply trying to get an access token from client id, client secret and tenant ID. Following powershell command works successfully
Invoke-RestMethod -Uri https://login.microsoftonline.com/TENANT/oauth2/token?api-version=1.0 -Method Post -Body #{"grant_type" = "client_credentials"; "resource" = "https://management.core.windows.net/"; "client_id" = "CLIENTID"; "client_secret" = "SECRET" }
But this curl doesn't work
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials&resource=https://management.core.windows.net/&client_id=CLIENTID&client_secret=SECRET" "https://login.microsoftonline.com/TENANT/oauth2/token?api-version=1.0"
Neither this ruby script
require 'json'
require 'typhoeus'
url = 'https://login.microsoftonline.com/TENANT/oauth2/token?api-version=1.0'
params = "grant_type=client_credentials&resource=https://management.core.windows.net/&client_id=CLIENTID&client_secret=SECRET"
HEADERS = {
"Content-Type" => "application/x-www-form-urlencoded"
}
resp = Typhoeus::Request.post(url, body: params, headers: HEADERS)
I am following this link. Any clues why neither of curl / ruby works ?
Thanks in advance
I tried to reproduce your issue successfully, and I discovered that the issue was caused by curl without OpenSSL and Typhoeus request without setting ssl_verifypeer: false.
So please follow this to check via curl --version and install openssl libraries on your environment.
Here is my sample code.
require "typhoeus"
url = 'https://login.microsoftonline.com/<tanet-id>/oauth2/token?api-version=1.0'
params = "grant_type=client_credentials&resource=https://management.core.windows.net/&client_id=<client-id>&client_secret=<client-key>"
headers = {
"Content-Type" => "application/x-www-form-urlencoded"
}
request = Typhoeus.post(url, body: params, headers: headers, ssl_verifypeer: false)
puts request.code, request.body
Hope it helps.

Ruby rest-client returning 401 while curl command works

I have a working curl command which returns exactly what I want, bunch of JSON:
curl -D- -u username:password -X GET -H "Content-Type: application/json" https://stash.address.net/rest/api/1.0/projects/FOOBAR/repos\?limit\=1000
And I need to transform it into RestClient::Request, but I am still getting 401 back:
RestClient::Request.execute(
method: :get,
headers: {
content_type: 'application/json'
},
username: 'username',
password: 'password',
url: 'https://stash.address.net/rest/api/1.0/projects/FOOBAR/repos',
params: {
limit: '1000'
},
verify_ssl: false
)
Did I forget something? Is there something missing from my request? Isn't it exactly same as the curl command above?
From the documentation I don't see any mention of the username and params options. They suggest to interpolate the value in the URL.
RestClient.get 'https://username:password#stash.address.net/rest/api/1.0/projects/FOOBAR/repos', { accept: :json, params: { limit: 1000 }}

Resources