Getting HTTP response in Rails - ruby-on-rails

In my Rails controller, I have the url that the user inputs:
url_parsed = URI.parse(url)
response = Net::HTTP.get_response(url_parsed)
If the user inputs www.google.com, it gives
undefined method `request_uri' for #<URI::Generic:0x00000002e07908 URL:www.google.com>
on the line response = ....
I want it to display my error page, instead of this error. How can I do it?

Don't know if your question is why it isn't working, or how to use the error message in the view.
Why you get the error
EDIT:
I think that it's because there is no protocol in 'www.google.com', 'http://www.google.com' should work
How to show the error
Rescue the error:
error = nil
begin
url_parsed = URI.parse(url)
response = Net::HTTP.get_response(url_parsed)
rescue => error
end
if error
#error_message = "Your URL wasn't good enough"
# or you can use error.message if you want
# then use #error_message in your view
else
# do stuff when ok
end

Related

Rails 6 how to add an API error with message

I'm trying to implement error handling for my API client. Everything looks pretty good but except of the error I want to error description from the API either (it's inside response.body['FirebirdApiError']['ApiStatusDescription']). Like below:
# error handler class
module Errors
class APIExceptionError < StandardError; end
BadRequestError = Class.new(APIExceptionError)
UnauthorizedError = Class.new(APIExceptionError)
ForbiddenError = Class.new(APIExceptionError)
ApiRequestsQuotaReachedError = Class.new(APIExceptionError)
NotFoundError = Class.new(APIExceptionError)
UnprocessableEntityError = Class.new(APIExceptionError)
ApiError = Class.new(APIExceptionError)
def error_class(status)
case status
when 400
BadRequestError
when 401
UnauthorizedError
when 403
ForbiddenError
when 404
NotFoundError
when 429
UnprocessableEntityError
else
ApiError
end
end
end
Which is user inside of client class:
#client class
class Client
include ::Errors
def get(path, options = {})
handle_response(client.public_send(:get, path.to_s, options))
end
private
(...)
def handle_response(response)
return response_body(response) if response.success?
raise error_class(response.status)
end
def response_body(response)
return if response.body.blank?
response.body
end
end
Which works well but when I'll reach 400 error it will show me Errors::BadRequestError. I don't think it's handy in case where the API provides a pretty good description of the cause of the error inside response.body['FirebirdApiError']['ApiStatusDescription']. How do I add this message to display with the error?
You want to add error message when your raise error, right? Maybe you can try
raise error_class(response.status).new(response.body['FirebirdApiError']['ApiStatusDescription'])

Rails app to check the status of a server

I want to achieve a problem, where we manually go and check a webapp/server if it is up/down. I want to build a rails app which can automate this task.
Consider my app url is: HostName:PORT/Route?Params (may or may not have port in url)
I checked 'net/http'
def check_status()
#url='host'
uri = URI(#url)
http = Net::HTTP.new(#url,port)
response = http.request_get('/<route>?<params>')
if response == Net::HTTPSuccess
#result='Running'
else
#result='Not Running'
end
end
I am facing error at ,
response = http.request_get('/<route>?<params>')
when the app is down throwing 'Failed to open TCP connection to URL' which is correct.
Can you guys help me find some new solution or how can I improve the above implementation?
Since it's working as intended and you just need to handle the error that's returned when the app is down, wrap it in a rescue block.
def check_status()
#url='host'
uri = URI(#url)
http = Net::HTTP.new(#url,port)
begin
response = http.request_get('/<route>?<params>')
rescue TheClassNameOfThisErrorWhenSiteIsDown
#result = 'Not Running'
end
if response == Net::HTTPSuccess
#result='Running'
else
#result='Not Running'
end
end
end
Just came across this old question. Net::HTTP methods get and head don't raise an exception. So use one of these instead.
def up?(site)
Net::HTTP.new(site).head('/').kind_of? Net::HTTPOK
end
up? 'www.google.com' #=> true

How to change response.message in rails

Hello I am having given code
def create_profile(payment)
return unless payment.source.gateway_customer_profile_id.nil?
options = {
email: payment.order.email,
login: preferred_secret_key,
}.merge! address_for(payment)
source = update_source!(payment.source)
if source.number.blank? && source.gateway_payment_profile_id.present?
creditcard = source.gateway_payment_profile_id
else
creditcard = source
end
response = provider.store(creditcard, options)
if response.success?
cc_type=payment.source.cc_type
response_cc_type = response.params['sources']['data'].first['brand']
cc_type = CARD_TYPE_MAPPING[response_cc_type] if CARD_TYPE_MAPPING.include?(response_cc_type)
payment.source.update_attributes!({
cc_type: cc_type, # side-effect of update_source!
gateway_customer_profile_id: response.params['id'],
gateway_payment_profile_id: response.params['default_source'] || response.params['default_card']
})
else
payment.send(:gateway_error, response.message)
end
end
I need to change message in response.message for that i had tried using response = [ { message: "fraud card"} ].to_json but it gives error `
undefined method `message' for "[{"message":"fraud card"}]":String
I had also tried response.message = 'fraud error', still it gives error. Response I receive is :
params:
error:
message: Your card was declined.
type: card_error
code: card_declined
decline_code: fraudulent
charge: ch_1AgncyJEfCzWOpKDdoxn1x1R
message: Your card was declined.
success: false
test: false
authorization: ch_1AgncyJEfCzWOpKDdoxn1x1R
fraud_review:
error_code: card_declined
emv_authorization:
avs_result:
code:
message:
street_match:
postal_match:
cvv_result:
code:
message:
Now my requirement is to check if decline_code is fraudulent than my message should be fraud error. please let me know how to change this.
Based on your comment, you're using Spree Gateway. By passing a string instead of the proper response object, your solution circumvents Spree's default implementation which logs error details for the response.
What I'd do instead is adapt the gateway_error method to your needs by following Spree's suggested approach for logic customization:
# app/models/spree/payment_decorator.rb
Spree::Payment.class_eval do
private
def gateway_error(error)
if error.is_a? ActiveMerchant::Billing::Response
# replace this with your actual implementation, e.g. based on response.params['error']['code']
text = 'fraud message'
elsif error.is_a? ActiveMerchant::ConnectionError
text = Spree.t(:unable_to_connect_to_gateway)
else
text = error.to_s
end
logger.error(Spree.t(:gateway_error))
logger.error(" #{error.to_yaml}")
raise Core::GatewayError.new(text)
end
end
It's not the cleanest implementation since it does copy & paste for existing code. But that's just how Spree is (I've implemented and contributed to multiple Spree shops and it's always a bit painful when customizing logic, especially private logic).
Hope that helps.

Simple Mongoid Validation for create! - how to display error messages

I'm using Rails 3 with mongoid 2 and have a simple question regarding mongoid validation.
if #forum.topics.create!(name: params[:topic][:name])
# success, do something
else
#should handle errors but doesn't
render 'new'
end
If I use the .create! method, it runs validations on a mongoid model class correctly, but it is not getting to the else block to display the error. Instead it returns a rails error page saying...
Mongoid::Errors::Validations in TopicsController#create
Validation failed - Name can't be blank.
That's good, but how do I display that in a view instead of getting an ugly rails error message page?
Try this way:
new_topic = #forum.topics.new(name: params[:topic][:name])
if new_topic.save
# success, do something
else
render 'new', errors: new_topic.errors.full_messages
end
with this way you will have the local variable errors which is a Hash formated like following:
new_topic.errors.full_messages # => ["\"Name\" can't be blank"]
you can rescue the Mongoid::Errors::Validations and use it's instance method to get the errors
new_topic = #forum.topics.new(name: params[:topic][:name])
new_topic.create!
rescue Mongoid::Errors::Validations => e
summary = e.summary
problem = e.problem
res = e.resolution
using the above error messages you can display the error
Documentaion link
https://docs.mongodb.com/mongoid/6.2/api/Mongoid/Errors/Validations.html

Ruby on Rails - Checking against HTTP errors in controller

Just today I've found my fbgraph implementation has started returning a 400 Bad Request error which is causing an internal server error.
The controller looks like:
def fb
fbclient = FBGraph::Client.new(:client_id => 'ID', :secret_id => 'SECRET')
#fbname = fbclient.selection.user('129220333799040').feed.info!['data'][0].from.name
#fbmessage = fbclient.selection.user('129220333799040').feed.info!['data'][0].message
end
How can I check before calling #fbname in my view that I've received a 200 status?
Thanks.
Update: following Devin M's suggestion, I've switched the above action to
def fb
fbclient = FBGraph::Client.new(:client_id => 'ID', :secret_id => 'SECRET')
begin
#fbname = fbclient.selection.user('129220333799040').feed.info!['data'][0].from.name
#fbmessage = fbclient.selection.user('129220333799040').feed.info!['data'][0].message
rescue
#fbname = "Facebook Account"
#fbmessage = "Facebook's API is a nightmare"
end
end
I think that you should write some tests for this, Its hard to work with Facebooks nightmare of an API.
Although if you wanted to catch this error try using that way you can catch the specific error and take some action on it in the rescue portion.
begin
rescue
end
If you want me to take a look at the docs and see what you should catch let me know.

Resources