Permalink
Browse files

Heroku --> Rhomobile

  • Loading branch information...
1 parent 28fc887 commit 406fa4be41000f84def0a47ae194c2656f86e865 @guilleiguaran guilleiguaran committed Dec 21, 2010
Showing with 146 additions and 10 deletions.
  1. +5 −5 README.md
  2. +2 −2 Rakefile
  3. +3 −3 heroku-nav.gemspec
  4. +136 −0 lib/rhomobile/nav.rb
View
@@ -9,19 +9,19 @@ displaying a customized header for users coming from a single sign-on session.
Use it just like any Rack middleware:
- require 'heroku/nav'
- use Heroku::Nav::Provider
+ require 'rhomobile/nav'
+ use Rhomobile::Nav::Provider
That will fetch the latest header from our API and insert it as the first
-element inside the body tag when the cookie "heroku-nav-data" is defined.
+element inside the body tag when the cookie "rhomobile-nav-data" is defined.
For Rails apps, add it to your Gemfile:
- gem 'heroku-nav', :require => 'heroku/nav'
+ gem 'rhomobile-nav', :require => 'rhomobile/nav'
And add the middleware like:
- config.middleware.use Heroku::Nav::Provider
+ config.middleware.use Rhomobile::Nav::Provider
## Meta #######################################################################
View
@@ -8,10 +8,10 @@ end
begin
require 'jeweler'
Jeweler::Tasks.new do |gemspec|
- gemspec.name = "heroku-nav"
+ gemspec.name = "rhomobile-nav"
gemspec.summary = ""
gemspec.description = ""
- gemspec.homepage = "http://heroku.com"
+ gemspec.homepage = "http://rhomobile.com"
gemspec.authors = ["David Dollar", "Pedro Belo", "Todd Matthews"]
gemspec.email = ["david@heroku.com", "pedro@heroku.com", "todd@heroku.com"]
View
@@ -4,7 +4,7 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
- s.name = %q{heroku-nav}
+ s.name = %q{rhomobile-nav}
s.version = "0.1.19"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
@@ -15,13 +15,13 @@ Gem::Specification.new do |s|
s.files = [
".gitignore",
"Rakefile",
- "heroku-nav.gemspec",
+ "rhomobile-nav.gemspec",
"lib/heroku/nav.rb",
"spec/api_spec.rb",
"spec/base.rb",
"spec/nav_spec.rb"
]
- s.homepage = %q{http://heroku.com}
+ s.homepage = %q{http://rhomobile.com}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.6}
View
@@ -0,0 +1,136 @@
+require 'rest_client'
+require 'json'
+require 'timeout'
+
+module Rhomobile
+ module Nav
+ class Base
+ def initialize(app, options={})
+ @app = app
+ @options = options
+ @options[:except] = [@options[:except]] unless @options[:except].is_a?(Array)
+ @options[:status] ||= [200]
+ refresh
+ end
+
+ def call(env)
+ @status, @headers, @body = @app.call(env)
+ @body.extend(Enumerable)
+ @body = @body.to_a.join
+ insert! if can_insert?(env)
+ [@status, @headers, [@body]]
+ end
+
+ def can_insert?(env)
+ return unless @options[:status].include?(@status)
+ return unless @headers['Content-Type'] =~ /text\/html/ || @headers['content-type'] =~ /text\/html/
+ return if @options[:except].any? { |route| env['PATH_INFO'] =~ route }
+ true
+ end
+
+ def refresh
+ @nav = self.class.fetch
+ end
+
+ class << self
+ def fetch
+ Timeout.timeout(4) do
+ raw = RestClient.get(resource_url, :accept => :json).to_s
+ return JSON.parse(raw)
+ end
+ rescue => e
+ STDERR.puts "Failed to fetch the Heroku #{resource}: #{e.class.name} - #{e.message}"
+ {}
+ end
+
+ def resource
+ name.split('::').last.downcase
+ end
+
+ def resource_url
+ [api_url, '/', resource].join
+ end
+
+ def api_url
+ ENV['API_URL'] || ENV['HEROKU_NAV_URL'] || "http://nav.heroku.com"
+ end
+
+ # for non-rack use
+ def html
+ @@body ||= fetch['html']
+ end
+ end
+ end
+
+ class Header < Base
+ def insert!
+ if @nav['html']
+ @body.gsub!(/(<head>)/i, "\\1<link href='#{self.class.api_url}/header.css' media='all' rel='stylesheet' type='text/css' />")
+ @body.gsub!(/(<body.*?>\s*(<div .*?class=["'].*?container.*?["'].*?>)?)/i, "\\1#{@nav['html']}")
+ @headers['Content-Length'] = @body.length.to_s
+ end
+ end
+ end
+
+ class Footer < Base
+ def insert!
+ if @nav['html']
+ @body.gsub!(/(<head>)/i, "\\1<link href='#{self.class.api_url}/footer.css' media='all' rel='stylesheet' type='text/css' />")
+ @body.gsub!(/(<\/body>)/i, "#{@nav['html']}\\1")
+ @headers['Content-Length'] = @body.length.to_s
+ end
+ end
+ end
+
+ class Internal < Base
+ def self.resource
+ "internal.json"
+ end
+ def insert!
+ if @nav['head']
+ @body.gsub!(/(<head>)/i, "\\1#{@nav['head']}")
+ end
+ if @nav['body']
+ @body.gsub!(/(<\/body>)/i, "#{@nav['body']}\\1")
+ end
+ @headers['Content-Length'] = @body.length.to_s
+ end
+ end
+
+ class Provider < Base
+ class << self
+ def fetch
+ Timeout.timeout(4) do
+ RestClient.get(resource_url).to_s
+ end
+ rescue => e
+ STDERR.puts "Failed to fetch the Heroku #{resource}: #{e.class.name} - #{e.message}"
+ {}
+ end
+
+ def resource_url
+ "#{api_url}/v1/providers/header"
+ end
+
+ # for non-rack use
+ def html
+ @@body ||= fetch
+ end
+ end
+
+ def can_insert?(env)
+ super && env['HTTP_COOKIE'] && env['HTTP_COOKIE'].include?('heroku-nav-data')
+ end
+
+ def insert!
+ if @nav
+ match = @body.match(/(\<body[^\>]*\>)/i)
+ if match && match.size > 0
+ @body.insert(match.end(0), @nav)
+ @headers['Content-Length'] = @body.length.to_s
+ end
+ end
+ end
+ end
+ end
+end

0 comments on commit 406fa4b

Please sign in to comment.