From 7bc41cefa0115067a2e9aab3dbd1924667c46dfe Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Sat, 14 Feb 2009 17:35:34 -0600 Subject: Adding clarity to query string handling in REST calls We previously only handled simple strings as values, but we know handle true and false as booleans, we URI-escape all strings, and we can yaml-encode and then escape arrays of strings. This could get abused a bit, in that we're just yaml-dumping anything that's an array, but it should be pretty safe. Mmmm, should. Signed-off-by: Luke Kanies --- lib/puppet/indirector/rest.rb | 16 +++++++++++++--- lib/puppet/network/http/handler.rb | 15 +++++++++++++++ lib/puppet/network/http/mongrel/rest.rb | 4 +++- lib/puppet/network/http/webrick/rest.rb | 1 + 4 files changed, 32 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb index 5ac25f02d..2d0799286 100644 --- a/lib/puppet/indirector/rest.rb +++ b/lib/puppet/indirector/rest.rb @@ -87,11 +87,21 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus deserialize network(request).put("/#{indirection.name}/", request.instance.render, headers) end - private - # Create the query string, if options are present. def query_string(request) return "" unless request.options and ! request.options.empty? - "?" + request.options.collect { |key, value| "%s=%s" % [key, value] }.join("&") + "?" + request.options.collect do |key, value| + case value + when nil; next + when true, false; value = value.to_s + when String; value = URI.escape(value) + when Symbol; value = URI.escape(value.to_s) + when Array; value = URI.escape(YAML.dump(value)) + else + raise ArgumentError, "HTTP REST queries cannot handle values of type '%s'" % value.class + end + + "%s=%s" % [key, value] + end.join("&") end end diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb index 7af0528eb..9bc94a037 100644 --- a/lib/puppet/network/http/handler.rb +++ b/lib/puppet/network/http/handler.rb @@ -180,4 +180,19 @@ module Puppet::Network::HTTP::Handler def params(request) raise NotImplementedError end + + def decode_params(params) + params.inject({}) do |result, ary| + param, value = ary + value = URI.unescape(value) + if value =~ /^---/ + value = YAML.load(value) + else + value = true if value == "true" + value = false if value == "false" + end + result[param.to_sym] = value + result + end + end end diff --git a/lib/puppet/network/http/mongrel/rest.rb b/lib/puppet/network/http/mongrel/rest.rb index 45d21ea62..04f413937 100644 --- a/lib/puppet/network/http/mongrel/rest.rb +++ b/lib/puppet/network/http/mongrel/rest.rb @@ -23,7 +23,9 @@ class Puppet::Network::HTTP::MongrelREST < Mongrel::HttpHandler # Return the query params for this request. We had to expose this method for # testing purposes. def params(request) - Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"]).merge(client_info(request)) + params = Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"]) + params = decode_params(params) + params.merge(client_info(request)) end # what path was requested? diff --git a/lib/puppet/network/http/webrick/rest.rb b/lib/puppet/network/http/webrick/rest.rb index f06914365..e34f0d2e8 100644 --- a/lib/puppet/network/http/webrick/rest.rb +++ b/lib/puppet/network/http/webrick/rest.rb @@ -13,6 +13,7 @@ class Puppet::Network::HTTP::WEBrickREST < WEBrick::HTTPServlet::AbstractServlet # Retrieve the request parameters, including authentication information. def params(request) result = request.query + result = decode_params(result) result.merge(client_information(request)) end -- cgit