Following a Typhoeus post in Rails/Sinatra - ruby-on-rails

I have a scenario where I'm doing a post in Sinatra via Typhoeus in app.rb. It looks like this:
post "/send-data" do
...
request = Typhoeus::Request.new("http://localhost:4000/renders",
:method => :post,
:headers => { :Accept => "text/html" },
:followlocation => true,
:timeout => 100, # milliseconds
:params => params )
# Run the request via Hydra.
hydra = Typhoeus::Hydra.new
hydra.queue(request)
hydra.run
...
end
When I post to 'send-data' Typhoeus successfully does it's post and pushes the user to the view of the created record (http://localhost:4000/renders/34634646464), which is a rails app.
The problem is that the user is never redirected away from /send-data, so if you refresh the page it tries to do the post again. I guess this makes sense, but I really need the user to be redirected to the final (url) location of the record. In other words, the new record can be seen, but this method of redirecting does not actually move the user off of the sinatra app.
What would be the best way to handle this? The only one I can think of off the top of my head is to not use 'followlocation', but rather have the /send-data controller action do the redirect after getting the response location fron Typhoeus.

I tried my suggestion and it works... and does not look too bad.
request = Typhoeus::Request.new("http://localhost:4000/renders.json",
:method => :post,
:headers => { :Accept => "json" },
:timeout => 100, # milliseconds
:params => params )
hydra = Typhoeus::Hydra.new
hydra.queue(request)
hydra.run
response = request.response
redirect response.headers_hash['Location']
I did have to make a change on my rails server. The rails create action responds with json and 'Location' is it's return value. 'Location'is the location of where the newly created record resides. Then I just do a Sinatra redirect which will redirect to the new record on the rails app.

Related

Rails use of httparty to parse the JSON to external URL

In a Rails application, a user has to be redirected to an external site for external processing. The controller generates a valid JSON string and a set of headers:
#result = HTTParty.post(
"https://some-test.supertester.com/checkout",
:verify => false,
:body => JSON.parse(#payment).to_json,
headers: {
'Content-Type' => 'application/json',
'X-TimeStamp' => "#{Time.now.to_i}",
'X-API-ID:' => "#{#api_id}",
'X-API-Signature:' => "#{#api_signature}"
},
timeout: 20
)
This action is launched by the user via:
<%= link_to t('proceed'), data_url_cart_path(id: #existing_cart.id), class: 'button' %>
whose controller action generates the above JSON string and call.
However, Rails tries to respond to this action with a view with the same action's name (even generating a blank with format.json { head :no_content }), when the goal is to redirect the user to the aforementioned URL with the defined headers and payload.
How can this be achieved?
HTTParty is making a network request with a json payload. In this situation #response will be the response from the network request. If you call puts #response.parsed_response.inspect you will see the json returned with said response in the terminal window running your Rails server.
I think you may not need to redirect the user to an external site at all, but instead check the response to see if the action you were trying to make was successful and handle it in your own application.

Accessing Pingdom API with HTTParty from Rails

Hi there i have a problem while accessing Pingdom API from my rails app. Here is the code:
auth = {:username => pingdom_username, :password => pingdom_password, :key => application_key }
response =HTTParty.get("https://api.pingdom.com/api/2.0/checks", :basic_auth => auth)
I have tried in many ways (putting the app key as a separate header, having different names :key, :app_key, :api_key) but i always receive error as a mistake with the application key:
so,
puts response.body
returns:
{"error":{"statuscode":403,"statusdesc":"Forbidden","errormessage":"Missing application key. Please see the documentation."}}
Any Ideas what am I doing Wrong? Thank you in advance
I found my misstake :) THe key should be provided as an HTTP header
One way can be:
response = HTTParty.get("https://api.pingdom.com/api/2.0/checks", :basic_auth => auth, :headers => {"App-Key" => application_key})
the other way is creating a class where you set the parameters and than you call get through this class.
class Pingdom
include HTTParty
headers "App-Key" => "xxxxxxxxxxxxxxxxxxxxxxxxxxxm6ogjzpd7v"
end
response = Pingdom.get("https://api.pingdom.com/api/2.0/checks", :basic_auth => auth)

Post destination receive put data 2 times in parameters

I'm developping a post to a callback url in Ruby on Rails and use the Httparty library for this, I receive the post perfectly on the url but it seems that rails convert the data that is pushed to the url 2 times to parameters. Here is the code that I use to do the call :
#result = HTTParty.post("http://localhost:3000/mailchimp/callback/",
:body => {
:data => {
:title => 'This is the screen name'}
}.to_json,
:headers => { 'Content-Type' => 'application/json' } )
In the logs of the receiving application I got this :
Parameters: {"mailchimp"=>{"controller"=>"mailchimp", "action"=>"callback", "data"=>{"title"=>"This is the screen name"}}, "data"=>{"title"=>"This is the screen name"}}
You see directly that I have 2 times the data parameters, once in the controller hash and once in the normal parameters hash. How does this come?
This is caused by the ParamsWrapper module https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/params_wrapper.rb
This is enabled by default in your rails app by the initializer config/wrap_parameters.rb

How to send a http post request to a rails app to get json response

For GET request its:-
response = Typhoeus::Request.get("http://localhost:3000/users/1.json?oauth_token=12")
This returns Json response perfectly.
for Post request:-
response = Typhoeus::Request.post("http://localhost:3000/users/1.json?oauth_token=12",:params => {'[user][city]' => params[:location]})
is not working...
This is returning routing error.
Update:--
FOr login this api post call is working..
response = Typhoeus::Request.post(API_SERVER_ADDRESS + "user_sessions.json" + API_OAUTH_TOKEN, :params => {'[user_session][email]' => params[:email], '[user_session][password]' =>params[:password]})
In routes its
resources :users
and also web http request is working perfectly fine..
UPDATE
For example http request from rails log is:--
Parameters: {"commit"=>"Update", "authenticity_token"=>"8nvzCd0GF9IxjMcTfHOMJTPnycVPNIENMoMff8w4qAI=", "utf8"=>"✓", "id"=>"1", "user"=>{ "city"=>"abc"}}
Now i want to sent same kind of request..
The :params parameter should be a hash of your parms, meaning key-value pairs, so maybe something like this:
response = Typhoeus::Request.post("http://localhost:3000/users/1.json?oauth_token=12",:params => {:user => 'u', :city => 'c', :location => 'l'})
...or somesuch - whatever the parms are, whatever the values are. Your original doesn't translate into a meaningful hash for what you are wanting to do, I think.
Also, check your routing to make sure that what you are trying to do is properly routed.
Here is the solution
From this
response = Typhoeus::Request.put(API_SERVER_ADDRESS + "users/" +user_id + ".json" ,:params => {:oauth_token=>'12', :user=>{:city => params[:location]}})
Make sure you have declared a separate POST route in your routes.rb file. Even if the URLs are the same, different HTTP methods require different routes.
Using resources :users gives you the following by default:
GET /users/new # new
POST /users # create
GET /users/:id # show
GET /users/:id/edit # edit
PUT /users/:id # update
DELETE /users/:id # destroy

parsing # in rails uris

i am getting the following url information and need to parse it within rails. i already checked request and params but it is not there.
the "#" character seems to f*ck up things.
here's the url:
http://foo.bar.me/whoo#access_token=131268096888809%7C2.5BRBl_qt4xJ08n88ycbpZg__.3600.1276880400-100001151606930%7C0kJ1K-qoGBbDoGbLx6s4z5UEaxM.
thanks for any pointers.
You won't be able to access the part after the '#' character as the browser doesn't send it to the server. You can use it on the client side with javascript though.
It seems that you're trying to use the javascript based authentication which is not what you really want.
I didn't have any problems using this oauth2 library. Then you only need to check for params[:code] within your callback action.
UPDATE:
This is a simplified version of the code I used in my experiments with the new facebook graph API:
# Accessible as facebook_url:
# routes.rb: map.facebook '/facebook', :controller => 'facebook', :action => 'index'
def index
oauth2 = OAuth2::Client.new(FB_API_KEY, FB_API_SECRET, :site => 'https://graph.facebook.com')
if current_user.facebook_token
# The user is already authenticated
fb = OAuth2::AccessToken.new(oauth2, current_user.facebook_sid)
result = JSON.parse(fb.get('/me'))
elsif params[:code]
# Here we get the access token from facebook
fb = oauth2.web_server.get_access_token(params[:code], :redirect_uri => facebook_url)
result = JSON.parse(fb.get('/me'))
current_user.facebook_id = result["id"]
current_user.facebook_token = fb.token.to_s
current_user.save
else
# The user is visiting this page for the first time. We redirect him to facebook
redirect_to oauth2.web_server.authorize_url(:redirect_uri => facebook_url, :scope => 'read_stream,publish_stream,offline_access')
end
end
You don't really need anything else for it to work.

Resources