Migrating Sinatra Webrick RACK:SSLEnforcer based HTTPS to Thin - ruby

I have been running Sinatra with Webrick and SSL using Rack::SSLenforcer in a development environment for a long while without any issues (based on https://github.com/tobmatth/rack-ssl-enforcer#readme ), i am trying to migrate to Thin in order to add websockets support but have issues getting my current app (without websockets) to run with Thin and SSL.
The basic code that i currently have on websockets is the following:
begin
pkey = OpenSSL::PKey::RSA.new(File.open("private_key.pem").read)
cert = OpenSSL::X509::Certificate.new(File.open("certificate.pem").read)
end
webrick_options = {
:Port => 8447,
:Logger => WEBrick::Log::new($stderr, WEBrick::Log::DEBUG),
:DocumentRoot => "/ruby/htdocs",
:SSLEnable => true,
:SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
:SSLCertificate => cert,
:SSLPrivateKey => pkey,
:SSLCertName => [ [ "CN",WEBrick::Utils::getservername ] ],
:app => MyWebRTCServer
}
Rack::Server.start webrick_options
Then in my app i have the following:
configure do
# require SSL - https://github.com/tobmatth/rack-ssl-enforcer#readme
use Rack::SslEnforcer
set :session_secret, 'asdfa2342923422f1adc05c837fa234230e3594b93824b00e930ab0fb94b'
use Rack::Session::Cookie, :key => '_rack_session',
:path => '/',
:expire_after => 2592000, # In seconds
:secret => session_secret
# load password file -
begin
##config = YAML.load_file(File.join(Dir.pwd, 'config', 'users.yml'))
rescue ArgumentError => e
puts "Could not parse YAML: #{e.message}"
end
# puts "config: " + ##config.to_s
use Rack::Auth::Basic, "Restricted Area" do |u, p|
$LOG.info "Use Rack::Auth::Basic"
if (!##config[:users][u])
puts "Bad username"
false
else
# initialize the BCrypt with the password
tPassword = BCrypt::Password.new(##config[:users][u][:password].to_s)
# puts "From BCrypt: " + tPassword
if (tPassword == p)
# puts "Validated password"
# check whether the user is already logged in or not
if (!##user_table_cache[u.to_sym])
# puts "User already logged in or session has not expired"
userHash = Hash.new
userHash[:name] = u
userHash[:privilege] = ##config[:users][u][:privilege]
# add the user hash to the cache
##user_table_cache[u.to_sym] = userHash
end
end
true
end
end
end
All of this works on webrick with Sinatra. I have tried the following on Thin (based on Can I enable SSL in Sinatra with Thin?)
class MyApp < Sinatra::Base
# ...
get '/' do
puts "got request"
end
end
MyApp.run! do |server|
ssl_options = {
:cert_chain_file => './certificate.pem',
:private_key_file => './private_key.pem',
:verify_peer => false
}
server.ssl = true
server.ssl_options = ssl_options
end
However, I get the following error, when i try to access it from the browser.
C:\Software\Ruby Projects\Utils\sandbox\thintest>thistest
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from Th
in
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop
terminate called after throwing an instance of 'std::runtime_error'
what(): Encryption not available on this event-machine
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
any thoughts would be greatly appreciated.

Related

how to check mysql connexion

I would want to check if there is a connection with the database before execute the query .
But when I write if mysql_connection ... then it passes twice on mysql_connection:
def mysql_connection
puts "mysql_connection 1"
read_config_file
#connexion = Mysql2::Client.new(:host => #conf['host'], :username => #conf['user'], :password => #conf['password'], :database=> #conf['base'], :port => #conf['port'])
end
# USER QUERY MYSQL
def mysql_select_user(value)
puts "select"
# if mysql_connection then
p = mysql_connection.query("select #{value} from User")
p.each do |f|
puts "value : #{f}"
mysql_close
end
# else
# end
end
Use Mysql2::Client#ping method (from docs: http://www.rubydoc.info/gems/mysql2/0.3.13/Mysql2/Client#ping-instance_method)

How to return to the calling method?

I have a program that uses a method for verification, if that verification failed I would like to return to the method it was called from, for example:
def obtain_pokemon_name
print 'Enter Pokemon: '
pokemon = gets.chomp.capitalize
obtain_basic_attack(pokemon)
end
def obtain_basic_attack(poke)
print 'Enter basic attack: '
basic_attack = gets.chomp.downcase
check_attacks(poke, basic_attack)
obtain_spec_attack(poke)
end
def obtain_spec_attack(poke)
print 'Enter special attack: '
spec_attack = gets.chomp.downcase
check_attacks(poke, spec_attack)
end
def check_attacks(pokemon, attack)
if POKEMON_ATTACKS[pokemon][attack] == nil
puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
return # to where this function was called
else
attack
end
end
begin
obtain_pokemon_name
rescue => e
puts "Failed with error code: #{e}"
end
When this is run:
Enter Pokemon: arbok
Enter basic attack: eat
eat is not one of Arbok's attacks, try again..
Enter special attack: test
test is not one of Arbok's attacks, try again..
Attack list:
POKEMON_ATTACKS = {
'Bulbasaur' => {'tackle' => 10.9, 'vine whip' => 15.4, 'power whip' => 21.4, 'seed bomb' => 12.5, 'sludge bomb' => 19.2},
'Ivysaur' => {'razor leaf' => 10.3, 'vine whip' => 15.4, 'power whip' => 21.4, 'sludge bomb' => 19.2, 'solar beam' => 13.3},
'Kakuna' => {'bug bite' => 13.3, 'poison sting' => 10.3, 'struggle' => 8.8},
'Beedrill' => {'bug bite' => 13.3, 'poison jab' => 14.3, 'aerial ace' => 8.6, 'sludge bomb' => 19.2, 'x-scissor' => 14.3},
'Pidgey' => {'quick attack' => 7.5, 'tackle' => 10.9, 'aerial ace' => 8.6, 'air cutter' => 7.6, 'twister' => 5.6},
'Ekans' => {'acid' => 9.5, 'poison sting' => 10.3, 'gunk shot' => 20.0, 'sludge bomb' => 19.2, 'wrap' => 3.8},
'Arbok' => {'acid' => 9.5, 'bite' => 12.0, 'dark pulse' => 12.9, 'gunk shot' => 20.0, 'sludge wave' => 17.6},
}
So my question is, if the attack is not present in the data, how can I return back to the calling method? So for instance if I call arbok and his attack is tackle if it doesn't exist in the hash, how would I return to the obtain_basic_attack(poke) method?
RIght here:
puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
return # to where this function was called
you should call the original method again. i.e.
if POKEMON_ATTACKS[pokemon][attack] == nil
puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
return obtain_spec_attack(poke)
You could alternatively add this logic to obtain_spec_attack:
def obtain_spec_attack(poke)
loop do
print 'Enter special attack: '
spec_attack = gets.chomp.downcase
attack_found = check_attacks(poke, spec_attack)
if attack_found
break attack_found # this will return attack_found from the loop
else
puts "attack not found"
end
end
end
edit
looking at your question again, I realize you want to return to a method multiple levels up. You could use the approaches I've already outlined, or alternatively use rescue:
def obtain_basic_attack(poke)
begin
print 'Enter basic attack: '
basic_attack = gets.chomp.downcase
check_attacks(poke, basic_attack)
obtain_spec_attack(poke)
rescue AttackNotFoundError
retry # runs the 'begin' block again
end
end
def obtain_spec_attack(poke)
print 'Enter special attack: '
spec_attack = gets.chomp.downcase
check_attacks(poke, spec_attack)
end
def check_attacks(pokemon, attack)
if POKEMON_ATTACKS[pokemon][attack] == nil
puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
raise AttackNotFoundError
else
attack
end
end
In order to use a custom error like AttackNotFoundError, you need to define the error class somewhere:
class AttackNotFoundError < StandardError; end
You could use any error really, such as raise StandardError, but it's better to restrict what errors you're rescuing so that you don't accidentally rescue an unrelated error.

how to excute code on webrick server

I start a webrick server like this:
dell#dev:/var/www/ruby$ ruby -run -httpd. -p 5000
and have this code in abc.rb:
require 'webrick'
root = File.path '/tmp/public_html'
server = WEBrick::HTTPServer.new :Port => 5000, :DocumentRoot => root
trap 'INT' do server.shutdown end
server.start
ary = { "0"=>"fred", "1"=>10, "2"=>3.14, "3"=>"This is a string", "4"=>"last element", }
ary.each do |key, value|
puts "#{key} #{value}"
end
When I run this code it shows me the same code on browser
http://localhost:5000/abc.rb
How can I view the output this code, I have already asked this question and did not get any correct answer :(
Is it the right code? I want to know this, where this code place
require 'webrick'
root = File.path '/tmp/public_html'
server = WEBrick::HTTPServer.new :Port => 5000, :DocumentRoot => root
trap 'INT' do server.shutdown end
server.start
if any one give me step by step ans to run this code i am very thankful.. I don't understand the ans :( how to do this
From the documentation:
The easiest way to have a server perform custom operations is through
WEBrick::HTTPServer#mount_proc. The block given will be called with a
WEBrick::HTTPRequest with request info and a WEBrick::HTTPResponse
which must be filled in appropriately:
server.mount_proc '/' do |req, res|
res.body = 'Hello, world!'
end
Remember that server.mount_proc must server.start.
So:
require 'webrick'
root = File.path '/tmp/public_html'
server = WEBrick::HTTPServer.new :Port => 5000, :DocumentRoot => root
server.mount_proc '/abc.rb' do |req, res|
ary = { "0"=>"fred", "1"=>10, "2"=>3.14, "3"=>"This is a string", "4"=>"last element" }
res.body = ary.map do |key, value|
"#{key} #{value}"
end.join("\n")
end
trap 'INT' do server.shutdown end
server.start
Also, I believe the correct way to start your WebBrick is by running:
ruby abc.rb

Ruby Tweetstream MongoDB Error

I keep getting the following error when running the following ruby script. If anyone can help me fix this it would be greatly appreciated. I've removed any sensitive data such as API keys.
Code:
#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"
TweetStream.configure do |config|
config.consumer_key = 'KEY'
config.consumer_secret = 'SECRET'
config.oauth_token = 'TOKEN'
config.oauth_token_secret = 'TOKEN_SECRET'
config.auth_method = :oauth
end
db = Mongo::Connection.new("ds045037.mongolab.com", 45037).db("tweets")
auth = db.authenticate("DB_USERNAME", "DB_PASSWORD")
tweets = db.collection("tweetdata")
TweetStream::Daemon.new("TWITTER_USERNAME", "TWITTER_PASSWORD").track("TERM") do |status|
# Do things when nothing's wrong
data = {"created_at" => Time.parse(status.created_at), "text" => status.text, "geo" => status.geo, "coordinates" => status.coordinates, "id" => status.id, "id_str" => status.id_str}
tweets.insert({"data" => data});
end
Command to start the script:
ruby tweetscrape.rb
Ruby version:
ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-linux]
ruby -c tweetscrape.rb produces:
Syntax OK
Error Message:
/usr/local/rvm/gems/ruby-1.9.3-p429/gems/daemons-1.1.9/lib/daemons.rb:184:in `[]=': can't convert Symbol into Integer (TypeError)
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/daemons-1.1.9/lib/daemons.rb:184:in `run_proc'
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/daemon.rb:48:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/client.rb:131:in `filter'
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/client.rb:98:in `track'
from tweetscrape.rb:19:in `<main>'
EDIT: I now have no errors using the below but nothing is entered in to the mongodb:
#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"
TweetStream.configure do |config|
config.consumer_key = 'gfdsgfdsgfdsgfdsgfdsgfds'
config.consumer_secret = 'gfsdgfdsgfdsgfdsgfsdgfd'
config.oauth_token = 'gfdgfdsgfsdgfdsgfsdgf'
config.oauth_token_secret = 'hsgfsdgfsdgfsdgfds'
config.auth_method = :oauth
end
db = Mongo::Connection.new("ds045037.mongolab.com", 45037).db("tweets")
auth = db.authenticate("gfsdgfdsgfsd", "gfdsgfdsgfdsgfsd")
tweets = db.collection("tweetdata")
TweetStream::Client.new.track('TERM') do |status|
puts status.text
data = {"created_at" => Time.parse(status.created_at), "text" => status.text, "geo" => status.geo, "coordinates" => status.coordinates, "id" => status.id, "id_str" => status.id_str}
tweets.insert({"data" => data})
end
Tweets show on screen through puts though...
The initial error you were getting with the Daemon class is because you're not passing the correct parameters to the constructor. The contructor takes a string and a hash.
Moving on from that , the insert failed because:
parsing status.datetime throws an exception (its already a Time object).
status.coordinate throws an exception if there's no coordinate.
The following code works for me (note : I added growl so you can see the tweets):
#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"
require 'growl'
DESIRED = %w{created_at text geo coordinates id id_str}
host= ENV["MONGO_HOST"] || 'localhost'
port = ENV["MONGO_PORT"] || 27017
username = ENV["MONGO_USERNAME"]
password = ENV["MONGO_PASSWORD"]
term = ARGV[1] || 'TERM'
begin
TweetStream.configure do |config|
config.consumer_key = ENV["TWEET_CONSUMER_KEY"]
config.consumer_secret = ENV["TWEET_CONSUMER_SECRET"]
config.oauth_token = ENV["TWEET_OAUTH_TOKEN"]
config.oauth_token_secret = ENV["TWEET_OAUTH_TOKEN_SECRET"]
config.auth_method = :oauth
end
db = Mongo::Connection.new(host, port).db("tweets")
db.authenticate(username, password)
tweets = db.collection("tweetdata")
puts "about to start tracking term #{term}"
TweetStream::Daemon.new('tracker').track(term) do |status|
Growl.notify status.text, :title => status.user.screen_name
#
# filter out nil values
# filter out all keys not in the desired array
#
data = status.attrs.select{|k,v| !v.nil? && DESIRED.include?(k.to_s)}
tweets.insert({"data" => data});
end
rescue Mongo::ConnectionFailure
puts "Connection Error : #{$!}"
rescue Mongo::AuthenticationError
puts "Auth Error : #{$!}"
rescue Mongo::MongoDBError
puts "Unexpected Error : #{$!}"
end
You'll need to setup your environment with the following correct values :
export MONGO_USERNAME="..."
export MONGO_PASSWORD="..."
export TWEET_CONSUMER_KEY="..."
export TWEET_CONSUMER_SECRET="..."
export TWEET_OAUTH_TOKEN="..."
export TWEET_OAUTH_TOKEN_SECRET="..."
Then you can start the daemon with something like (in this case we'll search for yankees):
ruby tweetscrape.rb start yankees

Too many parameters on Imap::new

I am trying the following, but Imap::new is complaining about too many parameters
require 'rubygems'
require 'highline/import'
require 'net/imap'
puts "username"
username = gets
password = ask("Enter password: ") { |q| q.echo = false }
imap = Net::IMAP.new('imap.gmail.com', {:port => '993', :ssl => true})
puts "connecting to imap server"
imap.login(username, password)
imap.select('INBOX')
imap.select('INBOX')
imap.search(["NOT", "DELETED"]).each do |message_id|
envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
puts "#{envelope.from[0].name}: \t#{envelope.subject}"
i += 1
Process.exit if i>10
end
Error:
/Users/username/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1101:in `get_tagged_response': Too many arguments provided ci7if1523987wib.93 (Net::IMAP::BadResponseError)
from /Users/username/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1153:in `block in send_command'
from /Users/username/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize'
from /Users/username/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1135:in `send_command'
from /Users/username/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:419:in `login'
from pull.rb:13:in main
Any ideas?
This should do the trick
imap = Net::IMAP.new('host', 993, true) // host, port, ssl
imap.login('IMAP_USERNAME', 'IMAP_PASSWORD')
imap.select('INBOX')
btw. you're selecting the INBOX twice :)

Resources