class Talkable::Middleware

Public Class Methods

new(app) click to toggle source
# File lib/talkable/middleware.rb, line 6
def initialize(app)
  @app = app
end

Public Instance Methods

call(env) click to toggle source
# File lib/talkable/middleware.rb, line 10
def call(env)
  request = Rack::Request.new(env)
  uuid = talkable_visitor_uuid(request)

  result = Talkable.with_uuid_and_url(uuid, request.url) do
    @app.call(env)
  end

  inject_uuid_in_cookie(uuid, result)
  modify_response_content(result) do |content|
    content = inject_uuid_in_body(uuid, content)
    inject_integration_js_in_head(content)
  end

end

Protected Instance Methods

attachment?(headers) click to toggle source
# File lib/talkable/middleware.rb, line 141
def attachment?(headers)
  content_disposition = headers['Content-Disposition']
  content_disposition && content_disposition.include?('attachment')
end
body_injection_position(content) click to toggle source
# File lib/talkable/middleware.rb, line 124
def body_injection_position(content)
  pattern = /<\s*body[^>]*>/im
  match = pattern.match(content)
  match.end(0) if match
end
collect_content(chunks) click to toggle source
# File lib/talkable/middleware.rb, line 118
def collect_content(chunks)
  ''.tap do |content|
    chunks.each { |chunk| content << chunk.to_s }
  end
end
cookies_expiration() click to toggle source
# File lib/talkable/middleware.rb, line 71
def cookies_expiration
  Time.now + (20 * 365 * 24 * 60 * 60) # 20 years
end
head_injection_position(content) click to toggle source
# File lib/talkable/middleware.rb, line 130
def head_injection_position(content)
  pattern = /<\s*\/\s*head[^>]*>/im
  match = pattern.match(content)
  match.begin(0) if match
end
html?(headers) click to toggle source
# File lib/talkable/middleware.rb, line 136
def html?(headers)
  content_type = headers['Content-Type']
  content_type && content_type.include?('text/html')
end
init_parameters() click to toggle source
# File lib/talkable/middleware.rb, line 99
def init_parameters
  {
    site_id: Talkable.configuration.site_slug,
    server: Talkable.configuration.server,
  }
end
inject_in_content(content, injection, position) click to toggle source
# File lib/talkable/middleware.rb, line 67
def inject_in_content(content, injection, position)
  content[0...position] << injection << content[position..-1]
end
inject_integration_js_in_head(content) click to toggle source
# File lib/talkable/middleware.rb, line 60
def inject_integration_js_in_head(content)
  if injection_index = head_injection_position(content)
    content = inject_in_content(content, integration_content, injection_index)
  end
  content
end
inject_uuid_in_body(uuid, content) click to toggle source
# File lib/talkable/middleware.rb, line 53
def inject_uuid_in_body(uuid, content)
  if injection_index = body_injection_position(content)
    content = inject_in_content(content, sync_uuid_content(uuid), injection_index)
  end
  content
end
integration_content() click to toggle source
# File lib/talkable/middleware.rb, line 86
def integration_content
  integration_init_content + integration_script_content
end
integration_init_content() click to toggle source
# File lib/talkable/middleware.rb, line 90
    def integration_init_content
      %Q{
<script>
  window._talkableq = window._talkableq || [];
  _talkableq.push(['init', #{init_parameters.to_json}]);
</script>
      }
    end
integration_script_content() click to toggle source
# File lib/talkable/middleware.rb, line 106
    def integration_script_content
      src = CGI.escape_html(Talkable.configuration.js_integration_library)
      %Q{
<script src="#{src}" type="text/javascript"></script>
      }
    end
modifiable?(result) click to toggle source
# File lib/talkable/middleware.rb, line 113
def modifiable?(result)
  status, headers = result
  status == 200 && html?(headers) && !attachment?(headers)
end
modify_response_content(result) { |response_content| ... } click to toggle source
# File lib/talkable/middleware.rb, line 36
def modify_response_content(result)
  return result unless modifiable?(result)

  status, header, body = result
  response_content = collect_content(body)
  body.close if body.respond_to?(:close)

  response_content = yield(response_content) if block_given?

  if response_content
    response = Rack::Response.new(response_content, status, header)
    response.finish
  else
    result
  end
end
sync_uuid_content(uuid) click to toggle source
# File lib/talkable/middleware.rb, line 79
    def sync_uuid_content(uuid)
      src = CGI.escape_html(sync_uuid_url(uuid))
      %Q{
<img src="#{src}" style="position:absolute; left:-9999px;" alt="" />
      }
    end
sync_uuid_url(uuid) click to toggle source
# File lib/talkable/middleware.rb, line 75
def sync_uuid_url(uuid)
  Furi.update("#{Talkable.configuration.server}/public/1x1.gif", query: {current_visitor_uuid: uuid})
end
talkable_visitor_uuid(request) click to toggle source
# File lib/talkable/middleware.rb, line 28
def talkable_visitor_uuid(request)
  request.params[UUID] || request.cookies[UUID] || Talkable.find_or_generate_uuid
end