CORS issue happening in tubesock - ruby-on-rails

I have a Sinatra application which runs fine.Now to implement websockets I am using tubesock gem and have added following code
class Server
def call(env)
if env["HTTP_UPGRADE"] == 'websocket'
tubesock = Tubesock.hijack(env)
tubesock.onmessage do |message|
puts "Got #{message}"
end
tubesock.listen
[ -1, {}, [] ]
else
[404, {'Content-Type' => 'text/plain'}, ['Not Found']]
end
end
end
Now it is giving CORS error(Cross origin error).Previously it was working fine.Any suggestions?
Thanks

I was able to use rack/cors and resolve the issue

Related

AWS lambda API ruby responding differently on postman

I am trying to execute some code using AWS lambda using ruby. The same code works well when using configured test event at the lambda function in AWS account, but when I send the same request using postman, it responds with 502 Bad Gateway response code.
When I watch cloudwatch logs, it gives an error message that is not possible on the code that is run.
require "payment_notification_response.rb"
Dir["payment_gateway/*.rb"].each {|file| require file }
class PaymentNotificationRequest
attr_accessor :headers, :body, :query_params, :http_method, :payment_gateway
PAYMENT_GATEWAYS = [::PaymentGateway]
def initialize(event)
self.headers = event["headers"] rescue {}
self.body = JSON.parse(event['body'].to_json, symbolize_names: true) rescue {}
self.query_params = event['queryStringParameters'] rescue {}
self.http_method = event["requestContext"]["http"]["method"] rescue {}
self.payment_gateway = self.find_payment_gateway_by_request
end
def find_payment_gateway_by_request
PAYMENT_GATEWAYS.each do |pg|
return pg if pg.new(self).is_the_requester?
end
end
def process
return self.payment_gateway.new(self).process
end
end
Below error is triggered at cloudwatch
{
"errorMessage": "undefined method `new' for [PaymentGateway]:Array",
"errorType": "Function<NoMethodError>",
"stackTrace": [
"/var/task/payment_notification_request.rb:23:in `process'",
"/var/task/lambda_function.rb:7:in `lambda_handler'"
]
}
How is this possible? Can anyone please help?

How to use SOAP service with xml in Rails (EU VAT number check)

I'd like to add a method in my Rails application that checks the validity of a VAT number using the EU's VIES system: http://ec.europa.eu/taxation_customs/vies/technicalInformation.html
I'm already pretty new to programming in Rails and the instructions here use xml. So I have trouble figuring this out. How should I include the code mentioned on the mentioned website in my Rails application?
In other words, what should the validate_vat(country, vatnumber) method below look like and how to process the response received from the SOAP service?
def vatsubmission
#organization = Organization.find(params[:id])
#organization.update_attributes(vat_params)
#organization.validate_vat(#organization.country, #organization.vatnumber) if (#organization.vatnumber? && #organization.vatnumber?)
# Process response
if valid == false
#organization.update_attributes(valid_vat: false)
flash.now[:danger] = "False VAT number"
render ...
elsif valid == true
#organization.update_attributes(valid_vat: true)
flash.now[:success] = "VAT number validated"
render ...
else
flash.now[:danger] = "VAT number could not be validated"
render ...
end
end
def validate_vat(country, vatnumber)
??
end
Update: I've added gem 'savon', '2.11.1' to my gemfile. In my controller I have:
def update
#organization = Organization.find(params[:id])
if #organization.check_valid == true
#organization.update_attributes(validnr: true)
else
#organization.update_attributes(validnr: false)
end
end
And I have added the following model method:
require 'savon'
def check_valid
debugger
if ["DK", "CY", "etc"].include? self.country
client = Savon.client(wsdl: 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl')
resp = client.call :check_vat do
message country_code: self.country, vat_number: self.vatnr
end
data = resp.to_hash[:check_vat_response]
data[:valid]
end
end
Error: The line message country_code: self.country, vat_number: self.vatnr fails with the error message: wrong number of arguments (1 for 2). I checked with the debugger and self.country as well as self.varnr do have values. What am I doing wrong?
For working with SOAP from Ruby I used excelent Savon gem.
With Savon v2, working code looks like this:
require 'savon'
client = Savon.client(wsdl: 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl')
resp = client.call :check_vat do
message country_code: 'AT', vat_number: '123'
end
data = resp.to_hash[:check_vat_response]
data[:valid] #=> false :)
Note Savon v3 is still in preparation.
I've just started using the ValVat gem for this and it workd beautifully so far!

Is it possible to access the AdSense API using ruby?

I am trying to access the AdSense Management API using ruby. They recommend using their generic Google-API client library:
http://code.google.com/p/google-api-ruby-client/#Google_AdSense_Management_API
This hasn't been very helpful and I have run into errors:
Faraday conflicts in google_drive and google-api-client
Where should I start in order to get access to my AdSense data?
Thanks in advance.
Unfortunately, we haven't prepared any sample code for the AdSense Management API... yet! As you point out, though, the client library is generic, and should work with any of the newer Google APIs, so some of the other samples may help.
If you're running into any specific issues, please create a question focused on those and point me to it, and I'll do my best to help.
If you want a quick sample to get started, I can cook that up for you, but we should make sure the issues you're running into have to do with the AdSense Management API itself, and not just the client library, as the one you were linking to.
[Edit]
Here's a quick sample, based on Sinatra:
#!/usr/bin/ruby
require 'rubygems'
require 'sinatra'
require 'google/api_client'
FILENAME = 'auth.obj'
OAUTH_CLIENT_ID = 'INSERT_OAUTH2_CLIENT_ID_HERE'
OAUTH_CLIENT_SECRET = 'INSERT_OAUTH2_CLIENT_SECRET_HERE'
before do
#client = Google::APIClient.new
#client.authorization.client_id = OAUTH_CLIENT_ID
#client.authorization.client_secret = OAUTH_CLIENT_SECRET
#client.authorization.scope = 'https://www.googleapis.com/auth/adsense'
#client.authorization.redirect_uri = to('/oauth2callback')
#client.authorization.code = params[:code] if params[:code]
# Load the access token here if it's available
if File.exist?(FILENAME)
serialized_auth = IO.read(FILENAME)
#client.authorization = Marshal::load(serialized_auth)
end
if #client.authorization.refresh_token && #client.authorization.expired?
#client.authorization.fetch_access_token!
end
#adsense = #client.discovered_api('adsense', 'v1.1')
unless #client.authorization.access_token || request.path_info =~ /^\/oauth2/
redirect to('/oauth2authorize')
end
end
get '/oauth2authorize' do
redirect #client.authorization.authorization_uri.to_s, 303
end
get '/oauth2callback' do
#client.authorization.fetch_access_token!
# Persist the token here
serialized_auth = Marshal::dump(#client.authorization)
File.open(FILENAME, 'w') do |f|
f.write(serialized_auth)
end
redirect to('/')
end
get '/' do
call = {
:api_method => #adsense.reports.generate,
:parameters => {
'startDate' => '2011-01-01',
'endDate' => '2011-08-31',
'dimension' => ['MONTH', 'CUSTOM_CHANNEL_NAME'],
'metric' => ['EARNINGS', 'TOTAL_EARNINGS']
}
}
response = #client.execute(call)
output = ''
if response && response.data && response.data['rows'] &&
!response.data['rows'].empty?
result = response.data
output << '<table><tr>'
result['headers'].each do |header|
output << '<td>%s</td>' % header['name']
end
output << '</tr>'
result['rows'].each do |row|
output << '<tr>'
row.each do |column|
output << '<td>%s</td>' % column
end
output << '</tr>'
end
output << '</table>'
else
output << 'No rows returned'
end
output
end

Integration testing Rails API with basic authentication

I'm trying to get a test signing in using basic authentication. I've tried a few approaches. See code below for a list of failed attempts and code. Is there anything obvious I'm doing wrong. Thanks
class ClientApiTest < ActionController::IntegrationTest
fixtures :all
test "adding an entry" do
# No access to #request
##request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("someone#somemail.com:qwerty123")
# Not sure why this didn't work
#session["warden.user.user.key"] = [User, 1]
# This didn't work either
# url = URI.parse("http://localhost.co.uk/diary/people/1/entries.xml")
# req = Net::HTTP::Post.new(url.path)
# req.basic_auth 'someone#somemail.com', 'qwerty123'
post "/diary/people/1/entries.xml", {:diary_entry => {
:drink_product_id => 4,
:drink_amount_id => 1,
:quantity => 3
},
}
puts response.body
assert_response 200
end
end
It looks like you might be running rails3 -- Rails3 switched over to Rack::test so the syntax is different. You pass in an environment hash to set your request variables like headers.
Try something like:
path = "/diary/people/1/entries.xml"
params = {:diary_entry => {
:drink_product_id => 4,
:drink_amount_id => 1,
:quantity => 3}
env=Hash.new
env["CONTENT_TYPE"] = "application/json"
env["ACCEPT"] = "application/json"
env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("someone#somemail.com:qwerty123")
get(end_point, params, env)
This could work too, but it might be a sinatra only thing:
get '/protected', {}, {'HTTP_AUTHORIZATION' => encode_credentials('go', 'away')}
Sinatra test credit
This works for me in Rails 3
#request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials('username', 'password')
get :index

How to "pretty" format JSON output in Ruby on Rails

I would like my JSON output in Ruby on Rails to be "pretty" or nicely formatted.
Right now, I call to_json and my JSON is all on one line. At times this can be difficult to see if there is a problem in the JSON output stream.
Is there way to configure to make my JSON "pretty" or nicely formatted in Rails?
Use the pretty_generate() function, built into later versions of JSON. For example:
require 'json'
my_object = { :array => [1, 2, 3, { :sample => "hash"} ], :foo => "bar" }
puts JSON.pretty_generate(my_object)
Which gets you:
{
"array": [
1,
2,
3,
{
"sample": "hash"
}
],
"foo": "bar"
}
The <pre> tag in HTML, used with JSON.pretty_generate, will render the JSON pretty in your view. I was so happy when my illustrious boss showed me this:
<% if #data.present? %>
<pre><%= JSON.pretty_generate(#data) %></pre>
<% end %>
Thanks to Rack Middleware and Rails 3 you can output pretty JSON for every request without changing any controller of your app. I have written such middleware snippet and I get nicely printed JSON in browser and curl output.
class PrettyJsonResponse
def initialize(app)
#app = app
end
def call(env)
status, headers, response = #app.call(env)
if headers["Content-Type"] =~ /^application\/json/
obj = JSON.parse(response.body)
pretty_str = JSON.pretty_unparse(obj)
response = [pretty_str]
headers["Content-Length"] = pretty_str.bytesize.to_s
end
[status, headers, response]
end
end
The above code should be placed in app/middleware/pretty_json_response.rb of your Rails project.
And the final step is to register the middleware in config/environments/development.rb:
config.middleware.use PrettyJsonResponse
I don't recommend to use it in production.rb. The JSON reparsing may degrade response time and throughput of your production app. Eventually extra logic such as 'X-Pretty-Json: true' header may be introduced to trigger formatting for manual curl requests on demand.
(Tested with Rails 3.2.8-5.0.0, Ruby 1.9.3-2.2.0, Linux)
If you want to:
Prettify all outgoing JSON responses from your app automatically.
Avoid polluting Object#to_json/#as_json
Avoid parsing/re-rendering JSON using middleware (YUCK!)
Do it the RAILS WAY!
Then ... replace the ActionController::Renderer for JSON! Just add the following code to your ApplicationController:
ActionController::Renderers.add :json do |json, options|
unless json.kind_of?(String)
json = json.as_json(options) if json.respond_to?(:as_json)
json = JSON.pretty_generate(json, options)
end
if options[:callback].present?
self.content_type ||= Mime::JS
"#{options[:callback]}(#{json})"
else
self.content_type ||= Mime::JSON
json
end
end
Check out Awesome Print. Parse the JSON string into a Ruby Hash, then display it with ap like so:
require "awesome_print"
require "json"
json = '{"holy": ["nested", "json"], "batman!": {"a": 1, "b": 2}}'
ap(JSON.parse(json))
With the above, you'll see:
{
"holy" => [
[0] "nested",
[1] "json"
],
"batman!" => {
"a" => 1,
"b" => 2
}
}
Awesome Print will also add some color that Stack Overflow won't show you.
If you find that the pretty_generate option built into Ruby's JSON library is not "pretty" enough, I recommend my own NeatJSON gem for your formatting.
To use it:
gem install neatjson
and then use
JSON.neat_generate
instead of
JSON.pretty_generate
Like Ruby's pp it will keep objects and arrays on one line when they fit, but wrap to multiple as needed. For example:
{
"navigation.createroute.poi":[
{"text":"Lay in a course to the Hilton","params":{"poi":"Hilton"}},
{"text":"Take me to the airport","params":{"poi":"airport"}},
{"text":"Let's go to IHOP","params":{"poi":"IHOP"}},
{"text":"Show me how to get to The Med","params":{"poi":"The Med"}},
{"text":"Create a route to Arby's","params":{"poi":"Arby's"}},
{
"text":"Go to the Hilton by the Airport",
"params":{"poi":"Hilton","location":"Airport"}
},
{
"text":"Take me to the Fry's in Fresno",
"params":{"poi":"Fry's","location":"Fresno"}
}
],
"navigation.eta":[
{"text":"When will we get there?"},
{"text":"When will I arrive?"},
{"text":"What time will I get to the destination?"},
{"text":"What time will I reach the destination?"},
{"text":"What time will it be when I arrive?"}
]
}
It also supports a variety of formatting options to further customize your output. For example, how many spaces before/after colons? Before/after commas? Inside the brackets of arrays and objects? Do you want to sort the keys of your object? Do you want the colons to all be lined up?
Dumping an ActiveRecord object to JSON (in the Rails console):
pp User.first.as_json
# => {
"id" => 1,
"first_name" => "Polar",
"last_name" => "Bear"
}
Using <pre> HTML code and pretty_generate is good trick:
<%
require 'json'
hash = JSON[{hey: "test", num: [{one: 1, two: 2, threes: [{three: 3, tthree: 33}]}]}.to_json]
%>
<pre>
<%= JSON.pretty_generate(hash) %>
</pre>
Here is a middleware solution modified from this excellent answer by #gertas. This solution is not Rails specific--it should work with any Rack application.
The middleware technique used here, using #each, is explained at ASCIIcasts 151: Rack Middleware by Eifion Bedford.
This code goes in app/middleware/pretty_json_response.rb:
class PrettyJsonResponse
def initialize(app)
#app = app
end
def call(env)
#status, #headers, #response = #app.call(env)
[#status, #headers, self]
end
def each(&block)
#response.each do |body|
if #headers["Content-Type"] =~ /^application\/json/
body = pretty_print(body)
end
block.call(body)
end
end
private
def pretty_print(json)
obj = JSON.parse(json)
JSON.pretty_unparse(obj)
end
end
To turn it on, add this to config/environments/test.rb and config/environments/development.rb:
config.middleware.use "PrettyJsonResponse"
As #gertas warns in his version of this solution, avoid using it in production. It's somewhat slow.
Tested with Rails 4.1.6.
#At Controller
def branch
#data = Model.all
render json: JSON.pretty_generate(#data.as_json)
end
If you're looking to quickly implement this in a Rails controller action to send a JSON response:
def index
my_json = '{ "key": "value" }'
render json: JSON.pretty_generate( JSON.parse my_json )
end
Here's my solution which I derived from other posts during my own search.
This allows you to send the pp and jj output to a file as needed.
require "pp"
require "json"
class File
def pp(*objs)
objs.each {|obj|
PP.pp(obj, self)
}
objs.size <= 1 ? objs.first : objs
end
def jj(*objs)
objs.each {|obj|
obj = JSON.parse(obj.to_json)
self.puts JSON.pretty_generate(obj)
}
objs.size <= 1 ? objs.first : objs
end
end
test_object = { :name => { first: "Christopher", last: "Mullins" }, :grades => [ "English" => "B+", "Algebra" => "A+" ] }
test_json_object = JSON.parse(test_object.to_json)
File.open("log/object_dump.txt", "w") do |file|
file.pp(test_object)
end
File.open("log/json_dump.txt", "w") do |file|
file.jj(test_json_object)
end
I have used the gem CodeRay and it works pretty well. The format includes colors and it recognises a lot of different formats.
I have used it on a gem that can be used for debugging rails APIs and it works pretty well.
By the way, the gem is named 'api_explorer' (http://www.github.com/toptierlabs/api_explorer)
if you want to handle active_record object, puts is enough.
for example:
without puts
2.6.0 (main):0 > User.first.to_json
User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> "{\"id\":1,\"admin\":true,\"email\":\"admin#gmail.com\",\"password_digest\":\"$2a$10$TQy3P7NT8KrdCzliNUsZzuhmo40LGKoth2hwD3OI.kD0lYiIEwB1y\",\"created_at\":\"2021-07-20T08:34:19.350Z\",\"updated_at\":\"2021-07-20T08:34:19.350Z\",\"name\":\"Arden Stark\"}"
with puts
2.6.0 (main):0 > puts User.first.to_json
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
{"id":1,"admin":true,"email":"admin#gmail.com","password_digest":"$2a$10$TQy3P7NT8KrdCzliNUsZzuhmo40LGKoth2hwD3OI.kD0lYiIEwB1y","created_at":"2021-07-20T08:34:19.350Z","updated_at":"2021-07-20T08:34:19.350Z","name":"Arden Stark"}
=> nil
if you are handle the json data, JSON.pretty_generate is a good alternative
Example:
obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
json = JSON.pretty_generate(obj)
puts json
Output:
{
"foo": [
"bar",
"baz"
],
"bat": {
"bam": 0,
"bad": 1
}
}
if it's in the ROR project, I always prefer to use gem pry-rails to format my codes in the rails console rather than awesome_print which is too verbose.
Example of pry-rails:
it also has syntax highlight.
# example of use:
a_hash = {user_info: {type: "query_service", e_mail: "my#email.com", phone: "+79876543322"}, cars_makers: ["bmw", "mitsubishi"], car_models: [bmw: {model: "1er", year_mfc: 2006}, mitsubishi: {model: "pajero", year_mfc: 1997}]}
pretty_html = a_hash.pretty_html
# include this module to your libs:
module MyPrettyPrint
def pretty_html indent = 0
result = ""
if self.class == Hash
self.each do |key, value|
result += "#{key}: #{[Array, Hash].include?(value.class) ? value.pretty_html(indent+1) : value}"
end
elsif self.class == Array
result = "[#{self.join(', ')}]"
end
"#{result}"
end
end
class Hash
include MyPrettyPrint
end
class Array
include MyPrettyPrint
end
Simplest example, I could think of:
my_json = '{ "name":"John", "age":30, "car":null }'
puts JSON.pretty_generate(JSON.parse(my_json))
Rails console example:
core dev 1555:0> my_json = '{ "name":"John", "age":30, "car":null }'
=> "{ \"name\":\"John\", \"age\":30, \"car\":null }"
core dev 1556:0> puts JSON.pretty_generate(JSON.parse(my_json))
{
"name": "John",
"age": 30,
"car": null
}
=> nil
Pretty print variant (Rails):
my_obj = {
'array' => [1, 2, 3, { "sample" => "hash"}, 44455, 677778, nil ],
foo: "bar", rrr: {"pid": 63, "state with nil and \"nil\"": false},
wwww: 'w' * 74
}
require 'pp'
puts my_obj.as_json.pretty_inspect.
gsub('=>', ': ').
gsub(/"(?:[^"\\]|\\.)*"|\bnil\b/) {|m| m == 'nil' ? 'null' : m }.
gsub(/\s+$/, "")
Result:
{"array": [1, 2, 3, {"sample": "hash"}, 44455, 677778, null],
"foo": "bar",
"rrr": {"pid": 63, "state with nil and \"nil\"": false},
"wwww":
"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"}
If you are using RABL you can configure it as described here to use JSON.pretty_generate:
class PrettyJson
def self.dump(object)
JSON.pretty_generate(object, {:indent => " "})
end
end
Rabl.configure do |config|
...
config.json_engine = PrettyJson if Rails.env.development?
...
end
A problem with using JSON.pretty_generate is that JSON schema validators will no longer be happy with your datetime strings. You can fix those in your config/initializers/rabl_config.rb with:
ActiveSupport::TimeWithZone.class_eval do
alias_method :orig_to_s, :to_s
def to_s(format = :default)
format == :default ? iso8601 : orig_to_s(format)
end
end
I use the following as I find the headers, status and JSON output useful as
a set. The call routine is broken out on recommendation from a railscasts presentation at: http://railscasts.com/episodes/151-rack-middleware?autoplay=true
class LogJson
def initialize(app)
#app = app
end
def call(env)
dup._call(env)
end
def _call(env)
#status, #headers, #response = #app.call(env)
[#status, #headers, self]
end
def each(&block)
if #headers["Content-Type"] =~ /^application\/json/
obj = JSON.parse(#response.body)
pretty_str = JSON.pretty_unparse(obj)
#headers["Content-Length"] = Rack::Utils.bytesize(pretty_str).to_s
Rails.logger.info ("HTTP Headers: #{ #headers } ")
Rails.logger.info ("HTTP Status: #{ #status } ")
Rails.logger.info ("JSON Response: #{ pretty_str} ")
end
#response.each(&block)
end
end
I had a JSON object in the rails console, and wanted to display it nicely in the console (as opposed to displaying like a massive concatenated string), it was as simple as:
data.as_json

Resources