I have a Rails API 4.2.10 and a NodeJS API.
Some of the Rails Request are deprecated and needs to be redirected to the NodeJS API.
I would like to not do the redirection by my WebServer (NgInx) but somewhere in Rails.
I would like to redirect the entire request => Url, Headers, body....
And return the NodeJS API body & status code.
Being a noob in ruby I tried some like making the requests myself but the Rails API still uses the create methods & so the related objects for example.
Here is my controller code :
class Api::V2::RedirectController < ActionController::API
def apiV3
redirect_to 'http://api-v3-node/api/v3' end
end
When I try with Postman, I get logs but "Could not get any response"
Here are the corresponding outputs :
[2018-09-11T13:08:12.633224 #61] INFO -- : Started POST "/api/v2/notes?token=[FILTERED]" for 172.19.0.1 at 2018-09-11 13:08:12 +0000
[2018-09-11T13:08:12.656050 #61] INFO -- : {:_method=>"POST", :_path=>"/api/v2/notes", :_format=>:json, :_controller=>"Api::V2::RedirectController", :_action=>"apiV3", :_status=>302, :_duration=>1.05, :_view=>0.0, :_location=>"http://api-v3-node/api/v3", :short_message=>"[302] POST /api/v2/notes (Api::V2::RedirectController#apiV3)"}
Related
I have a data scraper in ruby that retrieves article data.
Another dev on my team needs my scraper to spin up a webServer he can make a request to so that he may import the data on a Node Application he's built.
Being a junior, I do not understand the following :
a) Is there a proper convention in Rails that tells me where to place my scraper.rb file
b) Once that file is properly placed, how would i get the server to accept connections with the scrapedData
c)What (functionally) is the relationship between the ports, sockets, and routing
I understand this may be a "rookieQuestion" but I honestly dont know.
Can someone please BREAK THIS DOWN.
I have already:
i) Setup a server.rb file and have it linking to localhost:2000 but Im not sure how to create a proper route or connection that allows someone to use Postman for a valid route and connect to my data.
require 'socket'
require 'mechanize'
require 'awesome_print'
port = ENV.fetch("PORT",2000).to_i
server = TCPServer.new(port)
puts "Listening on port #{port}..."
puts "Current Time : #{Time.now}"
loop do
client = server.accept
client.puts "= Running Web Server ="
general_sites = [
"https://www.lovebscott.com/",
"https://bleacherreport.com/",
"https://balleralert.com/",
"https://peopleofcolorintech.com/",
"https://afrotech.com/",
"https://bossip.com/",
"https://www.itsonsitetv.com/",
"https://theshaderoom.com/",
"https://shadowandact.com/",
"https://hollywoodunlocked.com/",
"https://www.essence.com/",
"http://karencivil.com/",
"https://www.revolt.tv/"
]
holder=[]
agent = Mechanize.new
general_sites.each do |site|
page=agent.get(site);
newRet = page.search('a')
newRet.each do |e|
data = e.attr('href').to_s
if(data.length > 50)
holder.push(data)
end
end
pp holder.length.to_s + " [ posts total] ==> Now Scraping --> " + site
end
client.write(holder)
client.close
end
In Rails you don't spin up a web server manually, as it's done for you using rackup, unicorn, puma or any other compatible application server.
Rails itself is never "talking" to the HTTP clients directly, it is just a specific application that exposes a rack-compatible API (basically have an object that responds to call(hash) and returns [integer, hash, enumerable_of_strings]); the app server will get the data from unix/tcp sockets and call your application.
If you want to expose your scraper to an external consumer (provided it's fast enough), you can create a controller with a method that accepts some data, runs the scraper, and finally renders back the scraping results in some structured way. Then in the router you connect some URL to your controller method.
# config/routes.rb
post 'scrape/me', to: 'my_controller#scrape'
# app/controllers/my_controller.rb
class MyController < ApplicationController
def scrape
site = params[:site]
results = MyScraper.run(site)
render json: results
end
end
and then with a simple POST yourserver/scrape/me?site=www.example.com you will get back your data.
My Ruby on Rails application (ruby 2.6.6; rails 5.2) makes a header only request using HTTPClient, for a Google Drive direct download link. This is to check if the file is really there.
The code is:
response = client.head(<google_drive_direct_download_url>, follow_redirect: true)
This results in 405 status code.
But, at the same time, I can make a normal request to the same URL using
response = client.request('GET', <google_drive_direct_download_url>, follow_redirect: true)
obtaining status code 200.
There is a post saying there is a chance that the URL endpoint doesn't accept header only requests.
But I do can make a header only request using httpie receinving 200:
$ http <google_drive_direct_download_url> -h --follow
Would be a matter of outdated version, or there's an issue with HTTPClient?
I'm trying to authorize in OAuth. I have to open url in browser. That url redirects me to my application sending auth code.
When I open link in browser everything works fine and I receive the code. When I'm sending get (or post) request from code to that link nothing happens. How can I solve this problem.
Logic: I receive response from OAuth in controller and then send it to service.
Method in controller:
def auth_code
MyService.code(params)
render json: params
end
Method in service:
def self.code(params)
##code = params['code']
end
Sending Request from code (Using Httparty [I tried both post and get] ):
code_request = HTTParty.get(code_url)
Sending Request from code:
code_request = Net::HTTP.get(URI(code_url))
P.S. I don't wanna use OAuth gems
I am setting up a url to receive webhooks from a third party API, but I am struggling with verifying my URL as required by the API. The API will post JSON data with a verification token to my url, but when I see the POST come in, Rails says that the controller is processing it as TEXT instead of JSON and it appears rails tries to convert the JSON to a hash before my controller has a chance to interact with it.
Here is what I see when the post request is made:
Processing by WebhooksController#receive as TEXT
Parameters: {"id"=>"5bb2181f-8b7d-4ba2-80a3-072818bb5310", "type"=>"webhook.verify", "created"=>"2014-09-10T22:36:59Z", "data"=>{"token"=>"CWkrAwoPITotLOPQtaiRosOVHPKiOEyh"}, "webhook"=>{"id"=>"5bb2181f-8b7d-4ba2-80a3-072818bb5310", "type"=>"webhook.verify", "created"=>"2014-09-10T22:36:59Z", "data"=>{"token"=>"CWkrAwoPITotLOPQtaiRosOVHPKiOEyh"}}}
Which since the above is not valid JSON, leads to:
JSON::ParserError (757: unexpected token at ''):
app/controllers/webhooks_controller.rb:24:in `receive'
I have tested the controller below with the Postman Chrome extension and when posting JSON similar to what I will receive it does successfully return the token in the response header.
I understand that it might be possible that the third party API is not setting the content type to "application/json", and that could cause this, but how can I ensure Rails processes the data as JSON instead of text?
Controller:
class WebhooksController < ApplicationController
def receive
raw_body = request.body.read
json = JSON.parse raw_body
# Return verification token only once for intitial webhook setup.
token = json['data']['token']
response.headers["token"]= token
render :nothing => true
end
end
Thank you!
Though I still am not fully certain how rails is working in this situation, I have found the solution to my problem. Even though the controller code posted in my question returned the results I was looking for in the Chrome Postman extension, it was giving me a JSON parse error with the API I was trying to integrate webhooks for. I instead tested locally using curl and realized that I got the same error.
Here is the curl to test locally:
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{"id":"evt_REPLACEME"}' localhost:3000/your-webhook-path
And here is my updated controller code that worked:
class WebhooksController < ApplicationController
def receive
token = params[:data][:token]
response.headers["token"]= token
render :text => token
end
end
It was unclear how the token should have been returned for this particular API, and I was unsure if I should return a response in the header or return JSON or Text. Rendering text and setting the token in the header solved this for me.
I set up shopify auth (omniauth-shopify-oauth2 gem) for my rails 3.2.6 app.
It works fine when routed from a web page (to the following controller#action)
class ShopifyController < ApplicationController
...
def login
redirect_to "/auth/shopify?shop=#{current_retailer.primary_host_name}"
end
It redirects me to shop login and, once I am logged in, redirects back to success callback. All good (see SERVER LOG SUCCESS below).
But when I try to do pretty much the same from the rails console:
irb(main):001:0> RestClient.get 'http://localhost:3000/auth/shopify?shop=vinehillposters.myshopify.com'
I get:
RestClient::Unauthorized: 401 Unauthorized: <?xml version="1.0" encoding="UTF-8"?>
<hash>
<errors>[API] Invalid API key or access token (unrecognized login or wrong password)</errors>
</hash>
see SERVER LOG FAIL below
SERVER LOG SUCCESS:
Processing by ShopifyController#login as HTML
... AR stuff snipped ...
Redirected to http://localhost:3000/auth/shopify?shop=vinehillposters.myshopify.com
Completed 302 Found in 93ms (ActiveRecord: 1.6ms)
(shopify) Setup endpoint detected, running now.
(shopify) Request phase initiated.
"https://vinehillposters.myshopify.com/admin/oauth/authorize?response_type=code&client_id=44dd9799fbc268c36ef609f0c2386b8c&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fshopify%2Fcallba
ck&scope=read_orders"
Started GET "/auth/shopify?shop=vinehillposters.myshopify.com" for 127.0.0.1 at 2012-10-30 11:24:21 +0000
(shopify) Setup endpoint detected, running now.
(shopify) Callback phase initiated.
Started GET "/auth/shopify/callback?code=c8c6696ed347e37324d2d62ec203457b&shop=vinehillposters.myshopify.com×tamp=1351596261&signature=e6324b041d6a6ed1e07719a8909d70f7" for 127.0.0.1 at
2012-10-30 11:24:21 +0000
Processing by ShopifyController#auth_callback as HTML
...
SERVER LOG FAILURE:
(shopify) Setup endpoint detected, running now.
(shopify) Request phase initiated.
"https://vinehillposters.myshopify.com/admin/oauth/authorize?response_type=code&client_id=44dd9799fbc268c36ef609f0c2386b8c&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fshopify%2Fcallback&scope=read_orders"
Started GET "/auth/shopify?shop=vinehillposters.myshopify.com" for 127.0.0.1 at 2012-10-30 11:24:54 +0000
You may have noticed that I print out the request_phase url right before it gets redirected to shopify (after (shopify) Request phase initiated.). It is the same in both cases. Except in one case it returns success and in another it is 401.
So, what am I doing wrong?
I think your question is confusing and you are focusing on the wrong part. What you need to do is once your user has logged in grab some information about them from the shopify callback.
def shopify
shopify_domain = params[:shop]
#your_shop_object = your_finds_or_initializes_shop_or_auth_object_with shopify_domain, token
if #your_shop_object.persisted?
redirect_to root_url
else
# something went wrong :/
session['devise.shopify_data'] = request.env['omniauth.auth']
redirect_to auth_index_url
end
end
private
def token
request.env['omniauth.auth']['credentials']['token']
end
Now with this you can use that persisted shop objects data to set up an authorized session
session = ShopifyAPI::Session.new(domain, authentication_token)
if session.valid?
ShopifyAPI::Base.activate_session(session)
# Now you can make api calls for that shop (domain)
else
Rails.logger.error "[Shop] Could not create a valid session for '#{domain}'"
end