From: Michal Fojtik <[email protected]>

---
 server/lib/sinatra/rack_matrix_params.rb |   86 ++++++++++++++++++++++++++++++
 server/server.rb                         |    4 +-
 server/views/instances/show.xml.haml     |    2 +-
 3 files changed, 90 insertions(+), 2 deletions(-)
 create mode 100644 server/lib/sinatra/rack_matrix_params.rb

diff --git a/server/lib/sinatra/rack_matrix_params.rb 
b/server/lib/sinatra/rack_matrix_params.rb
new file mode 100644
index 0000000..2858abe
--- /dev/null
+++ b/server/lib/sinatra/rack_matrix_params.rb
@@ -0,0 +1,86 @@
+# Copyright (C) 2011  Red Hat, Inc.
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# Methods added to this helper will be available to all templates in the 
application.
+
+module Rack
+
+  require 'cgi'
+
+  class MatrixParams
+    def initialize(app)
+      @app = app
+    end
+
+    # This will allow to use 'matrix' params in requests, like:
+    #
+    # http://example.com/library;section=nw/books;topic=money;binding=hardcover
+    #
+    # Will result in this params matrix:
+    #
+    # => params['library']['section'] = 'nw'
+    # => params['books']['topic'] = 'money'
+    # => params['books']['binding'] = 'hardcover'
+    #
+    # All HTTP methods are supported, in case of POST they will be passed as a
+    # regular <form> parameters.
+    
+    def call(env)
+      # Return if this header is not set properly (Rack::Test case...)
+      return @app.call(env) unless env['REQUEST_URI']
+
+      # Split URI to components and then extract ;var=value pairs
+      uri_components = env['REQUEST_URI'].split('/')
+      matrix_params = {}
+      uri_components.each do |component|
+       sub_components, value = component.split(/\;(\w+)\=/), nil
+       next unless sub_components.first  # Skip subcomponent if it's empty 
(usually /)
+       while param=sub_components.pop do
+         if value
+           matrix_params[sub_components.first] ||= {}
+           matrix_params[sub_components.first].merge!(
+             param => value
+           )
+           value=nil
+           next
+         else
+           value = param
+         end
+       end
+      end
+
+      # If request method is POST, simply include matrix params in form_hash
+      env['rack.request.form_hash'].merge!(matrix_params) if 
env['rack.request.form_hash']
+
+      # For other methods it's a way complicated ;-)
+      if env['REQUEST_METHOD']!='POST' and not matrix_params.keys.empty?
+       # Rewrite current path and query string and strip all matrix params 
from it
+       env['REQUEST_PATH'], env['PATH_INFO'] = 
env['REQUEST_URI'].gsub(/;([^\/]*)/, '').gsub(/\?(.*)$/, '')
+       env['PATH_INFO'] = env['REQUEST_PATH']
+       env['QUERY_STRING'].gsub!(/;([^\/]*)/, '')
+       new_params = matrix_params.collect do |component, params|
+         params.collect { |k,v| "#{component}[#{k}]=#{CGI::escape(v.to_s)}" }
+       end.flatten
+       # Add matrix params as a regular GET params
+       env['QUERY_STRING'] += '&' if not env['QUERY_STRING'].empty?
+       env['QUERY_STRING'] += "#{new_params.join('&')}"
+      end
+      @app.call(env)
+    end
+  end
+
+end
diff --git a/server/server.rb b/server/server.rb
index 2618a9c..7eba0ae 100644
--- a/server/server.rb
+++ b/server/server.rb
@@ -30,15 +30,17 @@ require 'lib/deltacloud/helpers/blob_stream'
 require 'sinatra/rack_driver_select'
 require 'sinatra/rack_runtime'
 require 'sinatra/rack_etag'
+require 'sinatra/rack_matrix_params'
 
 set :version, '0.2.0'
 
 include Deltacloud::Drivers
 set :drivers, Proc.new { driver_config }
 
-use Rack::DriverSelect
 use Rack::ETag
 use Rack::Runtime
+use Rack::MatrixParams
+use Rack::DriverSelect
 
 configure do
   set :raise_errors => false
diff --git a/server/views/instances/show.xml.haml 
b/server/views/instances/show.xml.haml
index ca7e0c6..ec2751a 100644
--- a/server/views/instances/show.xml.haml
+++ b/server/views/instances/show.xml.haml
@@ -22,7 +22,7 @@
       - @instance.actions.compact.each do |instance_action|
         %link{:rel => instance_action, :method => 
instance_action_method(instance_action), :href => 
self.send("#{instance_action}_instance_url", @instance.id)}
       - if driver.respond_to?(:run_on_instance)
-        %link{:rel => 'run', :method => :post, :href => 
run_instance_url(@instance.id)}
+        %link{:rel => 'run', :method => :post, :href => 
"#{run_instance_url(@instance.id)};id=#{@instance.id}"}
   - if @instance.instance_variables.include?("@launch_time")
     %launch_time<
       [email protected]_time
-- 
1.7.4

Reply via email to