Using WSDL With Ruby - ruby

I'm getting this error:
WSDL::XMLSchema::Parser::UnknownElementError
unknown element: {}HTML
at 'new'
when I consume webservices using Ruby. Here is the code snippet:
require 'soap/wsdlDriver'
wsdl = url
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
driver.options["protocol.http.basic_auth"] << [url, user_name, password]
the url points to a well-formed xml.
Any solutions?

Can you share the wsdl file? Maybe that would help us answering it better.
In any case, I'd suggest generating the Driver classes first using wsdl2ruby. And then loding them in your Ruby file (through require). Examples (from the man pages):
# For server side:
$ wsdl2ruby.rb --wsdl myapp.wsdl --type server
# For client side:
$ wsdl2ruby.rb --wsdl myapp.wsdl --type client

If you load the URL in a web browser, does it get redirected to a different location?
In my experience, one reason the error "unknown element: {}HTML" comes up is the WSDL parser is trying to parse the HTML portion of the HTTP redirect and failing to do so. Therefore, you should deal with the redirect yourself (either in code or manually) and give the WSDL driver the final URL.

Related

Using Twilio/XML without Rails

I am attempting to write a Twilio script to do voice broadcasting without rails - I would like to be able to run the script straight from my terminal.
I have a very simple script, straight from the twilio-rb gem docs:
# This should be in an initializer or similar
Twilio::Config.setup \
:account_sid => account,
:auth_token => token
Twilio::Call.create :to => '+1234567890', :from => '+0987654321',
:url => xml_file
xml_file is a xml file on my local machine, but it throws this error:
Error #21205: Url is not a valid url
How can I write the above script to operate off of a local xml file? The end goal is strictly to make a phone call, play an audio message, gather a button press and do an action based on the number received. The Twiml XML file should do that for me, if I can get it to work.
EDIT:
When using the dropbox share link, I get this error within the Twilio interface:
'Twilio is unable to process the Content-Type of the provided URL. Please see the Twilio Markup XML Documentation for more information on valid Content-Types.
You must return a Content-Type for all requests. Requests without a Content-Type will appear in the Debugger as a 502 Bad Gateway error.
Having a phone number, outgoing call request or action attribute refer to a non XML or audio resource.
Having a Play verb attempt to play non-audio content, such as XML or text.
Verify that that your web server is returning a Content-Type and it is the expected value
Make sure the URL noted refers to a valid resource'
To make sure, I copied an example I know will work into my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say voice="man">Hey man! Listen to this!</Say>
<Play>http://foo.com/cowbell.mp3</Play>
<Say voice="man">What did you think of that?!</Say>
<Record action="http://foo.com/handleRecording.php" method="GET" maxLength="20" finishOnKey="*"/>
<Gather action="/process_gather.php" method="GET">
<Say>Now hit some buttons!</Say>
</Gather>
<Say voice="man">Awesome! Thanks!</Say>
<Hangup/>
</Response>
Two ideas to try:
(1) If the file is read locally and sent to the Twilio server, try:
:url => 'file:///path/file.xml'
where
host in //host/ is omitted, yielding three slashes in a row.
path is the full filesystem path to your XML file.
file.xml is the name of your XML file.
(2) If the file must be publicly readable by the Twilio server, try placing it in the cloud somewhere (such as Dropbox) and using the public URL to it there.

Ruby openuri test if uri is valid

I'm trying to test if a uri is valid (e.g. actually has content, not testing if it is well formed here) using ruby code, and I can open a uri using open(uri). But in my case, the uri is a link to a file to be downloaded and I don't want to have to download the whole file just to verify that there is content there.
Is there another solution for this?
Try this
require 'net/http'
u = URI.parse('http://www.example.com/')
status = Net::HTTP.start(u.host, u.port).head(u.request_uri).code
# status is HTTP status code
You'll need to use rescue to catch exception in case domain resolution fails.

Cucumber Error: Socket Error for Test Environment Host in REST API

I posted this to the Cucumber group with no replies, which makes me wonder if this is actually a cucumber issue or not. I'm pretty new to cucumber, and there are a number of things I really don't quite understand about how the cucumber environment is set up and executed within the test environment.
I have a REST API rails app I'm testing with cucumber, using the RestClient gem to generate a post to controller create action. When I run the feature with a hard-coded URL pointing to a running localhost server (my local dev server environment; replacing tickets_url with "http://
localhost/tickets" in the snippet below), my cucumber steps execute as expected. However, when the resource URL resolves to the cucumber host I'm declaring, I get a socket error exception.
getaddrinfo: nodename nor servname provided, or not known (SocketError)
From the steps file:
When /^POS Adapter sends JSON data to the Tickets resource$/ do
ticket = {
:ticket => {
...
}
}
host! "test.host"
puts tickets_url
RestClient.post tickets_url, ticket.to_json, :content_type => :json, :accepts => :json
end
(the "puts" statement prints "http://test.host/tickets")
Using the following gems:
cucumber-0.6.1
webrat-0.6.0
rest-client-1.2.0
I should also say I have a similar set up in another rails app, using test.host as my host, and it seems to work fine. I'd appreciate any insight on what I might be missing in my configuration or what this could be related to.
What port number are you using? A similar problem was patched back in Oct. 2009. The issue was related to a large port number being used. Here's the light houseticket: https://rspec.lighthouseapp.com/projects/16211/tickets/502-wire-protocol-features-fail-with-os-x-snowy

Issues POSTing XML to OAuth and Signature Invalid with Ruby OAuth Gem

[Cross-posted from the OAuth Ruby Google Group. If you couldn't help me there, don't worry bout it]
I'm working on integrating a project with TripIt's OAuth API
and am running into a weird issue.
I authenticate fine, I store and retrieve the token/secret for a given
user with no problem, I can even make GET requests to a number of
services using the gem. But when I try using the one service I need
POST for, I'm getting a 401 "invalid signature" response.
Perhaps I'm not understanding how to pass in data to the AccessToken's
post method, so here's a sample of my code:
xml = <<-XML
<Request>
<Trip>
<start_date>2008-12-09</start_date>
<end_date>2008-12-27</end_date>
<primary_location>New York, NY</primary_location>
</Trip>
</Request>
XML`
response = access_token.post('/v1/create', {:xml => xml},
{'Content-Type' => 'application/x-www-form-urlencoded'})
I've tried this with and without escaping the xml string before hand.
The guys at TripIt seemed to think that perhaps the xml param wasn't
getting included in the signature_base_string, but when I output that
(from lib/signature/base.rb) I see:
POST&https%3A%2F%2Fapi.tripit.com%2Fv1%2Fcreate&oauth_consumer_key
%3D%26oauth_nonce
%3Djs73Y9caeuffpmPVc6lqxhlFN3Qpj7OhLcfBTYv8Ww%26oauth_signature_method
%3DHMAC-SHA1%26oauth_timestamp%3D1252011612%26oauth_token
%3D%26oauth_version%3D1.0%26xml%3D%25253CRequest%25253E
%25250A%252520%252520%25253CTrip%25253E%25250A
%252520%252520%252520%252520%25253Cstart_date%25253E2008-12-09%25253C
%252Fstart_date%25253E%25250A
%252520%252520%252520%252520%25253Cend_date%25253E2008-12-27%25253C
%252Fend_date%25253E%25250A
%252520%252520%252520%252520%25253Cprimary_location%25253ENew
%252520York%252C%252520NY%25253C%252Fprimary_location%25253E%25250A
%252520%252520%25253C%252FTrip%25253E%25250A%25253C%252FRequest%25253E
%25250A
This seems to be correct to me.
I output signature (from the same file) and the output doesn't match
the oauth_signature param of the Auth header in lib/client/
net_http.rb. It's been URL-encoded in the auth header. Is this
correct?
Anyone know if the gem is broken/if there's a fix somewhere? I'm finding it hard to trace through some of the code.
Your oauth_token is empty. Not familiar with the protocol, is that ok?
Once you include the correct token, please also remember to use token_secret in the signing.

POSTing an HTML form to remote.cgi - written in Ruby?

I am working on a website hosted on microsoft's office live service. It has a contact form enabling visitors to get in touch with the owner. I want to write a Ruby script that sits on a seperate sever and which the form will POST to. It will parse the form data and email the details to a preset address. The script should then redirect the browser to a confirmation page.
I have an ubuntu hardy machine running nginx and postfix. Ruby is installed and we shall see about using Thin and it's Rack functionality to handle the script. Now it's come to writing the script and i've drawn a blank.
It's been a long time and if i remember rightly the process is something like;
read HTTP header
parse parameters
send email
send redirect header
Broadly speaking, the question has been answered. Figuring out how to use the answer was more complicated than expected and I thought worth sharing.
First Steps:
I learnt rather abruptly that nginx doesn't directly support cgi scripts. You have to use some other process to run the script and get nginx to proxy requests over. If I was doing this in php (which in hind sight i think would have been a more natural choice) i could use something like php-fcgi and expect life would be pretty straight forward.
Ruby and fcgi felt pretty daunting. But if we are abandoning the ideal of loading these things at runtime then Rack is probably the most straight forward solution and Thin includes all we need. Learning how to make basic little apps with them has been profoundly beneficial to a relative Rails newcomer like me. The foundations of a Rails app can seem hidden for a long time and Rack has helped me lift the curtain that little bit further.
Nonetheless, following Yehuda's advice and looking up sinatra has been another surprise. I now have a basic sinatra app running in a Thin instance. It communicates with nginx over a unix socket in what i gather is the standard way. Sinatra enables a really elegant way to handle different requests and routes into the app. All you need is a get '/' {} to start handling requests to the virtual host. To add more (in a clean fashion) we just include a routes/script.rb into the main file.
# cgi-bin.rb
# main file loaded as a sinatra app
require 'sinatra'
# load cgi routes
require 'routes/default'
require 'routes/contact'
# 404 behaviour
not_found do
"Sorry, this CGI host does not recognize that request."
end
These route files will call on functionality stored in a separate library of classes:
# routes/contact.rb
# contact controller
require 'lib/contact/contactTarget'
require 'lib/contact/contactPost'
post '/contact/:target/?' do |target|
# the target for the message is taken from the URL
msg = ContactPost.new(request, target)
redirect msg.action, 302
end
The sheer horror of figuring out such a simple thing will stay with me for a while. I was expecting to calmly let nginx know that .rb files were to be executed and to just get on with it. Now that this little sinatra app is up and running, I'll be able to dive straight in if I want to add extra functionality in the future.
Implementation:
The ContactPost class handles the messaging aspect. All it needs to know are the parameters in the request and the target for the email. ContactPost::action kicks everything off and returns an address for the controller to redirect to.
There is a separate ContactTarget class that does some authentication to make sure the specified target accepts messages from the URL given in request.referrer. This is handled in ContactTarget::accept? as we can guess from the ContactPost::action method;
# lib/contact/contactPost.rb
class ContactPost
# ...
def action
return failed unless #target.accept? #request.referer
if send?
successful
else
failed
end
end
# ...
end
ContactPost::successful and ContactPost::failed each return a redirect address by combining paths supplied with the HTML form with the request.referer URI. All the behaviour is thus specified in the HTML form. Future websites that use this script just need to be listed in the user's own ~/cgi/contact.conf and they'll be away. This is because ContactTarget looks in /home/:target/cgi/contact.conf for the details. Maybe oneday this will be inappropriate, but for now it's just fine for my purposes.
The send method is simple enough, it creates an instance of a simple Email class and ships it out. The Email class is pretty much based on the standard usage example given in the Ruby net/smtp documentation;
# lib/email/email.rb
require 'net/smtp'
class Email
def initialize(from_alias, to, reply, subject, body)
#from_alias = from_alias
#from = "cgi_user#host.domain.com"
#to = to
#reply = reply
#subject = subject
#body = body
end
def send
Net::SMTP.start('localhost', 25) do |smtp|
smtp.send_message to_s, #from, #to
end
end
def to_s
<<END_OF_MESSAGE
From: #{#from_alias}
To: #{#to}
Reply-To: #{#from_alias}
Subject: #{#subject}
Date: #{DateTime::now().to_s}
#{#body}
END_OF_MESSAGE
end
end
All I need to do is rack up the application, let nginx know which socket to talk to and we're away.
Thank you everyone for your helpful pointers in the right direction! Long live sinatra!
It's all in the Net module, here's an example:
#net = Net::HTTP.new 'http://www.foo.com', 80
#params = {:name => 'doris', :email => 'doris#foo.com'}
# Create HTTP request
req = Net::HTTP::Post.new( 'script.cgi', {} )
req.set_form_data #params
# Send request
response = #net.start do |http|
http.read_timeout = 5600
http.request req
end
Probably the best way to do this would be to use an existing Ruby library like Sinatra:
require "rubygems"
require "sinatra"
get "/myurl" do
# params hash available here
# send email
end
You'll probably want to use MailFactory to send the actual email, but you definitely don't need to be mucking about with headers or parsing parameters.
CGI class of Ruby can be used for writing CGI scripts. Please check: http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/index.html
By the way, there is no need to read the HTTP header. Parsing parametres will be easy using CGI class. Then, send the e-mail and redirect.

Resources