how to call method in one application from another application in ruby on rails - ruby

I want to call the method and get the response in my application from another application in Ruby on Rails technology, but here cross site scripting problem is there. so, i can i resolve this issue please help me it would be great.
http://video_tok.com/courses/get_course
def get_course
#course = Course.find(params[:id])
end
now i want to call this above method from this application which is running in edupdu.com domain
http://edupdu.com/call_course_method
def call_course_method
#course = redirect_to "http://video_tak.com/courses/get_course/1"
end
but it would be redirect into video_tak.com application.
i want to call get_course method and get #course object internally without redirect to another site.
Thanks in advance.

Cross-domain AJAX is indeed a problem, but none that could not be solved. In your get_course method you could return the course objects as a JSON response like so:
render json: #course
From there on you could either retrieve the course through JavaScript (AJAX), here you should use JSONP or inside Rails by issuing a HTTP GET request.
AJAX with JSONP
There is JSONP (JSON with padding), which is a communication technique for JavaScript programs to provide a method to request data from a server in a different domain. Look at
the documentation of jQuery.getJSON() and scroll down to the JSONP section.
If the URL includes the string "callback=?" (or similar, as defined by
the server-side API), the request is treated as JSONP instead. See the
discussion of the jsonp data type in $.ajax() for more details.
HTTP GET request
Simply use the Net::HTTP class:
require 'net/http'
require 'json'
url = URI.parse('http://video_tak.com/courses/get_course/1')
req = Net::HTTP::Get.new(url.to_s)
res = Net::HTTP.start(url.host, url.port) do |http|
http.request(req)
end
course_json = JSON.parse(res.body)
If you provide methods for your model to convert JSON into a domain object of yours, you can take it from there.
RPC
You can also use RPC to invoke methods between different Ruby processes, although I recommend this the least I do not want to omit it. There are several remote procedure call (RPC) libraries. The Ruby standard library provides DRb, but there are also implementations based on Ruby on Rails, for instance the rails-xmlrpc gem which allows you to implement RPC based on the XML-RPC protocol or the alternative protocol using JSON with json-rpcj
You will probably find even more libraries when searching for Rails RPC. From whatever library you pick, the concrete solution will differ.

Related

Need help handling Timeout::Error in Savon

I'm building a connection between REST-API and SOAP API in Ruby (without Rails).
For SOAP calls I use Savon gem, which is great.
However, I cannot figure out from the docs, how does Savon handle Timeout::Error?
Does it raise Savon::HTTPError or Savon::SOAPFault?
Please advise.
I was curious myself. After a bit of experimentation and skimming through Savon sources it seems that transport-level errors aren't handled and translated to Savon's own exception types, but thrown "as is", so if you need to handle them, you have to handle exceptions thrown by the underlying HTTP client library.
It's important to note that Savon supports multiple HTTP clients through the httpi abstraction layer. By default it just chooses one from those being available, but if you need to handle it's exceptions, you shouldn't rely on the automatic selection, but explicitly configure which HTTPI adapter should be used (e.g. HTTPI.adapter = :net_http).
The code below can be used to test the timeout scenario with HTTPI adapter of your choice.
Code for experimentation
Server (written in PHP, because there are no up-to-date working solutions for writing a dead-simple SOAP server like this, without a ton of boilerplate code, in Ruby):
<?php
// simple SOAP server - run with 'php -S localhost:12312 name_of_this_file.php'
class SleepySoapServer
{
public function hello()
{
sleep(3600); // take an hour's nap before responding
return 'Hello, world!';
}
}
$options = array('uri' => 'http://localhost:12312/');
$server = new SoapServer(null, $options);
$server->setClass(SleepySoapServer::class);
$server->handle();
Client (using Savon 2):
require 'savon'
HTTPI.adapter = :net_http # request Net::HTTP client from the standard library
uri = 'http://localhost:12312'
client = Savon.client do
endpoint uri
namespace uri
end
response = client.call :Hello
p response.body
If you don’t like to rescue errors, here’s how you can tell Savon not to raise them
Savon.configure do |config|
config.raise_errors = false
end

Retrieving JSON from an external API with backbone

I'm new to backbone.js and I've read other solutions to similar problems but still can't get my example to work. I have a basic rails api that is returning some JSON from the url below and I am trying to access in through a backbone.js front end. Since they are one different servers I think I need to use a 'jsonp' request. I'm currently doing this by overriding the sync function in my backbone collection.
Api url:
http://guarded-wave-4073.herokuapp.com/api/v1/plans.json
sync: function(method, model, options) {
options.timeout = 10000;
options.dataType = 'jsonp';
options.url = 'http://guarded-wave-4073.herokuapp.com/api/v1/plans.json'
return Backbone.sync(method, model, options);
}
To test this I create a new 'plans' collection in my chrome console using "plans = new Plans()" and then "plans.fetch()" to try and get the JSON.
When I call plans.models afterwards I still have an empty array and the object that returns from plans.fetch() doesn't seem to have any json data included.
Any ideas where I'm going wrong?
I have had the same problem before. You should not have to override your sync method.
Taken from Stackoverflow Answer
"The JSONP technique uses a completely different mechanism for issuing HTTP requests to a server and acting on the response. It requires cooperating code in the client page and on the server. The server must have a URL that responds to HTTP "GET" requests with a block of JSON wrapped in a function call. Thus, you can't just do JSONP transactions to any old server; it must be a server that explicitly provides the functionality."
Are you sure your server abides to the above? Test with another compatible jsonp service (Twitter) to see if you receive results?
Have you tried overriding the fetch method as well?
You should add ?callback=? to your api url in order to enable jsonp

How do I create a Ruby SOAP client without using a WSDL?

I need to write a soap client that is capable of sending and receiving soap messages.
This soap service does not have an associated WSDL file and soap4r and savon both seem to require one.
I have an example of what I need to do in Java, see the link below.
http://community.cecid.hku.hk/index.php/product/article/writing_hermes_2_ws_client_under_java/#ebms-2_0-sender-ws
I could use java for this, at this point it seems like it would be easier. However I personally prefer coding in ruby and our company has more ruby resources than java.
Can anyone confirm thats its possible to do something similar to java example in ruby without writing my own specialised soap library?. I need to be able to send a payload, which I believe is usually in the form of a soap attachment.
I am particularly interested in seeing soap4r examples that don't use a WSDL as I have had trouble finding any with google.
Any help much appreciated.
as of Savon v2, the syntax is slightly different
client = Savon.client do
endpoint "http://example.com"
namespace "http://v1.example.com"
end
http://savonrb.com/version2/client.html
Savon does not require a WSDL document. Please take a look at the new documentation. If you know the SOAP endpoint and target namespace, you can execute a SOAP request like this:
client = Savon::Client.new
wsdl.endpoint = "http://example.com"
wsdl.namespace = "http://soap.example.com"
end
client.request :any_soap_action do
soap.body = { :do => "something" }
end
client = Savon::Client.new
wsdl.endpoint = "http://example.com"
wsdl.namspace = "http://soap.example.com"
end
This does not work, it misses a the block name and the "e" in namespace:
client = Savon::Client.new do | wsdl |
wsdl.endpoint = "http://example.com"
wsdl.namespace = "http://soap.example.com"
end

django ajax proxy view

A django web app needs to make ajax calls to an external url. In development I serve directly from django so I have a cross domain problem. What is the django way to write a proxy for the ajax call?
Here's a dead simple proxy implementation for Django.
from django.http import HttpResponse
import mimetypes
import urllib2
def proxy_to(request, path, target_url):
url = '%s%s' % (target_url, path)
if request.META.has_key('QUERY_STRING'):
url += '?' + request.META['QUERY_STRING']
try:
proxied_request = urllib2.urlopen(url)
status_code = proxied_request.code
mimetype = proxied_request.headers.typeheader or mimetypes.guess_type(url)
content = proxied_request.read()
except urllib2.HTTPError as e:
return HttpResponse(e.msg, status=e.code, mimetype='text/plain')
else:
return HttpResponse(content, status=status_code, mimetype=mimetype)
This proxies requests from PROXY_PATH+path to TARGET_URL+path.
The proxy is enabled and configured by adding a URL pattern like this to urls.py:
url(r'^PROXY_PATH/(?P<path>.*)$', proxy_to, {'target_url': 'TARGET_URL'}),
For example:
url(r'^images/(?P<path>.*)$', proxy_to, {'target_url': 'http://imageserver.com/'}),
will make a request to http://localhost:8000/images/logo.png fetch and return the file at http://imageserver.com/logo.png.
Query strings are forwarded, while HTTP headers such as cookies and POST data are not (it's quite easy to add that if you need it).
Note: This is mainly intended for development use. The proper way to handle proxying in production is with the HTTP server (e.g. Apache or Nginx).
I ran across this question while trying to answer it myself, and found this Django app:
http://httpproxy.yvandermeer.net/
...which is a little heavyweight for what I needed (recording and playback, requires a syncdb to add in model stuff). But you can see the code it uses in its generic proxying view, which is based on httplib2:
http://bitbucket.org/yvandermeer/django-http-proxy/src/1776d5732113/httpproxy/views.py
Am I right that you are asking about how to write view in Django that could accept incoming AJAX request, issue request to the remote server and then return received response to browser?
If so, then it's not really Django-specific question - remote calls could be done with Python's urllib2 or httplib, and then you just have to put:
return HttpResponse(received_response)
-- in your Django proxy-view. I assume no reponse processing here, because if it's just a proxy for AJAX call then JavaScript expects unprocessed data.

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