Ruby: How to access an api using HTTParty - ruby

I'm new to Ruby, and to using HTTParty, and was trying to follow the HTTParty examples from their github page to execute a basic POST. When I run the code below I get an error:
require 'pp'
require 'HTTParty'
require 'pry'
class Partay
include HTTParty
base_uri "http://<myapidomain>/search/semanticsearch/query/"
end
options= {
query: {
version: "0.4",
query: "lawyer"
}}
response = Partay.post(options)
puts response
The error I get is:
rbenv/versions/2.2.0/lib/ruby/2.2.0/uri/common.rb:715:in `URI': bad argument (expected URI object or URI string) (ArgumentError)
from ~/.ruby/2.2.0/gems/httparty-0.13.3/lib/httparty/request.rb:47:in `path='
from ~/.ruby/2.2.0/gems/httparty-0.13.3/lib/httparty/request.rb:34:in `initialize'
from ~/.ruby/2.2.0/gems/httparty-0.13.3/lib/HTTParty.rb:539:in `new'
from ~/.ruby/2.2.0/gems/httparty-0.13.3/lib/HTTParty.rb:539:in `perform_request'
from ~/.ruby/2.2.0/gems/httparty-0.13.3/lib/HTTParty.rb:491:in `post'
from json-to-csv.rb:16:in `<main>'
What I am looking for is calling a post that receives JSON in the same way that calling this URL works:
http://somedomain.com/search/semanticsearch/query/?version=0.4&query=lawyer

Noting a solution with the suggested gem - unirest:
require 'unirest'
url = "http://somedomain.com/search/semanticsearch/query"
response = Unirest.post url,
headers:{ "Accept" => "application/json" },
parameters:{ :version => 0.4, :query => "lawyer" }

Related

How to simulate a POST request in Ruby with the webmock gem?

I am trying to simulate a POST request with rspec. I thought about using the webmock gem, after searching how it worked, my code looks like this:
Gist_Request_spec.rb:
require_relative '../Gist_Request.rb'
require 'spec_helper'
require 'webmock'
include WebMock::API
WebMock.enable!
RSpec.describe GistRequest do
describe "#post" do
it "crear gist" do
stub_request(:post, "https://api.github.com/gists").
with(
body: {"description" => "description","public" => true,"files" => { "file.txt" => { "content" => "content" }}},
headers: {
'Accept'=>'*/*',
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Authorization'=>'Basic Sm9lbEFsYXlvbjEyMzo0NzVmYjI1ZWU0MGQyNGQzZGM1NWQ0MzQ5YjI4MTU3MjM1ZjdmZDBk',
'Host'=>'api.github.com',
'User-Agent'=>'Ruby'}).to_return(status: 201, body: "", headers: {})
expect(WebMock).to have_requested(:post, "https://api.github.com/gists").with { |req| req.status == 201 }
end
end
end
I added code to my file spec_helper.rb and now it looks like this:
The first lines spec_helper.rb:
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
But when I run rspec spec/Gist_Request_spec.rb, it returns the following error:
GistRequest
#post
crear gist (FAILED - 1)
Failures:
1) GistRequest#post crear gist
Failure/Error: expect(WebMock).to have_requested(:post, "https://api.github.com/gists").with { |req| req.status == 201 }
The request POST https://api.github.com/gists with given block was expected to execute 1 time but it executed 0 times
The following requests were made:
No requests were made.
============================================================
# ./spec/Gist_Request_spec.rb:21:in `block (3 levels) in <top (required)>'

how to specify namespace in SOAP request with 'savon' gem?

I am using recent version of savon gem and trying to send a SOAP request i am getting this error about invalid url:
Invalid URL: %7Bendpoint%20address%7D (ArgumentError)
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/httpi-2.3.0/lib/httpi/request.rb:27:in `url='
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/savon-2.8.0/lib/savon/operation.rb:103:in `build_request'
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/savon-2.8.0/lib/savon/operation.rb:51:in `call'
from /home/vagrant/.rvm/gems/ruby-2.1.0/gems/savon-2.8.0/lib/savon/client.rb:36:in `call'
My code is:
require "savon"
require "excon"
Excon.defaults[:ssl_verify_peer] = false
class Payback
attr_reader :connection, :client, :operation, :message
SOAP_URL = "https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl"
def initialize operation, message
#client = Savon.client(wsdl: "https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl", ssl_verify_mode: :none)
#operation = operation
#message = message
end
def response
#response ||= client.call(operation, message: message)
end
end
this is how i am using it.(I know something is wrong with namespaces)
payback = Payback.new :get_account_balance,
{"typ:Authentication" => { "typ1:Principal" => { "typ1:PrincipalValue" => 9899012182,
"typ1:PrincipalClassifier" => 3 }}}
payback.response
I need to construct this XML with savon
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://www.payback.net/lmsglobal/ws/v1/extint/types" xmlns:typ1="http://www.payback.net/lmsglobal/xsd/v1/types">
<soapenv:Header/>
<soapenv:Body>
<typ:GetAccountBalanceRequest>
<typ:Authentication>
<typ1:Principal>
<typ1:PrincipalValue>9899012182</typ1:PrincipalValue>
<typ1:PrincipalClassifier>3</typ1:PrincipalClassifier>
</typ1:Principal>
</typ:Authentication>
</typ:GetAccountBalanceRequest>
</soapenv:Body>
</soapenv:Envelope>
i don't know what i am doing wrong here, please help.
I noticed that on line 5820 of the WSDL file the location looks like this:
<soap:address location="{endpoint address}"/>
Could it be the problem?
Edited 1.
Open up in your browser: https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl
Search for {endpoint address} string on the page.
I'm far from understand this particular WSDL document, but I wonder if there must be something else in place of {endpoint address}, like a real URI. E.g. could it be the WSDL document that has the problem?
Edited 2
Tried to remove the typ and typ1 which were not recognized by the service. Ended up with a working code that returns a valid response:
puts Savon.client(
wsdl: 'https://partnertest.payback.in/PBExternalServices/v1/soap?wsdl',
endpoint: 'https://partnertest.payback.in/PBExternalServices/v1/soap',
ssl_verify_mode: :none
).call(
:get_account_balance,
:message => {
'Authentication' => {
'Principal' => {
'PrincipalValue' => 9899012182,
'PrincipalClassifier' => 3
}
}
}
)

Obtaining a render Argument Error: What is the correct syntax or usage?

I am new to Ruby, Sinatra and Pusher so this is a basic question. I am attempting to authenticate a Pusher Client (using iOS demo code https://github.com/lukeredpath/libPusher). The server code below fails with error when the iOS client attempts to join a presence channel:
ArgumentError - wrong number of arguments (1 for 2):
/Users/waveocean/.rvm/gems/ruby-1.9.3-p327/gems/sinatra-1.3.3/lib/sinatra/base.rb:665:in `render'
web.rb:13:in `auth'
web.rb:26:in `block in <main>'
/Users/waveocean/.rvm/gems/ruby-1.9.3-p327/gems/sinatra-1.3.3/lib/sinatra/base.rb:1265:in `call'
... snipped for brevity ...
Here is the code:
require 'sinatra'
require 'pusher'
require 'thin'
Thin::HTTP_STATUS_CODES[403] = "FORBIDDEN"
Pusher.app_id = 'MY-APP-ID'
Pusher.key = 'MY-KEY'
Pusher.secret = 'MY-SECRET'
def auth
response = Pusher[params[:channel_name]].authenticate(params[:socket_id], {:user_id => 101})
render :json => response
end
use Rack::Auth::Basic, "Protected Area" do |username, password|
username == 'foo' && password == 'bar'
end
post '/presence/auth' do
if params[:channel_name] == 'presence-demo'
auth
else
# render :text => "Forbidden", :status => '403'
response.status = 403
end
end
Can someone provide a suggestion or correct usage of render?
Here's is what I discovered. render is associated with Rails, and not strictly Ruby. To respond to the Sinatra route, use the following in the auth method:
def auth
response = Pusher[params[:channel_name]].authenticate(params[:socket_id], {:user_id => 101})
[200, {"Content-Type" => "application/json"}, response.to_json]
end
As it turns out, the Pusher iOS project demo provides a Scripts/auth_server.rb file with the required implementation. It is documented with the installation instructions here: https://github.com/lukeredpath/libPusher/wiki/Adding-libPusher-to-your-project .

Sinatra fails to answer to a very basic GET request

I have the following Gemfile:
source "http://rubygems.org"
gem 'sinatra', '1.3.2'
gem 'json', '1.6.4'
And the following Sinatra application:
require 'sinatra'
require 'json'
get '/ze/api/session.json' do
content_type :json
{ :name => 'name' }
end
And when I make a basic request like this one:
curl localhost:4567/ze/api/session.json
I get this:
[2012-01-13 17:30:36] ERROR TypeError: can't convert Array into String
/Users/mauricio/.rvm/gems/ruby-1.9.2-p290#office-drop-sync/gems/rack-1.4.0/lib/rack/handler/webrick.rb:72:in `block in service'
/Users/mauricio/.rvm/gems/ruby-1.9.2-p290#office-drop-sync/gems/rack-1.4.0/lib/rack/handler/webrick.rb:71:in `each'
/Users/mauricio/.rvm/gems/ruby-1.9.2-p290#office-drop-sync/gems/rack-1.4.0/lib/rack/handler/webrick.rb:71:in `service'
/Users/mauricio/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpserver.rb:111:in `service'
/Users/mauricio/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpserver.rb:70:in `run'
/Users/mauricio/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'
localhost - - [13/Jan/2012:17:30:36 BRT] "GET /ze/api/session.json HTTP/1.1" 500 311
I am using Ruby 1.9.2 with RVM in a Lion Mac.
You're trying to return a hash from the route, but a hash isn't something you can return here.
Simply use .to_json to turn the hash into a json string which you can then return (you've required json, but aren't using it yet):
get '/ze/api/session.json' do
content_type :json
{ :name => 'name' }.to_json
end

How to use mocha outside of unit tests?

I'm trying to use mocha outside of unit tests to mock an Net::HTTPResponse object. here is a simple example:
#!/usr/bin/env ruby -w
require 'net/http'
require 'rubygems'
require 'mocha'
response = mock('Net::HTTPResponse')
response.stubs(:code => '500', :message => "Failed", :content_type => "text/plaint", :body => '')
I get this error:
undefined method `mock' for main:Object (NoMethodError)
I'd recommend using the fakeweb gem for this. It's designed to stub out http requests.
require 'rubygems'
require 'fakeweb'
FakeWeb.register_uri(:get, "http://something.com/", :body => "", :status => ["500", "Server Error"])
More info: https://github.com/chrisk/fakeweb

Resources