You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by mf...@redhat.com on 2012/08/31 14:48:04 UTC

[PATCH core 1/2] Core: Improved url_for helpers

From: Michal Fojtik <mf...@redhat.com>

* Updated url_for helper code to latest version from github[1]
* Improved handling of matrix parameters
* Added 'url()' Sinatra helper to produce valid links when Deltacloud
  is 'mounted' in another Rack application.

Signed-off-by: Michal fojtik <mf...@redhat.com>
---
 server/Rakefile                                    |    1 +
 server/lib/cimi/helpers.rb                         |    2 +-
 server/lib/deltacloud/helpers.rb                   |    2 +-
 server/lib/deltacloud/helpers/url_helper.rb        |  183 ++++++++++++--------
 .../tests/helpers/sinatra/url_for_helper_test.rb   |   69 ++++++++
 5 files changed, 183 insertions(+), 74 deletions(-)
 create mode 100644 server/tests/helpers/sinatra/url_for_helper_test.rb

diff --git a/server/Rakefile b/server/Rakefile
index 80d45d3..c7cad4b 100644
--- a/server/Rakefile
+++ b/server/Rakefile
@@ -165,6 +165,7 @@ namespace :test do
     t.test_files = FileList[
       'tests/helpers/core_ext/*test.rb',        # Deltacloud extensions (core_ext) and other helpers
       'tests/helpers/rack/*test.rb',            # Rack extensions Deltacloud use
+      'tests/helpers/sinatra/*test.rb',         # Sinatra helpers and extensions Deltacloud use
       'tests/drivers/base/*test.rb',            # Deltacloud drivers API tests
       'tests/drivers/models/*test.rb',          # Deltacloud models tests
       'tests/deltacloud/*test.rb',              # Deltacloud internal API tests
diff --git a/server/lib/cimi/helpers.rb b/server/lib/cimi/helpers.rb
index 2dba3be..93910e4 100644
--- a/server/lib/cimi/helpers.rb
+++ b/server/lib/cimi/helpers.rb
@@ -50,12 +50,12 @@ module CIMI::Collections
 
     helpers Deltacloud::Helpers::Drivers
     helpers Sinatra::AuthHelper
-    helpers Sinatra::UrlForHelper
     helpers Rack::RespondTo::Helpers
     helpers Deltacloud::Helpers::Application
     helpers CIMIHelper
 
     register Rack::RespondTo
+    register Sinatra::UrlFor
 
     enable :xhtml
     enable :dump_errors
diff --git a/server/lib/deltacloud/helpers.rb b/server/lib/deltacloud/helpers.rb
index 6566c59..9ce14bf 100644
--- a/server/lib/deltacloud/helpers.rb
+++ b/server/lib/deltacloud/helpers.rb
@@ -29,11 +29,11 @@ module Deltacloud::Collections
 
     helpers Deltacloud::Helpers::Drivers
     helpers Sinatra::AuthHelper
-    helpers Sinatra::UrlForHelper
     helpers Rack::RespondTo::Helpers
     helpers Deltacloud::Helpers::Application
 
     register Rack::RespondTo
+    register Sinatra::UrlFor
 
     enable :xhtml
     enable :dump_errors
diff --git a/server/lib/deltacloud/helpers/url_helper.rb b/server/lib/deltacloud/helpers/url_helper.rb
index 1b084d4..ff5c910 100644
--- a/server/lib/deltacloud/helpers/url_helper.rb
+++ b/server/lib/deltacloud/helpers/url_helper.rb
@@ -25,91 +25,130 @@
 # USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 module Sinatra
-  module UrlForHelper
+  module UrlFor
 
     require 'uri'
 
-    def method_missing(name, *args)
-      if name.to_s =~ /^([\w\_]+)_url$/
-        if args.size > 0
-          t = $1
-          if t.match(/^(stop|reboot|start|attach|detach)_/)
-            action = $1
-            api_url_for(t.pluralize.split('_').last + '/' + args.first.to_s + '/' + action, :full)
-          elsif t.match(/^(destroy|update)_/)
-            api_url_for(t.pluralize.split('_').last + '/' + args.first.to_s, :full)
-          else
-            api_url_for(t.pluralize, :full) + '/' + "#{args.first}"
+    # FIXME:
+    # This is the list of 'allowable' actions. Everything else is considered
+    # as a collection by the UrlFor:
+    #
+    ACTIONS = [
+      :start, :stop, :new, :run, :reboot, :attach, :detach, :register, :unregister
+    ]
+
+    def self.valid_action?(action)
+      ACTIONS.include?(action.to_sym)
+    end
+
+    def self.registered(app)
+      app.helpers UrlFor::Helper
+      app.class_eval do
+        def method_missing(name, *args)
+          action_list = Sinatra::UrlFor::ACTIONS.join('|')
+          return super unless name =~ %r[^((#{action_list})_)?([\w_]+)_url$]
+          action, resource, options = $2, $3, (args.first || {})
+
+          options = { :id => options } unless options.is_a? Hash
+
+          # instances_url => /instances
+          # instances_url( :format => :xml) => /instances?format=xml
+          #
+          if (action.nil? or (action && action=='create')) and options.empty?
+            return url_for('/%s' % resource, options.reject { |k, v| k == :id })
           end
-        else
-          api_url_for($1, :full)
+
+          # instance_url(:id => 'i-111') => /instances/i-111
+          # instance_url(:id => 'i-123', :format => 'xml') => /instances/i-123?format=xml
+          if action.nil? and options.has_key?(:id)
+            raise TypeError.new("The :id parameter cannot be nil (/#{resource}/nil)") if options[:id].nil?
+            return url_for('/' + [resource, options[:id]].compact.join('/'),
+                    options.reject { |k, v| k == :id })
+          end
+
+          # stop_instance_url(:id => 'i-1234') => /instances/i-123/stop
+          #
+          # NOTE: The resource must be in singular!
+          #
+          if action and options.has_key?(:id)
+            action = nil if ['create', 'destroy'].include? action
+            return url_for('/' + [resource.pluralize, options[:id], action].compact.join('/'),
+                    options.reject { |k, v| k == :id })
+          end
+
+          # create_image_url => /images
+          #
+          if action and action == :create
+            return url_for('/' + resource.pluralize, options.reject { |k,v| l == :id })
+          end
+
+          super
         end
-      else
-        super
       end
     end
 
-    def api_url_for(url_fragment, mode=:path_only)
-      matrix_params = ''
-      if request.params['api']
-        matrix_params += ";provider=%s" % request.params['api']['provider'] if request.params['api']['provider']
-        matrix_params += ";driver=%s" % request.params['api']['driver'] if request.params['api']['driver']
-      end
-      url_fragment = "/#{url_fragment}" unless url_fragment =~ /^\// # There is no need to prefix URI with '/'
-      if mode == :path_only
-        url_for "#{settings.root_url}#{matrix_params}#{url_fragment}", mode
-      else
-        url_for "#{matrix_params}#{url_fragment}", :full
-      end
-    end
+    module Helper
 
-    # Construct a link to +url_fragment+, which should be given relative to
-    # the base of this Sinatra app.  The mode should be either
-    # <code>:path_only</code>, which will generate an absolute path within
-    # the current domain (the default), or <code>:full</code>, which will
-    # include the site name and port number.  (The latter is typically
-    # necessary for links in RSS feeds.)  Example usage:
-    #
-    #   url_for "/"            # Returns "/myapp/"
-    #   url_for "/foo"         # Returns "/myapp/foo"
-    #   url_for "/foo", :full  # Returns "http://example.com/myapp/foo"
-    #--
-    # See README.rdoc for a list of some of the people who helped me clean
-    # up earlier versions of this code.
-    def url_for url_fragment, mode=:path_only
-      case mode
-      when :path_only
-        base = request.script_name.empty? ? Deltacloud.default_frontend.root_url : request.script_name
-      when :full
-        scheme = request.scheme
-        port = request.port
-        request_host = request.host
-        if request.env['HTTP_X_FORWARDED_FOR']
-          scheme = request.env['HTTP_X_FORWARDED_SCHEME'] || scheme
-          port = request.env['HTTP_X_FORWARDED_PORT']
-          request_host = request.env['HTTP_X_FORWARDED_HOST']
+      # Code originaly copied from https://github.com/emk/sinatra-url-for
+      # Copyright 2009 Eric Kidd
+      def url_for(url_fragment, mode=nil, options = nil)
+
+        if mode.is_a? Hash
+          options = mode
+          mode = nil
+        end
+
+        mode ||= :full
+
+        mode = mode.to_sym unless mode.is_a? Symbol
+        optstring = nil
+
+        # Deal with matrix parameters
+        #
+        if request.params['api'] and request.params['api'].is_a? Hash
+          matrix_params = ''
+          if request.params['api']['driver']
+            matrix_params += ';driver=%s' % request.params['api']['driver']
+          end
+          if request.params['api']['provider']
+            matrix_params += ';provider=%s' % request.params['api']['provider']
+          end
+        end
+
+        if options.is_a? Hash
+          optstring = '?' + options.map do |k,v|
+            next if k.nil?
+            "#{k}=#{URI.escape(v.to_s, /[^#{URI::PATTERN::UNRESERVED}]/)}"
+          end.compact.join('&') if !options.empty?
         end
-        if (port.nil? || port == "" ||
-            (scheme == 'http' && port.to_s == '80') ||
-            (scheme == 'https' && port.to_s == '443'))
-          port = ""
+
+        case mode
+        when :path_only
+          base = url request.script_name
+        when :full
+          scheme = request.scheme
+          if (scheme == 'http' && request.port == 80 ||
+              scheme == 'https' && request.port == 443)
+            port = ""
+          else
+            port = ":#{request.port}"
+          end
+          if matrix_params
+            uri_components = url_fragment.split('/')
+            if uri_components.size>1
+              uri_components[1] = uri_components[1] + matrix_params
+              url_fragment = uri_components.join('/')
+            end
+          end
+          base = url(request.script_name).gsub(/\/$/, '')
         else
-          port = ":#{port}"
+          raise TypeError, "Unknown url_for mode #{mode.inspect}"
         end
-        base = "#{scheme}://#{request_host}#{port}#{request.script_name.empty? ? settings.config.root_url : request.script_name}"
-      else
-        raise TypeError, "Unknown url_for mode #{mode}"
-      end
-      uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
-      url_escape = uri_parser.escape(url_fragment)
-      # Don't add the base fragment if url_for gets called more than once
-      # per url or the url_fragment passed in is an absolute url
-      if url_escape.match(/^#{base}/) or url_escape.match(/^http/)
-        url_escape
-      else
-        "#{base}#{url_escape}"
+        "#{base}#{url_fragment}#{optstring}"
       end
+
+      alias_method :api_url_for, :url_for
     end
-  end
 
+  end
 end
diff --git a/server/tests/helpers/sinatra/url_for_helper_test.rb b/server/tests/helpers/sinatra/url_for_helper_test.rb
new file mode 100644
index 0000000..159f657
--- /dev/null
+++ b/server/tests/helpers/sinatra/url_for_helper_test.rb
@@ -0,0 +1,69 @@
+require 'rubygems'
+require 'require_relative' if RUBY_VERSION < '1.9'
+
+require_relative '../../test_helper.rb'
+require_relative '../rack/common.rb'
+require_relative '../../../lib/deltacloud/helpers/url_helper.rb'
+
+class TestURLApp < Sinatra::Base
+  register Sinatra::UrlFor
+  use Rack::MatrixParams
+
+  get '/api/:id' do
+    case params[:id]
+      when '1' then tests_url
+      when '2' then tests_url(:id => '1')
+      when '3' then stop_test_url(:id => '1')
+      when '4' then tests_url(:id => '1', :format => :xml)
+      when '5' then tests_url(:id => nil)
+    end
+  end
+end
+
+describe Sinatra::UrlFor do
+
+  before do
+    def app; TestURLApp; end
+  end
+
+  it 'should return /tests for for test_url' do
+    must_return_for '1', 'http://example.org/tests'
+  end
+
+  it 'should return /tests/1 for test_url(:id => 1)' do
+    must_return_for '2', 'http://example.org/tests/1'
+  end
+
+  it 'should return /tests/1/stop for stop_test_url(:id => 1)' do
+    must_return_for '3', 'http://example.org/tests/1/stop'
+  end
+
+  it 'should return /tests/1?format=xml for stop_test_url(:id => 1, :format => :xml)' do
+    must_return_for '4', 'http://example.org/tests/1?format=xml'
+  end
+
+  it 'should preserve the matrix parameters in URL' do
+    get '/api;driver=mock/1'
+    response_body.must_equal 'http://example.org/tests;driver=mock'
+    get '/api;driver=mock/2'
+    response_body.must_equal 'http://example.org/tests;driver=mock/1'
+    get '/api;driver=mock/3'
+    response_body.must_equal 'http://example.org/tests;driver=mock/1/stop'
+    get '/api;driver=mock/4'
+    response_body.must_equal 'http://example.org/tests;driver=mock/1?format=xml'
+  end
+
+  it 'should raise exception when :id is nil for test_url(:id => nil)' do
+    lambda { get '/api/5' }.must_raise TypeError
+  end
+
+  private
+
+  def must_return_for(url, value)
+    get '/api/%s' % url
+    status.must_equal 200
+    response_body.wont_be_empty
+    response_body.must_equal value
+  end
+
+end
-- 
1.7.10.2


Re: [PATCH core 1/2] Core: Improved url_for helpers

Posted by David Lutterkort <lu...@redhat.com>.
On Fri, 2012-08-31 at 14:48 +0200, mfojtik@redhat.com wrote:
> From: Michal Fojtik <mf...@redhat.com>
> 
> * Updated url_for helper code to latest version from github[1]
> * Improved handling of matrix parameters
> * Added 'url()' Sinatra helper to produce valid links when Deltacloud
>   is 'mounted' in another Rack application.
> 
> Signed-off-by: Michal fojtik <mf...@redhat.com>

These give me a very long list of test failures in test:base; looks like
all the XXX_url helpers are missing. Log attached.

David


[PATCH core 2/2] Core: Replaced api_url_for with url_for

Posted by mf...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>

* The api_url_for does not add any extra value to original
  'url_for' helper. Mixing there two helper in views cause
  confusion.

Signed-off-by: Michal fojtik <mf...@redhat.com>
---
 server/lib/deltacloud/helpers/url_helper.rb             |    1 -
 server/views/api/show.html.haml                         |    2 +-
 server/views/buckets/index.html.haml                    |    2 +-
 server/views/cimi/cloudEntryPoint/index.xml.haml        |    2 +-
 server/views/cimi/collection/index.html.haml            |    6 +++---
 server/views/cimi/collection/response.xml.haml          |    2 +-
 server/views/cimi/error.html.haml                       |    2 +-
 server/views/cimi/layout.html.haml                      |    2 +-
 server/views/cimi/machine_configurations/show.html.haml |    2 +-
 server/views/cimi/machine_configurations/show.xml.haml  |    2 +-
 server/views/cimi/machine_images/show.html.haml         |    2 +-
 server/views/cimi/machine_images/show.xml.haml          |    2 +-
 server/views/cimi/machines/show.html.haml               |    2 +-
 server/views/cimi/machines/show.xml.haml                |    2 +-
 server/views/cimi/volumes/show.html.haml                |    2 +-
 server/views/cimi/volumes/show.xml.haml                 |    2 +-
 server/views/docs/collection.html.haml                  |    2 +-
 server/views/docs/collection.xml.haml                   |    4 ++--
 server/views/docs/index.html.haml                       |    2 +-
 server/views/docs/index.xml.haml                        |    2 +-
 server/views/docs/operation.xml.haml                    |    2 +-
 server/views/error.html.haml                            |    2 +-
 server/views/firewalls/index.html.haml                  |    2 +-
 server/views/firewalls/show.html.haml                   |    2 +-
 server/views/images/show.html.haml                      |    4 ++--
 server/views/instance_states/show.html.haml             |    2 +-
 server/views/instances/run_command.html.haml            |    2 +-
 server/views/instances/show.html.haml                   |    4 ++--
 server/views/keys/index.html.haml                       |    2 +-
 server/views/layout.html.haml                           |    2 +-
 server/views/load_balancers/index.html.haml             |    2 +-
 server/views/load_balancers/show.html.haml              |    6 +++---
 server/views/storage_snapshots/show.html.haml           |    2 +-
 server/views/storage_volumes/attach.html.haml           |    2 +-
 server/views/storage_volumes/index.html.haml            |    2 +-
 server/views/storage_volumes/show.html.haml             |    8 ++++----
 36 files changed, 45 insertions(+), 46 deletions(-)

diff --git a/server/lib/deltacloud/helpers/url_helper.rb b/server/lib/deltacloud/helpers/url_helper.rb
index ff5c910..9ae4139 100644
--- a/server/lib/deltacloud/helpers/url_helper.rb
+++ b/server/lib/deltacloud/helpers/url_helper.rb
@@ -147,7 +147,6 @@ module Sinatra
         "#{base}#{url_fragment}#{optstring}"
       end
 
-      alias_method :api_url_for, :url_for
     end
 
   end
diff --git a/server/views/api/show.html.haml b/server/views/api/show.html.haml
index d315ebb..541c388 100644
--- a/server/views/api/show.html.haml
+++ b/server/views/api/show.html.haml
@@ -5,7 +5,7 @@
   %ul{ :'data-role' => :listview, :'data-inset' => 'true'}
     - supported_collections do |c|
       %li
-        %a{ :href => api_url_for(c.collection_name),  :'data-icon' => "arrow-r"}=c.collection_name.to_s.gsub('_', ' ').titlecase
+        %a{ :href => url_for(c.collection_name),  :'data-icon' => "arrow-r"}=c.collection_name.to_s.gsub('_', ' ').titlecase
 
 
 - unless Deltacloud::Drivers.driver_config.nil?
diff --git a/server/views/buckets/index.html.haml b/server/views/buckets/index.html.haml
index 1510dbb..48dc699 100644
--- a/server/views/buckets/index.html.haml
+++ b/server/views/buckets/index.html.haml
@@ -1,5 +1,5 @@
 =header "Buckets" do
-  %a{ :href => api_url_for('buckets/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new bucket
+  %a{ :href => url_for('buckets/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new bucket
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'a'}
diff --git a/server/views/cimi/cloudEntryPoint/index.xml.haml b/server/views/cimi/cloudEntryPoint/index.xml.haml
index 784b931..cce651b 100644
--- a/server/views/cimi/cloudEntryPoint/index.xml.haml
+++ b/server/views/cimi/cloudEntryPoint/index.xml.haml
@@ -1,6 +1,6 @@
 !!!XML
 %CloudEntryPoint{ :xmlns => CMWG_NAMESPACE }
-  %uri= api_url_for("/cloudEntryPoint")
+  %uri= url_for("/cloudEntryPoint")
   %name cloud entry point
   %description cloud entry point
   %created= Time.new.getutc.to_s
diff --git a/server/views/cimi/collection/index.html.haml b/server/views/cimi/collection/index.html.haml
index 0860f5f..76ea9ba 100644
--- a/server/views/cimi/collection/index.html.haml
+++ b/server/views/cimi/collection/index.html.haml
@@ -2,7 +2,7 @@
 - new_name = new_name.gsub(/[A-Z]/, ' \0')
 %h1 #{new_name.capitalize}
 
-%form{ :action => api_url_for("/collection/" + @dmtfitem["uri"]) }
+%form{ :action => url_for("/collection/" + @dmtfitem["uri"]) }
   %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
   %input{ :name => :xmlRootNode, :type => :hidden, :value => @xml_root_node }/
   %p
@@ -28,7 +28,7 @@
         - iter += 1
         %br
         %label
-          = operation["rel"].capitalize + ":&nbsp;" + api_url_for(operation["href"])
+          = operation["rel"].capitalize + ":&nbsp;" + url_for(operation["href"])
           %input{ :name => "operation_"+iter.to_s, :oper_type => operation["rel"], :type => :hidden, :value => operation["href"] }
   %br
 %p
@@ -42,4 +42,4 @@
     - @dmtf_col_items.map do |template|
       %tr
         %td
-          %a{ :href => template["href"] }= template["name"]
\ No newline at end of file
+          %a{ :href => template["href"] }= template["name"]
diff --git a/server/views/cimi/collection/response.xml.haml b/server/views/cimi/collection/response.xml.haml
index ad892d7..0b8eb7a 100644
--- a/server/views/cimi/collection/response.xml.haml
+++ b/server/views/cimi/collection/response.xml.haml
@@ -1,3 +1,3 @@
 !!!XML
 %ReturnCode{ :xmlns => CMWG_NAMESPACE }
-  %Status= "Success"
\ No newline at end of file
+  %Status= "Success"
diff --git a/server/views/cimi/error.html.haml b/server/views/cimi/error.html.haml
index 5a9bb59..942393c 100644
--- a/server/views/cimi/error.html.haml
+++ b/server/views/cimi/error.html.haml
@@ -28,4 +28,4 @@
         #copyright
           Copyright 2009-2011
           %a{:href => 'http://incubator.apache.org/deltacloud/'} The Apache Software Foundation
-          and individual contributors.
\ No newline at end of file
+          and individual contributors.
diff --git a/server/views/cimi/layout.html.haml b/server/views/cimi/layout.html.haml
index 2673453..7c3b754 100644
--- a/server/views/cimi/layout.html.haml
+++ b/server/views/cimi/layout.html.haml
@@ -29,4 +29,4 @@
         #copyright
           Copyright 2009-2011
           %a{:href => 'http://incubator.apache.org/deltacloud/'} The Apache Software Foundation
-          and individual contributors.
\ No newline at end of file
+          and individual contributors.
diff --git a/server/views/cimi/machine_configurations/show.html.haml b/server/views/cimi/machine_configurations/show.html.haml
index 38dc867..c59242e 100644
--- a/server/views/cimi/machine_configurations/show.html.haml
+++ b/server/views/cimi/machine_configurations/show.html.haml
@@ -156,4 +156,4 @@
     })
 
     cellRightBut.appendChild(er);
-  }
\ No newline at end of file
+  }
diff --git a/server/views/cimi/machine_configurations/show.xml.haml b/server/views/cimi/machine_configurations/show.xml.haml
index c337fe1..dbcfe78 100644
--- a/server/views/cimi/machine_configurations/show.xml.haml
+++ b/server/views/cimi/machine_configurations/show.xml.haml
@@ -24,4 +24,4 @@
         %capacity{ :quantity => disk["capacity"]["quantity"], :units => disk["capacity"]["units"] }
         %guestInterface= disk["guestInterface"]
   %operation{ :rel => "edit", :href => machine_configurations_url + "/" + @dmtfitem["uri"] }
-  %operation{ :rel => "delete", :href => machine_configurations_url + "/" + @dmtfitem["uri"] }
\ No newline at end of file
+  %operation{ :rel => "delete", :href => machine_configurations_url + "/" + @dmtfitem["uri"] }
diff --git a/server/views/cimi/machine_images/show.html.haml b/server/views/cimi/machine_images/show.html.haml
index 1c3a28e..202291e 100644
--- a/server/views/cimi/machine_images/show.html.haml
+++ b/server/views/cimi/machine_images/show.html.haml
@@ -76,4 +76,4 @@
     xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
 
     return xmlData;
-  }
\ No newline at end of file
+  }
diff --git a/server/views/cimi/machine_images/show.xml.haml b/server/views/cimi/machine_images/show.xml.haml
index a00713c..3d55ebf 100644
--- a/server/views/cimi/machine_images/show.xml.haml
+++ b/server/views/cimi/machine_images/show.xml.haml
@@ -14,4 +14,4 @@
       %property{ :name => key}=value["content"]
   %imageLocation{ :href => @dmtfitem["imageLocation"]}
   %operation{ :rel => "edit", :href => machine_images_url + "/" + @dmtfitem["uri"] }
-  %operation{ :rel => "delete", :href => machine_images_url + "/" + @dmtfitem["uri"] }
\ No newline at end of file
+  %operation{ :rel => "delete", :href => machine_images_url + "/" + @dmtfitem["uri"] }
diff --git a/server/views/cimi/machines/show.html.haml b/server/views/cimi/machines/show.html.haml
index c29ddff..569caeb 100644
--- a/server/views/cimi/machines/show.html.haml
+++ b/server/views/cimi/machines/show.html.haml
@@ -174,4 +174,4 @@
 
     cellRightBut.appendChild(er);
 
-  }
\ No newline at end of file
+  }
diff --git a/server/views/cimi/machines/show.xml.haml b/server/views/cimi/machines/show.xml.haml
index c699b19..653b51f 100644
--- a/server/views/cimi/machines/show.xml.haml
+++ b/server/views/cimi/machines/show.xml.haml
@@ -25,4 +25,4 @@
         %capacity{ :quantity => disk["capacity"]["quantity"], :units => disk["capacity"]["units"] }
         %guestInterface= disk["guestInterface"]
   %operation{ :rel => "edit", :href => machines_url + "/" + @dmtfitem["uri"] }
-  %operation{ :rel => "delete", :href => machines_url + "/" + @dmtfitem["uri"] }
\ No newline at end of file
+  %operation{ :rel => "delete", :href => machines_url + "/" + @dmtfitem["uri"] }
diff --git a/server/views/cimi/volumes/show.html.haml b/server/views/cimi/volumes/show.html.haml
index 0e7b20b..c91c540 100644
--- a/server/views/cimi/volumes/show.html.haml
+++ b/server/views/cimi/volumes/show.html.haml
@@ -65,4 +65,4 @@
     xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
 
     return xmlData;
-  }
\ No newline at end of file
+  }
diff --git a/server/views/cimi/volumes/show.xml.haml b/server/views/cimi/volumes/show.xml.haml
index 30ef2c2..32f48af 100644
--- a/server/views/cimi/volumes/show.xml.haml
+++ b/server/views/cimi/volumes/show.xml.haml
@@ -14,4 +14,4 @@
       %property{ :name => key}=value["content"]
   %capacity{ :quantity => @dmtfitem["capacity"]["quantity"], :units => @dmtfitem["capacity"]["units"]}
   %operation{ :rel => "edit", :href => volumes_url + "/" + @dmtfitem["uri"] }
-  %operation{ :rel => "delete", :href => volumes_url + "/" + @dmtfitem["uri"] }
\ No newline at end of file
+  %operation{ :rel => "delete", :href => volumes_url + "/" + @dmtfitem["uri"] }
diff --git a/server/views/docs/collection.html.haml b/server/views/docs/collection.html.haml
index 537f52c..7485b60 100644
--- a/server/views/docs/collection.html.haml
+++ b/server/views/docs/collection.html.haml
@@ -13,7 +13,7 @@
       %h3 Operations:
     - @operations.keys.sort_by { |k| k.to_s }.each do |operation|
       %li{ :'data-role' => 'list-divider'}
-        %a{:href => api_url_for("docs/#{@collection.name.to_s}/#{operation}"), :'data-ajax' => 'false'} #{operation}
+        %a{:href => url_for("docs/#{@collection.name.to_s}/#{operation}"), :'data-ajax' => 'false'} #{operation}
       %li
         %br
         %p=@operations[operation].description
diff --git a/server/views/docs/collection.xml.haml b/server/views/docs/collection.xml.haml
index 8525f45..4359901 100644
--- a/server/views/docs/collection.xml.haml
+++ b/server/views/docs/collection.xml.haml
@@ -1,9 +1,9 @@
 %docs{:status => "unsupported"}
-  %collection{:url => api_url_for("docs/#{@collection.name}"), :name => "#{@collection.name}"}
+  %collection{:url => url_for("docs/#{@collection.name}"), :name => "#{@collection.name}"}
     %description #{@collection.description}
     %operations
       - @operations.keys.sort_by { |k| k.to_s }.each do |operation|
-        %operation{:url => api_url_for("#{@collection.name.to_s}"), :name => "#{operation}", :href => api_url_for("#{@operations[operation].path}"), :method => "#{@operations[operation].method}"}
+        %operation{:url => url_for("#{@collection.name.to_s}"), :name => "#{operation}", :href => url_for("#{@operations[operation].path}"), :method => "#{@operations[operation].method}"}
           %description #{@operations[operation].description}
           - @operations[operation].each_param do |param|
             %parameter{:name => "#{param.name}", :type => "#{param.type}"}
diff --git a/server/views/docs/index.html.haml b/server/views/docs/index.html.haml
index c3912bd..742e03f 100644
--- a/server/views/docs/index.html.haml
+++ b/server/views/docs/index.html.haml
@@ -5,7 +5,7 @@
   %ul{ :'data-role' => :listview, :'data-inset' => 'true'}
     - collections.keys.sort_by { |k| k.to_s }.each do |collection|
       %li
-        %a{:href => api_url_for("docs/#{collection}"), :'data-ajax' => 'false'}
+        %a{:href => url_for("docs/#{collection}"), :'data-ajax' => 'false'}
           %h3=collection.to_s.capitalize.tr('_', ' ')
           %p=collections[collection].description
 
diff --git a/server/views/docs/index.xml.haml b/server/views/docs/index.xml.haml
index c953c33..18c9f7b 100644
--- a/server/views/docs/index.xml.haml
+++ b/server/views/docs/index.xml.haml
@@ -1,5 +1,5 @@
 %docs{:status => "unsupported"}
   - collections.keys.sort_by { |k| k.to_s }.each do |collection|
-    %collection{:url => api_url_for("docs/#{collection}")}
+    %collection{:url => url_for("docs/#{collection}")}
       %name #{collection}
       %description  #{collections[collection].description}
diff --git a/server/views/docs/operation.xml.haml b/server/views/docs/operation.xml.haml
index fcc9c59..3faa5e5 100644
--- a/server/views/docs/operation.xml.haml
+++ b/server/views/docs/operation.xml.haml
@@ -1,5 +1,5 @@
 %docs{:status => "unsupported"}
-  %operation{:url => api_url_for("docs/#{@collection.name.to_s}"), :name => "#{@operation.name.to_s}", :href => url_for("#{@operation.path}"), :method => "#{@operation.method}"}
+  %operation{:url => url_for("docs/#{@collection.name.to_s}"), :name => "#{@operation.name.to_s}", :href => url_for("#{@operation.path}"), :method => "#{@operation.method}"}
     %description #{@operation.description}
     - @operation.each_param do |param|
       %parameter{:name => "#{param.name}", :type => "#{param.type}"}
diff --git a/server/views/error.html.haml b/server/views/error.html.haml
index 92897e1..220a44a 100644
--- a/server/views/error.html.haml
+++ b/server/views/error.html.haml
@@ -26,7 +26,7 @@
         %div{ 'data-role' => :navbar}
           %ul
             %li
-              %a{ :'data-icon' => 'home', :href => api_url_for(''), :'data-ajax' => 'false'} Home
+              %a{ :'data-icon' => 'home', :href => url_for(''), :'data-ajax' => 'false'} Home
             %li=link_to_format(:xml)
             %li=link_to_format(:json)
         %div{ 'data-role' => :header, 'data-theme' => 'a' }
diff --git a/server/views/firewalls/index.html.haml b/server/views/firewalls/index.html.haml
index 403f21f..f497b59 100644
--- a/server/views/firewalls/index.html.haml
+++ b/server/views/firewalls/index.html.haml
@@ -1,5 +1,5 @@
 =header "Firewalls" do
-  %a{ :href => api_url_for('firewalls/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new firewall
+  %a{ :href => url_for('firewalls/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new firewall
 =subheader "#{Thread::current[:provider] || ENV['API_PROVIDER'] || 'default'}"
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
diff --git a/server/views/firewalls/show.html.haml b/server/views/firewalls/show.html.haml
index 0fdea19..c2fd5d0 100644
--- a/server/views/firewalls/show.html.haml
+++ b/server/views/firewalls/show.html.haml
@@ -18,7 +18,7 @@
         =link_to_action "Destroy", destroy_firewall_url(@firewall.id), :delete
 
 =header "Rules", :back => 'false' do
-  %a{ :href => api_url_for("firewalls/#{@firewall.id}/new_rule"), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right', :'data-ajax' => 'false'} Add new rule
+  %a{ :href => url_for("firewalls/#{@firewall.id}/new_rule"), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right', :'data-ajax' => 'false'} Add new rule
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   - @firewall.rules.each do |rule|
diff --git a/server/views/images/show.html.haml b/server/views/images/show.html.haml
index c166e87..6030a47 100644
--- a/server/views/images/show.html.haml
+++ b/server/views/images/show.html.haml
@@ -25,9 +25,9 @@
       %li
         %div{ :'data-role' => 'controlgroup', :'data-type' => "horizontal" }
           - @image.hardware_profiles.each do |hwp|
-            %a{ :href => api_url_for("hardware_profiles/#{hwp.name}"), :'data-role' => "button", :'data-ajax' => 'false'} #{hwp.name}
+            %a{ :href => url_for("hardware_profiles/#{hwp.name}"), :'data-role' => "button", :'data-ajax' => 'false'} #{hwp.name}
     %li{ :'data-role' => 'list-divider'} Actions
     %li
       %div{ :'data-role' => 'controlgroup', :'data-type' => "horizontal" }
-        %a{ :href => api_url_for("instances/new?image_id=#{@image.id}"), :'data-role' => "button", :'data-ajax' => 'false'} Launch
+        %a{ :href => url_for("instances/new?image_id=#{@image.id}"), :'data-role' => "button", :'data-ajax' => 'false'} Launch
         = link_to_action 'Destroy', destroy_image_url(@image.id), :delete
diff --git a/server/views/instance_states/show.html.haml b/server/views/instance_states/show.html.haml
index 252f249..2a94801 100644
--- a/server/views/instance_states/show.html.haml
+++ b/server/views/instance_states/show.html.haml
@@ -2,7 +2,7 @@
 =subheader "#{driver_symbol}@#{Thread::current[:provider] || ENV['API_PROVIDER'] || 'default'}"
 
 %div{ :'data-role' => :content, :'data-theme' => 'd', :class => 'middle-dialog'}
-  %img{ :src => api_url_for('instance_states?format=png') }
+  %img{ :src => url_for('instance_states?format=png') }
 
   %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-theme' => 'a'}
     - @machine.states.each do |state|
diff --git a/server/views/instances/run_command.html.haml b/server/views/instances/run_command.html.haml
index 73a267a..75c7534 100644
--- a/server/views/instances/run_command.html.haml
+++ b/server/views/instances/run_command.html.haml
@@ -2,7 +2,7 @@
 =subheader "#{@instance.id}"
 
 %div{ :'data-role' => :content, :'data-theme' => 'c', :class => 'middle-dialog'}
-  %form{ :action => api_url_for('/instances/%s/run' % @instance.id), :method => :post }
+  %form{ :action => url_for('/instances/%s/run' % @instance.id), :method => :post }
     %p
       %label{ :for => :cmd } Desired command:
       %input{ :name => :cmd, :value => "", :type => :text}
diff --git a/server/views/instances/show.html.haml b/server/views/instances/show.html.haml
index 9910de4..cc0b92b 100644
--- a/server/views/instances/show.html.haml
+++ b/server/views/instances/show.html.haml
@@ -59,6 +59,6 @@
         - @instance.actions.each do |action|
           =link_to_action action, self.send(:"#{action}_instance_url", @instance.id), instance_action_method(action)
         - if @instance.state=="RUNNING" and driver.respond_to?(:run_on_instance)
-          =link_to_action 'run command', api_url_for('instances/%s/run' % @instance.id), :get
+          =link_to_action 'run command', url_for('instances/%s/run' % @instance.id), :get
         - if @instance.can_create_image?
-          =link_to_action 'Create Image', api_url_for("images/new?instance_id=#{@instance.id}"), :get
+          =link_to_action 'Create Image', url_for("images/new?instance_id=#{@instance.id}"), :get
diff --git a/server/views/keys/index.html.haml b/server/views/keys/index.html.haml
index c7a9f36..248aca7 100644
--- a/server/views/keys/index.html.haml
+++ b/server/views/keys/index.html.haml
@@ -1,5 +1,5 @@
 =header "Keys" do
-  %a{ :href => api_url_for('keys/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new key
+  %a{ :href => url_for('keys/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new key
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'a'}
diff --git a/server/views/layout.html.haml b/server/views/layout.html.haml
index 4806d59..4db3b7f 100644
--- a/server/views/layout.html.haml
+++ b/server/views/layout.html.haml
@@ -18,7 +18,7 @@
         %div{ 'data-role' => :navbar}
           %ul
             %li
-              %a{ :'data-icon' => 'home', :href => "#{api_url_for('').chomp("/")}", :'data-ajax' => 'false'} Home
+              %a{ :'data-icon' => 'home', :href => "#{url_for('').chomp("/")}", :'data-ajax' => 'false'} Home
             %li=link_to_format(:xml)
             %li=link_to_format(:json)
         %div{ 'data-role' => :header, 'data-theme' => 'a' }
diff --git a/server/views/load_balancers/index.html.haml b/server/views/load_balancers/index.html.haml
index 8b730a1..789cd57 100644
--- a/server/views/load_balancers/index.html.haml
+++ b/server/views/load_balancers/index.html.haml
@@ -1,5 +1,5 @@
 =header "Load balancers" do
-  %a{ :href => api_url_for('load_balancers/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new load balancer
+  %a{ :href => url_for('load_balancers/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new load balancer
 =subheader "#{Thread::current[:provider] || ENV['API_PROVIDER'] || 'default'}"
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
diff --git a/server/views/load_balancers/show.html.haml b/server/views/load_balancers/show.html.haml
index cab8961..a1c754d 100644
--- a/server/views/load_balancers/show.html.haml
+++ b/server/views/load_balancers/show.html.haml
@@ -20,16 +20,16 @@
       %li
         %a{ :href => instance_url(instance[:id]), :'data-ajax' => 'false'}
           %h3=instance[:name]
-          =link_to_action "UnRegister", api_url_for("load_balancers/#{@load_balancer.id}/unregister?instance_id=#{instance[:id]}"), :post
+          =link_to_action "UnRegister", url_for("load_balancers/#{@load_balancer.id}/unregister?instance_id=#{instance[:id]}"), :post
     %li{ :'data-role' => 'list-divider'} UnRegistered Instances
     - @unregistered_instances.each do |instance|
       %li
         %a{:href => instance_url(instance[:id]), :'data-ajax' => 'false'}
           %h3=instance[:name]
-          =link_to_action "Register", api_url_for("load_balancers/#{@load_balancer.id}/register?instance_id=#{instance[:id]}"), :post
+          =link_to_action "Register", url_for("load_balancers/#{@load_balancer.id}/register?instance_id=#{instance[:id]}"), :post
     %li{ :'data-role' => 'list-divider'} Actions
     %li
-      =link_to_action "Destroy", api_url_for("load_balancers/#{@load_balancer.id}"), :delete
+      =link_to_action "Destroy", url_for("load_balancers/#{@load_balancer.id}"), :delete
 
   =header "Listeners", :back => 'false'
   %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'd'}
diff --git a/server/views/storage_snapshots/show.html.haml b/server/views/storage_snapshots/show.html.haml
index bc76e3c..069e452 100644
--- a/server/views/storage_snapshots/show.html.haml
+++ b/server/views/storage_snapshots/show.html.haml
@@ -19,4 +19,4 @@
     %li
       %div{ :'data-role' => 'controlgroup', :'data-type' => "horizontal" }
         - if driver.respond_to?(:destroy_storage_snapshot)
-          =link_to_action "Delete", api_url_for("storage_snapshots/#{@storage_snapshot.id}"), :delete
+          =link_to_action "Delete", url_for("storage_snapshots/#{@storage_snapshot.id}"), :delete
diff --git a/server/views/storage_volumes/attach.html.haml b/server/views/storage_volumes/attach.html.haml
index 8c20753..073cc2a 100644
--- a/server/views/storage_volumes/attach.html.haml
+++ b/server/views/storage_volumes/attach.html.haml
@@ -1,6 +1,6 @@
 %h1 Attach storage volume
 
-%form{ :action => api_url_for("storage_volumes/#{params[:id]}/attach"), :method => :post }
+%form{ :action => url_for("storage_volumes/#{params[:id]}/attach"), :method => :post }
   %p
     %label
       Instance ID:
diff --git a/server/views/storage_volumes/index.html.haml b/server/views/storage_volumes/index.html.haml
index ba44b65..2cc8794 100644
--- a/server/views/storage_volumes/index.html.haml
+++ b/server/views/storage_volumes/index.html.haml
@@ -1,5 +1,5 @@
 =header "Storage volumes" do
-  %a{ :href => api_url_for('storage_volumes/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new volume
+  %a{ :href => url_for('storage_volumes/new'), :'data-icon' => :plus, :'data-role' => :button, :class => 'ui-btn-right'} Create new volume
 
 %div{ :'data-role' => :content, :'data-theme' => 'c'}
   %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'a'}
diff --git a/server/views/storage_volumes/show.html.haml b/server/views/storage_volumes/show.html.haml
index 9a9da37..eddf5a9 100644
--- a/server/views/storage_volumes/show.html.haml
+++ b/server/views/storage_volumes/show.html.haml
@@ -35,9 +35,9 @@
     %li
       %div{ :'data-role' => 'controlgroup', :'data-type' => "horizontal" }
         - if ["AVAILABLE", "IN-USE"].include?(@storage_volume.state)
-          =link_to_action "Snapshot", api_url_for("storage_snapshots/new?volume_id=#{@storage_volume.id}"), :get
+          =link_to_action "Snapshot", url_for("storage_snapshots/new?volume_id=#{@storage_volume.id}"), :get
           - unless @storage_volume.instance_id
-            =link_to_action "Delete", api_url_for("storage_volumes/#{@storage_volume.id}"), :delete
-            =link_to_action "Attach", api_url_for("storage_volumes/#{@storage_volume.id}/attach_instance"), :get
+            =link_to_action "Delete", url_for("storage_volumes/#{@storage_volume.id}"), :delete
+            =link_to_action "Attach", url_for("storage_volumes/#{@storage_volume.id}/attach_instance"), :get
           - if @storage_volume.instance_id
-            =link_to_action "Detach", api_url_for("storage_volumes/#{@storage_volume.id}/detach"), :post
+            =link_to_action "Detach", url_for("storage_volumes/#{@storage_volume.id}/detach"), :post
-- 
1.7.10.2