Ruby Program isn't returning results from httparty get request - ruby

I am having issues with the following code. I am not getting any errors but for some reason my results are coming back empty every time I use a search keyword that has a space in the string. I have tried using urleescape but that also doesn't work. Does anyone have any insight?
require 'httparty'
require 'uri'
class Recipe
include HTTParty
base_uri 'recipepuppy.com'
default_params onlyImages: "1"
format :json
#Uses request parameter to send to API
def self.for(q)
q = URI.escape(q)
p q
get("/api", query: {q: q})["results"]
end
end
puts Recipe.for "chocolate"
puts Recipe.for "apple pie"

Related

Create webhook for a payment Gateway

So, I've been following this guide: https://docs.github.com/pt/developers/webhooks-and-events/webhooks/creating-webhooks
This is my code:
require 'sinatra'
require 'json'
require 'openssl'
post '/payload' do
request.body.rewind
header_token = request.env["zzzzzzzzzzzzzzzzzzzz"]
payload_body = request.body.read
verify_signature(payload_body)
push = JSON.parse(payload_body)
"I got some JSON: #{push.inspect}"
end
def verify_signature(payload_body)
signature = 'sha256=' + (OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'),
ENV['jksdaskçjdaskçdhaskdhakdhaskdhaskdhaskdaskdasdkh'],
payload_body))
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])
end
When I load http://localhost:4567 i get :
Sinatra doesn’t know this ditty.
If I change Post to Get (trying to see if it is working) :
no implicit conversion of nil into String file: payload.rb location:
hexdigest line: 15
I'm pretty new to this and I'm attempting to create a prestashop module for a payment gateway, but this webhook thing is messing with me.
Im I doing something wrong? Is there a easy way? Is it everything correct?
Thanks

Parsed_response in Ruby from HTTP

How can i get parsed_response from here?
require 'HTTParty'
require 'httparty/request'
require 'httparty/response/headers'
class CRUD
include HTTParty
def retrieve
##response = CRUD.get('http://dummy.restapiexample.com/api/v1/employee/id')
end
end
{"id":"719","employee_name":"test","employee_salary":"123","employee_age":"23","profile_image":""}
puts #manter_user.retrieve.parsed_response['employee_name'] -- dont work
puts CRUD.class_variable_get(:##response).parsed_response['employee_name'] -- dont work
It's an instance method, it means that you need to create an instance. And you don't need global variable. And it is bad idea to name class with all uppercase letters - this style is used for constants. Classes and modules use MixedCase and have no underscores, each word starts with an uppercase letter.
class Crud
include HTTParty
def retrieve
self.class.get('http://dummy.restapiexample.com/api/v1/employee/id')
end
end
> Crud.new.retrieve.parsed_response
Since you are getting the JSON response, you can parsed it back as
require 'json'
foo = JSON['{"id":"719","employee_name":"test","employee_salary":"123","employee_age":"23","profile_image":""}']
puts foo['employee_name'] # => test

How to test HTTParty API call with Ruby and RSpec

I am using the HTTParty gem to make a call to the GitHub API to access a list of user's repos.
It is a very simple application using Sinatra that displays a user's favourite programming language based on the most common language that appears in their repos.
I am a bit stuck on how I can write an RSpec expectation that mocks out the actual API call and instead just checks that json data is being returned.
I have a mock .json file but not sure how to use it in my test.
Any ideas?
github_api.rb
require 'httparty'
class GithubApi
attr_reader :username, :data, :languages
def initialize(username)
#username = username
#response = HTTParty.get("https://api.github.com/users/#{#username}/repos")
#data = JSON.parse(#response.body)
end
end
github_api_spec.rb
require './app/models/github_api'
require 'spec_helper'
describe GithubApi do
let(:github_api) { GithubApi.new('mock_user') }
it "receives a json response" do
end
end
Rest of the files for clarity:
results.rb
require 'httparty'
require_relative 'github_api'
class Results
def initialize(github_api = Github.new(username))
#github_api = github_api
#languages = []
end
def get_languages
#github_api.data.each do |repo|
#languages << repo["language"]
end
end
def favourite_language
get_languages
#languages.group_by(&:itself).values.max_by(&:size).first
end
end
application_controller.rb
require './config/environment'
require 'sinatra/base'
require './app/models/github_api'
class ApplicationController < Sinatra::Base
configure do
enable :sessions
set :session_secret, "#3x!ilt£"
set :views, 'app/views'
end
get "/" do
erb :index
end
post "/user" do
#github = GithubApi.new(params[:username])
#results = Results.new(#github)
#language = #results.favourite_language
session[:language] = #language
session[:username] = params[:username]
redirect '/results'
end
get "/results" do
#language = session[:language]
#username = session[:username]
erb :results
end
run! if app_file == $0
end
There are multiple ways you could approach this problem.
You could, as #anil suggested, use a library like webmock to mock the underlying HTTP call. You could also do something similar with VCR (https://github.com/vcr/vcr) which records the results of an actual call to the HTTP endpoint and plays back that response on subsequent requests.
But, given your question, I don't see why you couldn't just use an Rspec double. I'll show you how below. But, first, it would be a bit easier to test the code if it were not all in the constructor.
github_api.rb
require 'httparty'
class GithubApi
attr_reader :username
def initialize(username)
#username = username
end
def favorite_language
# method to calculate which language is used most by username
end
def languages
# method to grab languages from repos
end
def repos
repos ||= do
response = HTTParty.get("https://api.github.com/users/#{username}/repos")
JSON.parse(response.body)
end
end
end
Note that you do not need to reference the #username variable in the url because you have an attr_reader.
github_api_spec.rb
require './app/models/github_api'
require 'spec_helper'
describe GithubApi do
subject(:api) { described_class.new(username) }
let(:username) { 'username' }
describe '#repos' do
let(:github_url) { "https://api.github.com/users/#{username}/repos" }
let(:github_response) { instance_double(HTTParty::Response, body: github_response_body) }
let(:github_response_body) { 'response_body' }
before do
allow(HTTParty).to receive(:get).and_return(github_response)
allow(JSON).to receive(:parse)
api.repos
end
it 'fetches the repos from Github api' do
expect(HTTParty).to have_received(:get).with(github_url)
end
it 'parses the Github response' do
expect(JSON).to have_received(:parse).with(github_response_body)
end
end
end
Note that there is no need to actually load or parse any real JSON. What we're testing here is that we made the correct HTTP call and that we called JSON.parse on the response. Once you start testing the languages method you'd need to actually load and parse your test file, like this:
let(:parsed_response) { JSON.parse(File.read('path/to/test/file.json')) }
You can mock those API calls using https://github.com/bblimke/webmock and send back mock.json using webmock. This post, https://robots.thoughtbot.com/how-to-stub-external-services-in-tests walks you through the setup of webmock with RSpec (the tests in the post mock GitHub API call too)

case sensitive headers in get request using httparty in rails

I'm currently getting an error when I make a GET request using httparty. The call works when I use curl. The error is as follows:
\"Authdate\":\"1531403501\"}" }, { "error_code":
"external_auth_error", "error_message": "Date header is missing or
timestamp out of bounds" } ] }
When I make the request via curl this is the header I use.
curl -X GET -H "AuthDate: 1531403501"
However, as you can see, the request changes from AuthDate to Authdate causing the error. Here is how I'm making the call:
require 'openssl'
require 'base64'
module SeamlessGov
class Form
include HTTParty
attr_accessor :form_id
base_uri "https://nycopp.seamlessdocs.com/api"
def initialize(id)
#api_key = ENV['SEAMLESS_GOV_API_KEY']
#signature = generate_signature
#form_id = id
#timestamp = Time.now.to_i
end
def relative_uri
"/form/#{#form_id}/elements"
end
def create_form
self.class.get(relative_uri, headers: generate_headers)
end
private
def generate_signature
OpenSSL::HMAC.hexdigest('sha256', ENV['SEAMLESS_GOV_SECRET'], "GET+#{relative_uri}+#{#timestamp}")
end
def generate_headers
{
"Authorization" => "HMAC-SHA256 api_key='#{#api_key}' signature='#{#signature}'",
"AuthDate" => #timestamp
}
end
end
end
any workaround this?
Headers are case-insensitive per the spec https://stackoverflow.com/a/41169947/1518336, so it seems like the server you're accessing is in the wrong.
Looking at Net::HTTPHeader, on which HTTParty is implemented
Unlike raw hash access, HTTPHeader provides access via case-insensitive keys
It looks like the class downcases the header keys for uniformity.
You'll likely need to look at a different networking library which doesn't rely on the net/http. Perhaps curb?
There is a work around this in the following article
https://github.com/jnunemaker/httparty/issues/406#issuecomment-239542015
I created the file lib/net_http.rb
require 'net/http'
class Net::HTTP::ImmutableHeaderKey
attr_reader :key
def initialize(key)
#key = key
end
def downcase
self
end
def capitalize
self
end
def split(*)
[self]
end
def hash
key.hash
end
def eql?(other)
key.eql? other.key.eql?
end
def to_s
def self.to_s
key
end
self
end
end
Then in the headers
def generate_headers
{
"Authorization" => "HMAC-SHA256 api_key='#{#api_key}' signature='#{#timestamp}'",
Net::HTTP::ImmutableHeaderKey.new('AuthDate') => "#{#timestamp}"
}
end

How to get ALL of the URL parameters in a Sinatra app

Using the following Sinatra app
get '/app' do
content_type :json
{"params" => params}.to_json
end
Invoking:
/app?param1=one&param2=two&param2=alt
Gives the following result:
{"params":{"param1":"one","param2":"alt"}}
Params has only two keys, param1 & param2.
I understand Sinatra is setting params as a hash, but it does not represent all of the URL request.
Is there a way in Sinatra to get a list of all URL parameters sent in the request?
Any request in rack
get '/app' do
params = request.env['rack.request.query_hash']
end
I believe by default params of the same name will be overwritten by the param that was processed last.
You could either setup params2 as an array of sorts
...&param2[]=two&param2[]=alt
Or parse the query string vs the Sinatra provided params hash.
kwon suggests to parse the query string.
You can use CGI to parse it as follows:
require 'cgi'
get '/app' do
content_type :json
{"params" => CGI::parse(request.query_string)}.to_json
end
Invoking:
/app?param1=one&param2=two&param2=alt
Gives the following result:
{"params":{"param1":["one"],"param2":["two","alt"]}}
You can create a helper to make the process more friendly:
require 'cgi'
helpers do
def request_params_repeats
params = {}
request.env["rack.input"].read.split('&').each do |pair|
kv = pair.split('=').map{|v| CGI.unescape(v)}
params.merge!({kv[0]=> kv.length > 1 ? kv[1] : nil }) {|key, o, n| o.is_a?(Array) ? o << n : [o,n]}
end
params
end
end
You can then access the parameters in your get block:
get '/app' do
content_type :json
request_params_repeats.to_json
end

Resources