[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, experimental, updated. debian/2.6.8-1-844-g7ec39d5

Nick Lewis nick at puppetlabs.com
Tue May 10 08:13:30 UTC 2011


The following commit has been merged in the experimental branch:
commit 46721411066926aff3a7d5bb6470d3b8aec1b47d
Author: Nick Lewis <nick at puppetlabs.com>
Date:   Tue Apr 12 17:08:36 2011 -0700

    (#6117) Add POST support to indirector requests
    
    POST with a singular indirection is turned into a find in the indirector.
    
    When making a large find request from a REST terminus, POST is used, and for
    small requests, GET is used for backward compatibility.
    
    Paired-With: Jesse Wolfe

diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb
index e50dc68..0d39972 100644
--- a/lib/puppet/indirector/rest.rb
+++ b/lib/puppet/indirector/rest.rb
@@ -72,7 +72,17 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
   end
 
   def find(request)
-    return nil unless result = deserialize(network(request).get(indirection2uri(request), headers))
+    uri, body = request_to_uri_and_body(request)
+    uri_with_query_string = "#{uri}?#{body}"
+    http_connection = network(request)
+    # WEBrick in Ruby 1.9.1 only supports up to 1024 character lines in an HTTP request
+    # http://redmine.ruby-lang.org/issues/show/3991
+    response = if "GET #{uri_with_query_string} HTTP/1.1\r\n".length > 1024
+      http_connection.post(uri, body, headers)
+    else
+      http_connection.get(uri_with_query_string, headers)
+    end
+    result = deserialize response
     result.name = request.key if result.respond_to?(:name=)
     result
   end
diff --git a/lib/puppet/network/http/api/v1.rb b/lib/puppet/network/http/api/v1.rb
index 5fe1439..61307f0 100644
--- a/lib/puppet/network/http/api/v1.rb
+++ b/lib/puppet/network/http/api/v1.rb
@@ -8,6 +8,9 @@ module Puppet::Network::HTTP::API::V1
       :plural => :search,
       :singular => :find
     },
+    "POST" => {
+      :singular => :find,
+    },
     "PUT" => {
       :singular => :save
     },
@@ -41,6 +44,11 @@ module Puppet::Network::HTTP::API::V1
     "/#{request.environment.to_s}/#{indirection}/#{request.escaped_key}#{request.query_string}"
   end
 
+  def request_to_uri_and_body(request)
+    indirection = request.method == :search ? pluralize(request.indirection_name.to_s) : request.indirection_name.to_s
+    ["/#{request.environment.to_s}/#{indirection}/#{request.escaped_key}", request.query_string.sub(/^\?/,'')]
+  end
+
   def indirection_method(http_method, indirection)
     raise ArgumentError, "No support for http method #{http_method}" unless METHOD_MAP[http_method]
 
diff --git a/spec/unit/indirector/rest_spec.rb b/spec/unit/indirector/rest_spec.rb
index d9c3068..29d00f1 100755
--- a/spec/unit/indirector/rest_spec.rb
+++ b/spec/unit/indirector/rest_spec.rb
@@ -224,13 +224,32 @@ describe Puppet::Indirector::REST do
       @searcher.stubs(:network).returns(@connection)    # neuter the network connection
 
       # Use a key with spaces, so we can test escaping
-      @request = Puppet::Indirector::Request.new(:foo, :find, "foo bar")
+      @request = Puppet::Indirector::Request.new(:foo, :find, "foo bar", :environment => "myenv")
     end
 
-    it "should call the GET http method on a network connection" do
-      @searcher.expects(:network).returns @connection
-      @connection.expects(:get).returns @response
-      @searcher.find(@request)
+    describe "with a large body" do
+      it "should use the POST http method" do
+        params = {}
+        'aa'.upto('zz') do |s|
+          params[s] = 'foo'
+        end
+
+        @request = Puppet::Indirector::Request.new(:foo, :find, "foo bar", params.merge(:environment => "myenv"))
+
+        @connection.expects(:post).with do |uri, body|
+          uri == "/myenv/foo/foo%20bar" and body.split("&").sort == params.map {|key,value| "#{key}=#{value}"}.sort
+        end.returns(@response)
+
+        @searcher.find(@request)
+      end
+    end
+
+    describe "with a small body" do
+      it "should use the GET http method" do
+        @searcher.expects(:network).returns @connection
+        @connection.expects(:get).returns @response
+        @searcher.find(@request)
+      end
     end
 
     it "should deserialize and return the http response, setting name" do
@@ -252,10 +271,8 @@ describe Puppet::Indirector::REST do
       @searcher.find(@request).should == instance
     end
 
-
     it "should use the URI generated by the Handler module" do
-      @searcher.expects(:indirection2uri).with(@request).returns "/my/uri"
-      @connection.expects(:get).with { |path, args| path == "/my/uri" }.returns(@response)
+      @connection.expects(:get).with { |path, args| path == "/myenv/foo/foo%20bar?" }.returns(@response)
       @searcher.find(@request)
     end
 
diff --git a/spec/unit/network/http/api/v1_spec.rb b/spec/unit/network/http/api/v1_spec.rb
index 3da8cbf..d16ff12 100755
--- a/spec/unit/network/http/api/v1_spec.rb
+++ b/spec/unit/network/http/api/v1_spec.rb
@@ -68,6 +68,10 @@ describe Puppet::Network::HTTP::API::V1 do
       @tester.uri2indirection("GET", "/env/foo/bar", {})[1].should == :find
     end
 
+    it "should choose 'find' as the indirection method if the http method is a POST and the indirection name is singular" do
+      @tester.uri2indirection("POST", "/env/foo/bar", {})[1].should == :find
+    end
+
     it "should choose 'head' as the indirection method if the http method is a HEAD and the indirection name is singular" do
       @tester.uri2indirection("HEAD", "/env/foo/bar", {})[1].should == :head
     end
@@ -164,4 +168,26 @@ describe Puppet::Network::HTTP::API::V1 do
     end
   end
 
+  describe "when converting a request into a URI with body" do
+    before :each do
+      @request = Puppet::Indirector::Request.new(:foo, :find, "with spaces", :foo => :bar, :environment => "myenv")
+    end
+
+    it "should use the environment as the first field of the URI" do
+      @tester.request_to_uri_and_body(@request).first.split("/")[1].should == "myenv"
+    end
+
+    it "should use the indirection as the second field of the URI" do
+      @tester.request_to_uri_and_body(@request).first.split("/")[2].should == "foo"
+    end
+
+    it "should use the escaped key as the remainder of the URI" do
+      escaped = URI.escape("with spaces")
+      @tester.request_to_uri_and_body(@request).first.split("/")[3].sub(/\?.+/, '').should == escaped
+    end
+
+    it "should return the URI and body separately" do
+      @tester.request_to_uri_and_body(@request).should == ["/myenv/foo/with%20spaces", "foo=bar"]
+    end
+  end
 end

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list