Webmock not registering my request stubs correctly - ruby

I am registering a request stub as follows:
url = "http://www.example.com/1"
stub_request(:get, url).
with(body: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project>\n <id>1</id>\n</project>\n",
headers: {
'Accept' => 'application/xml',
'Content-type' => 'application/xml',
'User-Agent' => 'Ruby',
'X-Trackertoken' => '12345'
}).
to_return(status: 200, body: '', headers: {})
for some reason when I run bundle exec rspec spec, my specs fails saying that the request isn't registered yet. The registered stub is this,
stub_request(:get, "http://www.example.com/1").
with(body: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project>\n <id>1</id>\n</project>\n",
headers: {
'Accept' => 'application/xml',
'Content-type' => 'application/xml',
'User-Agent' => 'Ruby',
'X-Trackertoken' => '12345'
})
note that the to_return part is missing
I tried replacing the body header with an empty string, the request stub is registered correctly but then my specs will still fail because they are expecting some value from the body other than the empty string. Thus, it is really important that I assign a value to body.
In my spec I am calling this method:
def find(id)
require 'net/http'
http = Net::HTTP.new('www.example.com')
headers = {
"X-TrackerToken" => "12345",
"Accept" => "application/xml",
"Content-type" => "application/xml",
"User-Agent" => "Ruby"
}
parse(http.request(Net::HTTP::Get.new("/#{id}", headers)).body)
end
Any ideas on why this is happening?
Thanks.

The problem is that your stub is matching a GET request with a non-empty body of <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project>\n <id>1</id>\n</project>\n, but when you make the request you're not including any body, so it doesn't find the stub.
I think you're confused about what body is what here. The body in the with method arguments is the body of the request you are making, not the body of the response. What you probably want is a stub like this:
url = "http://www.example.com/1"
stub_request(:get, url).
with(headers: {
'Accept' => 'application/xml',
'Content-type' => 'application/xml',
'User-Agent' => 'Ruby',
'X-Trackertoken' => '12345'
}).
to_return(status: 200,
body: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project>\n <id>1</id>\n</project>\n",
headers: {})

Related

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

Header parameter missing when making POST request using Rest-Client Ruby Gem

Hi I am successfully able to post from Post man , but unable to do so from Ruby Rest client.
Post details
Post Man Request
POST /endpoint HTTP/1.1
Host: host:11400
Accept: application/json
HTTP_USER: userid
fname: fname
lname: lname
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 589a5345-e384-bd71-d690-60987165487b
{ "rtdt":"09/08/2016","jobs":[{"pid":53} , {"pid":54}]}
the rest code I ve tried multiple ways including below
method tried
p RestClient.post 'http://url_details',
Accept: 'application/json',
'HTTP_USER'.to_sym => 'userid',
fname: 'name',
lname: '',
'Content-Type'.to_sym => 'application/json',
payload: JSON.parse('{ "rtdt":"09/08/2016","jobs":[{"pid":53} , {"pid":54}]}')
method tried
p RestClient.post 'http://url_details/job', http_user: 'userid', content_type: :json, accept: :json
method tried
p #uber_ride = (RestClient::Request.execute(
:method => :post,
:url => 'http://url_details/job',
'HTTP_USER' => 'userid',
:headers => {:content_type => 'application/json', :accept => 'application/json', :HTTP_USER => 'userid', :fname => 'name', :lname => 'lname'}
))
method tried
p '++++++++++++++++++++++++++++++++'
p RestClient.post($Current_Api_Endpoint,
$Current_Payload,
:http_user =>'userid',
headers:
{:accept => 'application/json',
:content_type => 'application/json',
:http_user =>'userid',
:fname => 'name',
:lname => 'lname'}
)
p '++++++++++++++++++++++++++++++++'
method tried
p env1 = ENV['http_proxy']
# p a = {:method => :post, :url => 'http://url_details/job', :headers => { :accept => 'application/json', :content_type => 'application/json', :http_user => 'userid', :fname => 'name', :lname => 'lname' }, :payload => { :rtdt => "06/10/2016",:jobs => [{:pid => 53} , {:pid => 54}]} }
p a = {
method: 'post',
url: 'http://url_details/job',
proxy: ENV['http_proxy'],
headers: {accept: 'application/json', content_type: 'application/json', http_user: 'userid', fname: 'name', lname: 'lname'},
payload: { rtdt: '06/10/2016', jobs: {pid: 53}}
}
I am getting error
HTTP Status 500 - HTTP_USER header not found in request
torg.springframework.security.web.authentication
I Found out the issue since then. All headers are able to be sent, except this one - This one in CAPS. rest of them in small characters. How to solve it
Ruby's Net::HTTP implementation does not transmit ALL_CAPS_UNDERSCORED header names. RestClient relies on Net::HTTP. So, for example, the HTTP_USER header is actually transformed into Http_user when transmitted.
Alertnative: curb
Curl, however, does not have this limitation. It transmits header names verbatim. Therefore instead of using RestClient, you could use the curb gem, which is a wrapper around libcurl. This seems to work:
require "curb"
Curl::Easy.http_post("http://URL_REDACTED") do |http|
http.headers["Accept"] = "application/json"
http.headers["Content-Type"] = "application/json"
http.headers["HTTP_USER"] = "userid"
http.post_body = '{ "rtdt":"09/08/2016","jobs":[{"pid":53} , {"pid":54}]}'
end
Alternative: excon
The excon gem is another possibility. It implements HTTP in pure Ruby, without relying on Net::HTTP. It does its own header processing and allows ALL_CAPS headers. So this should work:
require "excon"
Excon.post(
"http://URL_REDACTED",
:headers => {
"Accept" => "application/json",
"Content-Type" => "application/json",
"HTTP_USER" => "userid"
},
:body => '{ "rtdt":"09/08/2016","jobs":[{"pid":53} , {"pid":54}]}'
)
Anyway, I would argue that the server you are trying to connect to is ultimately at fault here, because headers are supposed to be evaluated as case-insensitive: Are HTTP headers case-sensitive?. If the server requires a header be in all uppercase, that is a bug.
The RestClient README examples indicate that the correct usage is:
RestClient.post(url, payload, headers)
So all you have to do is:
RestClient.post(
"http://URL_REDACTED",
'{ "rtdt":"09/08/2016","jobs":[{"pid":53} , {"pid":54}]}',
content_type: :json,
accept: :json,
"HTTP_USER" => "userid"
)
I tested against http://requestb.in and got the expected headers and body:
HEADERS
Total-Route-Time: 0
Connection: close
Via: 1.1 vegur
Connect-Time: 0
Http-User: userid
Content-Type: application/json
Content-Length: 55
User-Agent: rest-client/2.0.0 (darwin15.4.0 x86_64) ruby/2.3.1p112
X-Request-Id: c7cd819f-8901-41b9-8cbb-3b6d1895cd67
Accept-Encoding: gzip
Host: requestb.in
Accept: application/json
RAW BODY
{ "rtdt":"09/08/2016","jobs":[{"pid":53} , {"pid":54}]}

Api Requests with Ruby gem Typhoeus

What is wrong with the following request?
request = Typhoeus::Request.new("http://fluidsurveys.com/api/v2/groups",
method: :get,
userpwd: "test_user:test_password",
headers: { 'ContentType' => "application/json"})
response = request.body
puts response
This returns undefined method body for #<Typhoeus::Request:0x007f8e50d3b1d0> (NoMethodError)
The following request works fine with httparty:
call= "/api/v2/groups/"
auth = {:username => "test_user", :password => "test_password"}
url = HTTParty.get("http://fluidsurveys.com/api/v2/groups",
:basic_auth => auth,
:headers => { 'ContentType' => 'application/json' } )
response = url.body
puts response
EDIT:
I tried this:
response = request.response
puts response.body
with no luck. I receive this : undefined method body for nil:NilClass (NoMethodError)
From https://github.com/typhoeus/typhoeus
You need to do the get before the response body is available.
EDIT: Here is an operable solution. It doesn't use your website, which I couldn't access even manually. But, this returns response code 200 and the response_body. Running this in my debugger showed the complete response, which you could see using "puts response.inspect".
class TyphoeusTry
require 'typhoeus'
request = Typhoeus::Request.new("http://www.google.com",
method: :get,
userpwd: "test_user:test_password",
headers: { ContentType: "application/json"})
response = request.run
puts response.response_body
end
The problem is that you didn't actually execute your request. The following code should work.
request = Typhoeus::Request.new("http://fluidsurveys.com/api/v2/groups",
method: :get,
userpwd: "test_user:test_password",
headers: { 'ContentType' => "application/json"})
request.run
response = request.response
response_code = response.code
response_body = response.body

How can I get HTTParty to recognize ":footer" and ":collector" parameters?

I received the following code from a development team:
curl -u EMAILADDRESS:PASSWORD -d "sender=NAME <EMAILADDRESS>&message=[Invite Link]&collector=COLLECTOR&subject=Test Invite&footer=My Custom Text [Unsubscription Link]"
I have been told that the above works fine. This is what I translated it to in Ruby 1.9.3, using the httparty gem:
call= "/api/v2/emails/?survey=#{i}"
puts collector_final_id
url= HTTParty.post("https://www.fluidsurveys.com#{call}",
:basic_auth => auth,
:headers => { 'Content-Type' => 'application/x-www-form-urlencoded','Accept' => 'application/x-www-form-urlencoded' },
:collector => collector,
:body => {
"subject" => "Test Invite",
"sender" => "NAME <EMAILADDRESS>",
"message" => "[Invite Link]"
},
:footer => "My Custom Text [Unsubscription Link]"
)
Everything within this works fine except for the :footer and :collector parameters. It doesn't seem to recognize them at all.
There are no errors thrown, they just aren't included in the actual email I am sending. What am I doing wrong when passing in those two parameters?
Your :collector and :footer are not correct.
I wrote a little Sinatra service to receive a POST request with any parameters:
require 'pp'
require 'sinatra'
post "/*" do
pp params
end
And ran it, launching the web-server on my Mac OS laptop. As Sinatra apps do, it resides at 0.0.0.0:4567.
Running this code:
require 'httparty'
url = HTTParty.post(
"http://localhost:4567/api/v2/emails?survey=1",
:headers => {
'Content-Type' => 'application/x-www-form-urlencoded',
'Accept' => 'application/x-www-form-urlencoded'
},
:body => {
"subject" => 'subject',
"sender" => 'sender',
"message" => 'message',
},
:collector => 'collector',
:footer => 'footer'
)
puts url
Outputs:
["survey", "1"]["subject", "subject"]["sender", "sender"]["message", "message"]["splat", ["api/v2/emails"]]["captures", ["api/v2/emails"]]
Sinatra said:
127.0.0.1 - - [11/Sep/2013 17:58:47] "POST /api/v2/emails?survey=1 HTTP/1.1" 200 - 0.0163
{"survey"=>"1",
"subject"=>"subject",
"sender"=>"sender",
"message"=>"message",
"splat"=>["api/v2/emails"],
"captures"=>["api/v2/emails"]}
Changing :collector and :footer to strings and moving them inside the body, where they should be:
require 'httparty'
url = HTTParty.post(
"http://localhost:4567/api/v2/emails?survey=1",
:headers => {
'Content-Type' => 'application/x-www-form-urlencoded',
'Accept' => 'application/x-www-form-urlencoded'
},
:body => {
"subject" => 'subject',
"sender" => 'sender',
"message" => 'message',
'collector' => 'collector',
'footer' => 'footer'
},
)
puts url
Outputs:
["survey", "1"]["subject", "subject"]["sender", "sender"]["message", "message"]["collector", "collector"]["footer", "footer"]["splat", ["api/v2/emails"]]["captures", ["api/v2/emails"]]
And Sinatra said:
127.0.0.1 - - [11/Sep/2013 18:04:13] "POST /api/v2/emails?survey=1 HTTP/1.1" 200 - 0.0010
{"survey"=>"1",
"subject"=>"subject",
"sender"=>"sender",
"message"=>"message",
"collector"=>"collector",
"footer"=>"footer",
"splat"=>["api/v2/emails"],
"captures"=>["api/v2/emails"]}
The problem is, the POST request ONLY uses a URL and a :body hash. Inside the :body hash go all the variables you're sending to the server. That's why the second version of the code, with 'collector' and 'footer' works.
There is no comma after your :body parameter

Setting Request Headers in Ruby

I have the rest client gem and I am defining a request like this:
url = 'http://someurl'
request = {"data" => data}.to_json
response = RestClient.post(url,request,:content_type => :json, :accept => :json)
However I need to set the HTTP header to something. For example an API key. Which could be done in curl as:
curl -XHEAD -H x-auth-user: myusername -H x-auth-key: mykey "url"
Whats the best way to do this in ruby? Using this gem? Or can I do it manually to have more control.
The third parameter is the headers hash.
You can do what you want by:
response = RestClient.post(
url,
request,
:content_type => :json, :accept => :json, :'x-auth-key' => "mykey")
You can also do this
RestClient::Request.execute(
:method => :get or :post,
:url => your_url,
:headers => {key => value}
)
I had the same problem with Rest-Client (1.7.2) I need to put both params and HTTP headers.
I solved with this syntax:
params = {id: id, device: device, status: status}
headers = {myheader: "giorgio"}
RestClient.put url, params, headers
I hate RestClient :-)
If PUT isn't allowed we can pass it in the header of POST. Headers in bold. This worked for me:
act_resp = RestClient.post url, req_param, **:content_type => :json, :method => :put**

Resources