Class: Rack::RSI

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/rsi_version.rb,
lib/rack/rsi.rb

Defined Under Namespace

Classes: Error, RsiRender

Constant Summary collapse

VERSION =
"0.0.2"

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ RSI

Returns a new instance of RSI.



56
57
58
# File 'lib/rack/rsi.rb', line 56

def initialize( app )
  @app = app
end

Instance Method Details

#assemble_response(env) ⇒ Object

Assemble Response



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/rack/rsi.rb', line 65

def assemble_response( env )
  vanilla_env = env.dup
  vanilla_app = @app.dup

  # calling app and env on orignal request
  status, headers, enumerable_body = original_response = @app.call(env)

  rack_rsi_flag = headers.delete('rack.rsi')

  # Assemble Pages if rack_rsi_flag is set and status is 200 ok
  # otherwise return the original response
  return original_response unless rack_rsi_flag && status == 200

  body = ""
  enumerable_body.each do |part|
    body << part
  end

  cache_control_headers = Array( headers.delete( 'Cache-Control' ) || "max-age=0" )

  # Like Varnish supports upto 5 levels of ESI includes recursively
  level = 1
  while( rack_rsi_flag )
    erb = ERB.new( body, 0 )
    renderer = RsiRender.new( vanilla_app, vanilla_env, level )
    body = erb.result( renderer.get_binding )
    renderer.cache_control_headers.inject( cache_control_headers ){ |s,x| s.push( x ) }
    rack_rsi_flag = renderer.rack_rsi?
    level += 1
  end

  # Set ETag for the Request
  headers['ETag'] = Digest::MD5.hexdigest( body )
  headers.delete( 'Last-Modified' )

  # For Assembled Pages Cache-Control to be set as private, with
  # max-age=<minimum max-age of all the requests that are assembled>
  # and should be revalidate on stale. If max-age is not set for even one of the
  # requests then max-age is set to 0.
  min_max_age = cache_control_headers.collect{ |x| x.match(/max-age\s*=\s*(\d+)/).to_a[1].to_i }.min

  headers['Cache-Control'] = "private, max-age=#{min_max_age}, must-revalidate"
  headers.delete( 'Expires' )
  headers['Expires'] = ( Time.now.utc + min_max_age ).strftime("%a, %d %m %Y %T %Z") if min_max_age > 0

  # Create Correct Content-Length
  headers['Content-Length'] = Rack::Utils.bytesize( body ).to_s

  # For now whatever headers is set by the original action would be
  # passed on. Except for Cache-Control, ETag, Expires, Last-Modified
  # Cookies from the original action are passed on.
  [ status, headers, [ body ] ]
end

#call(env) ⇒ Object



60
61
62
# File 'lib/rack/rsi.rb', line 60

def call( env )
  assemble_response( env )
end