RoR JSON.parse catching an error - ruby-on-rails

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.

Related

How to handle 300 Multiple Choices Exception for Rails

I have an exception error for testing an API that I am not quite sure how to handle. Here is the snippet of code at the bottom.
begin
open(release_url(uuid)) do |feed|
response = JSON.parse(feed.read)
return get_target_releases_json(response['targets']) if feed.status.first != 200
return if pss.etag == feed.meta['etag']
response['releases']
end
rescue Exception => e
puts "#---Exception---#"
puts e
end
What is pertinent to understand the problem is the open(url) method.
When I reach this point using byebug I get an exception that is a 300 - Multiple Choices error. I read a little bit about it but I don't understand what I need to do to correct this. The api (which is internal to my company btw) is supposed to return a JSON structure when it hits 300. When I place this api url in my browser, I am able to see the JSON payload but when I try to use it programmatically, it errors out. Where does the problem lie? Is it in the api url or could it be elsewhere? As or right now, I can't do anything with this test url call so I'm a little bit stuck. Does anyone have any ideas to discover what I can do with this?

Sinatra before filter

I'm on Sinatra and i don't understand how to deal with my problem:
I want to "send" to curl a custom message when he try to go on a wrong path.
curl http://localhost:port/blabla
It's an error 404 but i want to send him thing like 'error try other path'
I tried with this :
before'/*' do
if (params[:splat].to_s =~ /path_i_want/) != 2
'wrong path'
end
end
or with raise 404 but it doesn't work.
Could you help me please ?
Regards.
Sinatra has a built-in handler for 404, see Error Handling page. You could do all your logic in there.
Not Found
When a Sinatra::NotFound exception is raised, or the
response’s status code is 404, the not_found handler is invoked:
not_found do
'This is nowhere to be found.'
end

Instagram embed code from url (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.

How can I handle errors with HTTParty?

I'm working on a Rails application using HTTParty to make HTTP requests. How can I handle HTTP errors with HTTParty? Specifically, I need to catch HTTP 502 & 503 and other errors like connection refused and timeout errors.
An instance of HTTParty::Response has a code attribute which contains the status code of the HTTP response. It's given as an integer. So, something like this:
response = HTTParty.get('http://twitter.com/statuses/public_timeline.json')
case response.code
when 200
puts "All good!"
when 404
puts "O noes not found!"
when 500...600
puts "ZOMG ERROR #{response.code}"
end
This answer addresses connection failures. If a URL isn´t found the status code won´t help you. Rescue it like this:
begin
HTTParty.get('http://google.com')
rescue HTTParty::Error
# don´t do anything / whatever
rescue StandardError
# rescue instances of StandardError,
# i.e. Timeout::Error, SocketError etc
end
For more information see: this github issue
You can also use such handy predicate methods as ok? or bad_gateway? like this:
response = HTTParty.post(uri, options)
p response.success?
The full list of all the possible responses can be found under Rack::Utils::HTTP_STATUS_CODES constant.

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