How to fix Net::ReadTimeout in SOAP API using Savon Ruby gem? - ruby

My script works but due to some reason it is throwing Net::ReadTimeout error. I presume due to high number of connections to the API. Any way to delay timeout using Savon? Thanks.
wsdl = 'https://org.my.domain/webservices/myservice.asmx?WSDL'
# Open Client Webservice
client = Savon.client(wsdl: wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1, convert_request_keys_to: :none)
# Connect to Webservice - Authenticate
response = client.call(:authenticate, message: { username: 'user', password: 'pwd', organization: 'org', domain: 'my.domain' })

You will want to increase the read timeout if you cannot decrease the amount of calls you are making to the API. In reality, your programs should always be respectful to the resource they are interacting with and should allow for other programs to access them without detracting from performance.
If you did want to increase the read timeout, the syntax would depend what version you are using, for version 2.x:
client = Savon.client(
wsdl: wsdl,
ssl_verify_mode: :none,
ssl_version: :TLSv1,
convert_request_keys_to: :none,
open_timeout: 400,
read_timeout: 400,
)
For version 3.x:
client.http.send_timeout = 400
client.http.receive_timeout = 400
Be wary these are seconds.

Related

Ruby hipchat gem invalid send file

So this is related to an earlier post I made on this method. This is essentially what I am using to send files via hipchat:
#!/usr/bin/env ruby
require 'hipchat'
client = HipChat::Client.new('HIPCHAT_TOKEN', :api_version => 'v2', :server_url => 'HIPCHAT_URL')
client.user('some_username').send_file('message', File.open('./output/some-file.csv') )
client['some_hipchat_room'].send_file('some_user', 'message', File.open('./output/some-file.csv') )
Now for some reason the send_file method is invalid:
/path/to/gems/hipchat-1.5.4/lib/hipchat/errors.rb:40:in `response_code_to_exception_for': You requested an invalid method. path:https://hipchat.illum.io/v2/user/myuser#myemail/share/file?auth_token=asdfgibberishasdf method:Net::HTTP::Get (HipChat::MethodNotAllowed)
from /path/to/gems/gems/hipchat-1.5.4/lib/hipchat/user.rb:50:in `send_file'
I think this indicating that you should be using POST instead of GET, but I'm not sure because I haven't used this library nor Hipchat.
Looking at the question you referenced and the source posted by another user they're sending the request using self.class.post, and your debug output shows Net::HTTP::Get
To debug, could you try,
file = Tempfile.new('foo').tap do |f|
f.write("the content")
f.rewind
end
user = client.user(some_username)
user.send_file('some bytes', file)
The issue is that I was attempting to connect to the server via http instead of https. If the following client is causing issues:
client = HipChat::Client.new('HIPCHAT_TOKEN', :api_version => 'v2', :server_url => 'my.company.com')
Then try adding https:// to the beginning of your company's name.
client = HipChat::Client.new('HIPCHAT_TOKEN', :api_version => 'v2', :server_url => 'https://my.company.com')

Ruby TCP server - ERROR:PG::ConnectionBad: FATAL: remaining connection slots are reserved for non-replication superuser connections

I have written a tcp server that receives packets from a terminal device. The TCP server interprets the data and saves it in the database using postgres.
The tcp server is multi-threaded. A sample of the code of the moment i open the db connection and save data looks like this;
conn = Sequel.connect('postgres://xxxxx:xxxxxxxxxx#127.0.0.1:xxxxx/xxxxxxxxx',:max_connections => 100) # requires pg
transactions = conn.from(:transactions)
if transactions.insert(serial_number: card_serial, balance_before: balance_before, amount: transaction_amount, balance_after: balance_after, transaction_time: time, terminal_number: terminal_number, terminal_type: terminal_type, created_at: Time.now, updated_at: Time.now)
response = {message: "TT01000080", status: "SUCCESS" }
return response
else
response = {message: "", status: "FAILED" }
return response
end
After a few packets, the db creates an error like this;
ERROR:PG::ConnectionBad: FATAL: remaining connection slots are reserved for non-replication superuser connections
Even adding the line conn.disconnect does not help the issue.
The idea to connect to DB every time you want to create a record is not the best approach. Think about changing it to some Connection Pool.
But if you still want to connect every time, try to use the block form of connect, which will assure connection is closed after block finishes.
Also there was no close/disconnect in your code, maybe you put it after return call (which means it was not executed)
Try something like this:
response = nil
Sequel.connect('postgres://xxxxx:xxxxxxxxxx#127.0.0.1:xxxxx/xxxxxxxxx',:max_connections => 100) do |conn| # requires pg
transactions = conn.from(:transactions)
if transactions.insert(serial_number: card_serial, balance_before: balance_before, amount: transaction_amount, balance_after: balance_after, transaction_time: time, terminal_number: terminal_number, terminal_type: terminal_type, created_at: Time.now, updated_at: Time.now)
response = {message: "TT01000080", status: "SUCCESS" }
else
response = {message: "", status: "FAILED" }
end
end
return response

Ruby 1.8 hangs making http request

I have the next configuration:
Net::HTTP.ssl_context_accessor 'ssl_version'
#http = Net::HTTP.new(#url.host, 443)
#http.ssl_version = :SSLv2
#http.use_ssl = true
#http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#http.set_debug_output $stderr
#http.open_timeout = 10
#http.read_timeout = 10
And then I use the #http object to make a request_get this way:
path = "/login.cgi?username=#{#url.user}&password=#{#url.password}"
debug("Making request #{#http.address}")
response = #http.request_get(path)
debug("#{response.body}")
#cookie = response.get_fields('set-cookie').split('; ')[0]
Puppet.debug('Cookie got!')
The server is supposed to return me a cookie, but the only output I get from the debug is
Debug: Making request server.com
opening connection to server.com...
opened
And it hangs there forever (not even raising timeout).
I'm very new to ruby, and this code has been retrieved from other stackoverflow questions, and was suppose to work.
I've been searching for google, but haven't found anything similar, any idea?
Changing the SSL version to SSLv3 and the request_get method by post solved the problem.

Getting assignees for a set of tasks

I'm developing a tool to assign a bunch of tasks to a guy according to some criteria.
I fetch tasks for a given tag.
I only assign a task to a guy if the task has no assignee.
My problem comes with the last statement. Fetching a list of tasks do not provide enough information. Going through the documentation, I remember I can format the response with the fields I need using opt_fields but I don't succeed to implement it.
I have this piece of code:
# set up HTTPS connection
uri = URI.parse("https://app.asana.com/api/1.0/tags/8232053093879/tasks?opt_fields=name,assignee")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
# set up the request
header = { "Content-Type" => "application/json" }
request = Net::HTTP::Get.new(uri.path, header)
request.basic_auth(AppConfig[:api_key], '')
# issue the request
response = http.start { |h| h.request(request) }
# output
body = JSON.parse(response.body)
And it keeps responding with:
{"id"=>8232053093904, "name"=>"Implement open VPN"}
{"id"=>8232053093899, "name"=>"Implement a #emi tool for random task affectation."}
{"id"=>8232053093893, "name"=>"List possibilities for internal server hosting ?"}
{"id"=>8232053093890, "name"=>"Create a server FAQ (how to access, how to restart an app, how to set up a new server)"}
{"id"=>8232053093883, "name"=>"Help alban debug munin configuration (server monitoring tool)"}
{"id"=>8232053093876, "name"=>"Think how to improve nanoc deployment"}
While, using curl:
curl -u 8NYknPS.aMxj55LsWwwujpZgNqQ078xf: "https://app.asana.com/api/1.0/tags/8232053093879/tasks?opt_fields=name,assignee"
I get:
{"data":[
{"id":8232053093904,"name":"Implement open VPN","assignee":null},
{"id":8232053093899,"name":"Implement a #emi tool for random task affectation.","assignee":null},
{"id":8232053093893,"name":"List possibilities for internal server hosting ?","assignee":{"id":1069528343983}},
{"id":8232053093890,"name":"Create a server FAQ (how to access, how to restart an app, how to set up a new server)","assignee":null},
{"id":8232053093883,"name":"Help alban debug munin configuration (server monitoring tool)","assignee":{"id":1069528343983}},
{"id":8232053093876,"name":"Think how to improve nanoc deployment","assignee":{"id":753180655981}}
]}
What am I missing?
You may need to give the nested fields, like ?opt_fields=name,assignee,assignee.id - it's a bit clunky, unfortunately. But if you just want the whole assignee, you can use ?opt_expand=assignee.
Hope that helps!

Using Ruby + OAuth to access Yelp API

I just getting started with OAuth, and I tried to make a small client to connect to some webservices... I tried twitter and it worked like a charm, however, I also tried to access Yelp V2 API (following their Python example) but I always get back as an answers:
HTTP 400 Bad Request
Missing parameter: oauth_consumer_key
Here's my code:
require 'rubygems'
require 'oauth'
CONSUMER_KEY = "MY_CONSUMER_KEY"
SECRET = "MY_CONSUMER_SECRET"
TOKEN = "MY_TOKEN"
TOKEN_SECRET = "MY_TOKEN_SECRET"
consumer = OAuth::Consumer.new( CONSUMER_KEY,SECRET, {:site => "http://api.yelp.com", :signature_method => "HMAC-SHA1", :scheme => :header})
access_token = OAuth::AccessToken.new( consumer, TOKEN,TOKEN_SECRET)
p access_token.get("/v2/search?location=new+york").body
Regardless to say, that code works with twitter API without any problem (I actually followed twitter's example code)
Cheers and thanks in advance,
Ze
Use :query_string instead of :header and everything will work (at least for me).
Same code, using Signet:
require 'signet/oauth_1/client'
client = Signet::OAuth1::Client.new(
:consumer_key => 'MY_CONSUMER_KEY',
:consumer_secret => 'MY_CONSUMER_SECRET',
:access_token_key => 'MY_TOKEN_KEY',
:access_token_secret => 'MY_TOKEN_SECRET'
)
response = client.fetch_protected_resource(
:uri => 'http://api.yelp.com/v2/search?location=new+york'
)
# The Rack response format is used here
status, headers, body = response
p body
As per the Yelp documentation, the OAuth parameters do not have to be passed in the query string. The fact that the accepted answer resolved the issue indicates to me that there's probably a bug in the oauth gem causing this.

Resources