How to Enable Ssl for a Standalone Sinatra App

How to enable SSL for a standalone Sinatra app?

To do this with MRI ruby, use the following monkeypatch:

sinatra_ssl.rb:

require 'webrick/https'

module Sinatra
class Application
def self.run!
certificate_content = File.open(ssl_certificate).read
key_content = File.open(ssl_key).read

server_options = {
:Host => bind,
:Port => port,
:SSLEnable => true,
:SSLCertificate => OpenSSL::X509::Certificate.new(certificate_content),
:SSLPrivateKey => OpenSSL::PKey::RSA.new(key_content)
}

Rack::Handler::WEBrick.run self, server_options do |server|
[:INT, :TERM].each { |sig| trap(sig) { server.stop } }
server.threaded = settings.threaded if server.respond_to? :threaded=
set :running, true
end
end
end
end

Then, in your standalone application:

app.rb

require 'sinatra'
require 'sinatra_ssl'

set :port, 8443
set :ssl_certificate, "server.crt"
set :ssl_key, "server.key"

get "/" do
"Hello world!"
end

Enable https in a rails app on a thin server

I don't know if you need it, but this helped me:

  thin start --ssl --ssl-verify --ssl-key-file ssllocal/server.key
--ssl-cert-file ssllocal/server.crt

edit path to ssl key and ssl fild. For example my keys were in paypal folder, so command was

    thin start --ssl --ssl-verify --ssl-key-file paypal/server.key
--ssl-cert-file paypal/server.crt

If you will have problems you can look at this post - Thin with SSL support and ruby-debug.

Hope this helps.

How to mount a Sinatra application inside another Sinatra app?

Take a look at https://stackoverflow.com/a/15699791/335847 which has some ideas about namespacing.

Personally, I would use the config.ru with mapped routes. If you're really in that space between "should this be a separate app or is it just helpful to organize it like this" it allows that, and then later you can still farm off one of the apps on its own without changing the code (or only a little). If you're finding that there's a lot of duplicated set up code, I'd do something like this:

# base_controller.rb

require 'sinatra/base'
require "haml"
# now come some shameless plugs for extensions I maintain :)
require "sinatra/partial"
require "sinatra/exstatic_assets"

module MyAmazingApp
class BaseController < Sinatra::Base
register Sinatra::Partial
register Sinatra::Exstatic

end

class Blog < BaseController
# this gets all the stuff already registered.
end

class Foo < BaseController
# this does too!
end
end

# config.ru

# this is just me being lazy
# it'd add in the /base_controller route too, so you
# may want to change it slightly :)
MyAmazingApp.constants.each do |const|
map "/#{const.name.downcase}" do
run const
end
end

Here's a quote from Sinatra Up and Running:

Not only settings, but every aspect of a Sinatra class will be inherited by its subclasses. This includes defined routes, all the error handlers, extensions, middleware, and so on.

It has some good examples of using this technique (and others). Since I'm in shameless plug mode I recommend it, even though I've nothing to do with it! :)

Sinatra, where to place the require statments

I recommend:

  • Require your main app file only from your config.ru.
  • Require Sinatra and views gems in your main app
  • Create individual init.rb files for each of your helpers, models, and routes, and require those in your main app.
  • Require DB-related gems in models/init.rb

Here's an example of the layout I use:

Using Sinatra for larger projects via multiple files

Note that by loading DB-related gems and setting up your DB in your models/init.rb you can (from IRB) load just that file and have your full model stack available for poking at.

Sinatra and environment.rb

The purpose of the configure block is to set various Sinatra environment all in one place, and different settings for dev vs production. The configure method itself is a part of the Sinatra framework.

This page explains Sinatra environment variables, if you haven't seen it yet. As for putting it in a separate file, it just helps to break an app into separate files. Some people prefer to break Sinatra apps into many files, whereas smaller apps can actually just be one large file.

A good example of the former is Phrogz' answer to this question (which also includes an example of using configure, albeit in the application file rather than in a separate configuration file).

Using Sinatra for larger projects via multiple files

Here is a basic template for Sinatra apps that I use. (My larger apps have 200+ files broken out like this, not counting vendor'd gems, covering 75-100 explicit routes. Some of these routes are Regexp routes covering an additional 50+ route patterns.) When using Thin, you run an app like this using:

thin -R config.ru start

Edit: I'm now maintaining my own Monk skeleton based on the below called Riblits. To use it to copy my template as the basis for your own projects:

# Before creating your project
monk add riblits git://github.com/Phrogz/riblits.git

# Inside your empty project directory
monk init -s riblits

File Layout:


config.ru
app.rb
helpers/
init.rb
partials.rb
models/
init.rb
user.rb
routes/
init.rb
login.rb
main.rb
views/
layout.haml
login.haml
main.haml

 

config.ru

root = ::File.dirname(__FILE__)
require ::File.join( root, 'app' )
run MyApp.new

 

app.rb

# encoding: utf-8
require 'sinatra'
require 'haml'

class MyApp < Sinatra::Application
enable :sessions

configure :production do
set :haml, { :ugly=>true }
set :clean_trace, true
end

configure :development do
# ...
end

helpers do
include Rack::Utils
alias_method :h, :escape_html
end
end

require_relative 'models/init'
require_relative 'helpers/init'
require_relative 'routes/init'

 

helpers/init.rb

# encoding: utf-8
require_relative 'partials'
MyApp.helpers PartialPartials

require_relative 'nicebytes'
MyApp.helpers NiceBytes

 

helpers/partials.rb

# encoding: utf-8
module PartialPartials
def spoof_request(uri,env_modifications={})
call(env.merge("PATH_INFO" => uri).merge(env_modifications)).last.join
end

def partial( page, variables={} )
haml page, {layout:false}, variables
end
end

 

helpers/nicebytes.rb

# encoding: utf-8
module NiceBytes
K = 2.0**10
M = 2.0**20
G = 2.0**30
T = 2.0**40
def nice_bytes( bytes, max_digits=3 )
value, suffix, precision = case bytes
when 0...K
[ bytes, 'B', 0 ]
else
value, suffix = case bytes
when K...M then [ bytes / K, 'kiB' ]
when M...G then [ bytes / M, 'MiB' ]
when G...T then [ bytes / G, 'GiB' ]
else [ bytes / T, 'TiB' ]
end
used_digits = case value
when 0...10 then 1
when 10...100 then 2
when 100...1000 then 3
else 4
end
leftover_digits = max_digits - used_digits
[ value, suffix, leftover_digits > 0 ? leftover_digits : 0 ]
end
"%.#{precision}f#{suffix}" % value
end
module_function :nice_bytes # Allow NiceBytes.nice_bytes outside of Sinatra
end

 

models/init.rb

# encoding: utf-8
require 'sequel'
DB = Sequel.postgres 'dbname', user:'bduser', password:'dbpass', host:'localhost'
DB << "SET CLIENT_ENCODING TO 'UTF8';"

require_relative 'users'

 

models/user.rb

# encoding: utf-8
class User < Sequel::Model
# ...
end

 

routes/init.rb

# encoding: utf-8
require_relative 'login'
require_relative 'main'

 

routes/login.rb

# encoding: utf-8
class MyApp < Sinatra::Application
get "/login" do
@title = "Login"
haml :login
end

post "/login" do
# Define your own check_login
if user = check_login
session[ :user ] = user.pk
redirect '/'
else
redirect '/login'
end
end

get "/logout" do
session[:user] = session[:pass] = nil
redirect '/'
end
end

 

routes/main.rb

# encoding: utf-8
class MyApp < Sinatra::Application
get "/" do
@title = "Welcome to MyApp"
haml :main
end
end

 

views/layout.haml

!!! XML
!!! 1.1
%html(xmlns="http://www.w3.org/1999/xhtml")
%head
%title= @title
%link(rel="icon" type="image/png" href="/favicon.png")
%meta(http-equiv="X-UA-Compatible" content="IE=8")
%meta(http-equiv="Content-Script-Type" content="text/javascript" )
%meta(http-equiv="Content-Style-Type" content="text/css" )
%meta(http-equiv="Content-Type" content="text/html; charset=utf-8" )
%meta(http-equiv="expires" content="0" )
%meta(name="author" content="MeWho")
%body{id:@action}
%h1= @title
#content= yield


Related Topics



Leave a reply



Submit