Instagram embed code from url (Rails) - ruby-on-rails

In my application, I would like to allow user introduce a url of instagram, and then automatically retrieve the embed code of it.
I found this reference:
https://www.instagram.com/developer/embedding/#oembed
When I try the given example (https://api.instagram.com/oembed?url=http://instagr.am/p/fA9uwTtkSN) in my Chrome browser, I get the json with the code I am looking for.
However, if I try this from the rails console:
Net::HTTP.get_response(URI("https://api.instagram.com/oembed?url=http://instagr.am/p/fA9uwTtkSN"))
I get this:
#<Net::HTTPMovedPermanently 301 MOVED PERMANENTLY readbody=true>
I saw that instagram have a new API, but I don't want to make user authenticate from instagram.
Is there a way to do it?

You can use oembed gem by soulim. nice and clean way to get embed code
In case of instagram it goes like
include following line in your gem file
gem 'oembed'
next
bundle install
create a helper class
class InstaApi
include Oembed::Client
def endpoint_uri
'http://api.instagram.com/oembed'
end
end
Now you can use
instClient = InstaApi.new
info = instClient.fetch('http://instagr.am/p/BUG/')
to Get your embed code
embed_code = info["html"]

Using the docs
def fetch(uri_str, limit = 10)
# You should choose a better exception.
raise ArgumentError, 'too many HTTP redirects' if limit == 0
response = Net::HTTP.get_response(URI(uri_str))
case response
when Net::HTTPSuccess then
response
when Net::HTTPRedirection then
location = response['location']
warn "redirected to #{location}"
fetch(location, limit - 1)
else
response.value
end
end
str = "https://api.instagram.com/oembed?url=http://instagr.am/p/fA9uwTtkSN"
response = fetch(str)
redirected to https://api.instagram.com/publicapi/oembed/?url=http://instagr.am/p/fA9uwTtkSN
redirected to https://www.instagram.com/publicapi/oembed/?url=http://instagr.am/p/fA9uwTtkSN
redirected to https://api.instagram.com/oembed/?url=http://instagr.am/p/fA9uwTtkSN
=> #<Net::HTTPOK 200 OK readbody=true>
response.body
=> # JSON response
So just follow the redirects.

Related

Rails API 422 Unprocessable Entity: No verification key available, heroku

I created a Rails API with a JWT authentication system and deployed it to Heroku. When I request the endpoints locally, all seems to be working fine but when I make requests to the live endpoints (i.e the Heroku deployed app) I get a: 422 Unprocessable Entity server error and the response body looks like this:
{
"message": "No verification key available"
}
The class responsible for encoding and decoding the auth token is defined as follows:
class JsonWebToken
# secret to encode and decode token
HMAC_SECRET = Rails.application.secrets.secret_key_base
def self.encode(payload, exp = 24.hours.from_now)
# set expiry to 24 hours from the creation time.
payload[:exp] = exp.to_i
# sign token with application secret
JWT.encode(payload, HMAC_SECRET)
end
def self.decode(token)
# get payload, first index in decoded Array
body = JWT.decode(token, HMAC_SECRET)[0]
HashWithIndifferentAccess.new body
# rescue from all decode errors
rescue JWT::DecodeError => e
# raise custom error to be handled by custom handler
raise ExceptionHandler::InvalidToken, e.message
end
end
I have an endpoint /signup where I can make a POST request to register a new user and POST /todos which is accessible and available only to registered users. Making a registration request works perfectly fine, but when I try to make the POST request to the /todos endpoint it raises an error.
The association between user and suit is 1:m respectively.
Please if you have any idea on how I can fix this, I'll be very grateful, thanks : ).
I finally figured a way out by altering the Rails.application.secrets.secret_key_base to Rails.application.secret_key_base. For a more detailed review on this please check out this link. Hopefully, this will help someone facing a similar issue.
This was also my problem. After checking out my json_web_token.rb file, I figured out that I had written the following line:
HMAC_SECRET = Rails.application.secrets.secret_key_base
There is an extra secrets reference, which is causing the problem. It should be:
HMAC_SECRET = Rails.application.secret_key_base
But as far as I'm concerned, you managed to figure it out yourself!

How to check for successful response from API in rails by just using status code?

I am consuming an API using a gem in Ruby on Rails. The gem makes the API call for me and returns the status code as an integer (for example 200, 201 e.t.c.) and the data response from the API.
def get_cars
status_code, data = MyGem::Cars.get_cars
if status_code in SUCCESSFUL_RESPONSE_CODES
# Perform data manipulation
else
raise "There was an error processing the request. Status code #{status_code}"
end
end
Now I have manually initialised SUCCESSFUL_RESPONSE_CODES as a list containing integers of successful codes I found here.
Is this list defined somewhere in Ruby/RoR to avoid manually defining it?
I would expect any widely supported gem to use standard HTTP response codes to determine if the HTTP response was a success. For example:
require 'open-uri' # Rails loads this by default.
res = open('http://example.com')
res.status
=> ["200","OK"]
status.include?'OK'
=>true
status.include?'200'
=> true
So long as you trust the gem code making your request to handle standard HTTP response codes, you should be ok. Here's another example using HTTParty gem
require 'HTTParty'
res = HTTParty.get('https://example.com')
res.success?
=> true

RoR JSON.parse catching an error

Writing an app that reaches out to an api (ETSY) and brings back some JSON but sometimes I get a 403 error and if I get an error I want to show an error page but I'm not sure how to check for that error and do something else.
my_hash = JSON.parse(open("https://openapi.etsy.com/v2/listings/#{$productId}?api_key=XXXX&fields=title,url,price,description&includes=MainImage").read)
I've looked around for a while but haven't seen what I'm looking for.
You can use a begin rescue block to redirect the user whenever you hit a 403 error
def index
begin
my_hash = JSON.parse(open("https://openapi.etsy.com/v2/listings/#{$productId}api_key=XXXX&fields=title,url,price,description&includes=MainImage").read)
rescue
redirect_to error_path
end
This is sort of quick and dirty, but I beileve it can get the job done.
This article may also help. http://www.mattjohnston.co/blog/2013/10/18/responding-with-errors-in-rails/
I think you need to check your api response, if the response is 404 then render error page. May be something like this. To getting response from api, you need to use third party like (restclient or httpparty).
def index
response = RestClient get "https://openapi.etsy.com/v2/listings/#{$productId}api_key=XXXX&fields=title,url,price,description&includes=MainImage"
unless response.code == 404
result_hash = JSON.parse(response.body)
// do something
else
// redirect to error page here
end
end
For reference, pls read restclient documentation here.

Get redirect of a URL in Ruby

According to Facebook graph API we can request a user profile picture with this (example):
https://graph.facebook.com/1489686594/picture
But the real image URL of the previous link is:
http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs356.snc4/41721_1489686594_527_q.jpg
If you type the first link on your browser, it will redirect you to the second link.
Is there any way to get the full URL (second link) with Ruby/Rails, by only knowing the first URL?
(This is a repeat of this question, but for Ruby)
This was already answered correctly, but there's a much simpler way:
res = Net::HTTP.get_response(URI('https://graph.facebook.com/1489686594/picture'))
res['location']
You can use Net::Http and read the Location: header from the response
require 'net/http'
require 'uri'
url = URI.parse('http://www.example.com/index.html')
res = Net::HTTP.start(url.host, url.port) {|http|
http.get('/index.html')
}
res['location']
You've got HTTPS URLs there, so you will handle that...
require 'net/http'
require 'net/https' if RUBY_VERSION < '1.9'
require 'uri'
u = URI.parse('https://graph.facebook.com/1489686594/picture')
h = Net::HTTP.new u.host, u.port
h.use_ssl = u.scheme == 'https'
head = h.start do |ua|
ua.head u.path
end
puts head['location']
I know this is an old question, but I'll add this answer for posterity:
Most of the solutions I've seen only follow a single redirect. In my case, I had to follow multiple redirects to get the actual final destination URL. I used Curl (via the Curb gem) like so:
result = Curl::Easy.perform(url) do |curl|
curl.head = true
curl.follow_location = true
end
result.last_effective_url
You can check the response status code and get the final URL recursively using something like get_final_redirect_url method:
require 'net/http'
def get_final_redirect_url(url, limit = 10)
uri = URI.parse(url)
response = ::Net::HTTP.get_response(uri)
if response.class == Net::HTTPOK
return uri
else
redirect_location = response['location']
location_uri = URI.parse(redirect_location)
if location_uri.host.nil?
redirect_location = uri.scheme + '://' + uri.host + redirect_location
end
warn "redirected to #{redirect_location}"
get_final_redirect_url(redirect_location, limit - 1)
end
end
I was facing the same issue. I solved it and built a gem final_redirect_url around it, so that everyone can benefit from it.
You can find the details on uses here.
Yeah, "Location" response header tell you the actual image URL.
However, if you use the picture as the user's profile image on your site, I recommend you to use "https://graph.facebook.com/:user_id/picture" style URL instead of actual image URL.
Otherwise, your users will see lots of "not found" images, or outdated profile images in the future.
You just put "https://graph.facebook.com/:user_id/picture" as the "src" attribute of "img" tag.
They browser gets the updated image of the user.
ps.
I have such troubles on my site with Twitter & Yahoo! OpenID now..
If you want a solution that:
does not use gems
follows all redirects
works also with url-shortening services
require 'net/http'
require 'uri'
def follow_redirections(url)
response = Net::HTTP.get_response(URI(url))
until response['location'].nil?
response = Net::HTTP.get_response(URI(response['location']))
end
response.uri.to_s
end
# EXAMPLE USAGE
follow_redirections("https://graph.facebook.com/1489686594/picture")
# => https://static.xx.fbcdn.net/rsrc.php/v3/yo/r/UlIqmHJn-SK.gif

How to get 302 redirect location in Rails? (have tried HTTParty, Net/Http and RedirectFollower)

Hello
i am trying to get Facebook user's album's cover picture.
as it's said in the API page, it returns "An HTTP 302 with the URL of the album's cover picture" when getting:
http s://graph.facebook.com/[album_id]}/picture?access_token=blahblahblah...
documents here: http://developers.facebook.com/docs/reference/api/album
i've tried HTTParty, Net:HTTP and also the RedirectFollower class
HTTParty returns the picture image itself, and no "location" (URL) information anywhere
NET:HTTP and RedirectFollower are a bit tricky...
if i don't use URI.encode when passing the URL into the get method, it causes "bad uri" error
but if i use URI.encode to pass the encoded URI, it causes EOFError (end of file reached)
what's amazing is that i can see the location URL when using apigee's FB API
here is the redirect method which is recommended on the Net:HTTP documents:
anything should be modified? or is there any easier way to do this?
thank you!!
def self.fetch(uri_str, limit = 10)
response = Net::HTTP.get_response(URI.parse(uri_str))
case response
when Net::HTTPSuccess then response
when Net::HTTPRedirection then fetch(response['location'], limit - 1)
else
response.error!
end
end
If you don't mind using a gem, curb will do this for you. It's all about using the follow_location parameter:
gem 'curb'
require 'curb'
# http://www.stackoverflow.com/ redirects to http://stackoverflow.com/
result = Curl::Easy.http_get("http://www.stackoverflow.com/") do |curl|
curl.follow_location = true
end
puts result.body_str
This is not the only library with this feature, though.
As a note, many times you will get an invalid location in the header and it will have to be interpreted by the user agent to render it into something useful. A header like Location: / will need to be re-written before it can be fetched. Other times you will get a header like Location: uri=... and you'll have to pull out the location from there. It's really best to leave it to your library than re-write that yourself.
here is what i end up with after some trial and error:
uri_str = URI.encode(https://graph.facebook.com/[album_id]}/picture?access_token=blahblahblah...)
result = Curl::Easy.http_get(uri_str) do |curl|
curl.follow_location = false
end
puts result.header_str.split('Location: ')[1].split(' ')[0]
the returned header_str looks like
"HTTP blah blah blah Location: http://xxxxxxx/xxxx.jpg blah blah blah"
so i managed to get the URL by using 2 split()
the final result is a clean URL
also the curl.follow_location should be false so it won't return the body of that page

Resources