On Jul 4, 2:52 pm, Brice Figureau <[email protected]>
wrote:
> The way the format was given to the server was kind of broken when
> we were saving to the server.
> It was using the first member of the Accept header.
> The Accept header is usually reserved for the other side, ie what
> the client will accept when the server will respond.
>
> This patch adds a Content-Type header containing the mime-type of
> the object sent by the client when saving.
>
> Signed-off-by: Brice Figureau <[email protected]>
> ---
> lib/puppet/indirector/rest.rb | 2 +-
> lib/puppet/network/format_handler.rb | 8 +++++++-
> lib/puppet/network/http/handler.rb | 17 ++++++++++++++---
> lib/puppet/network/http/mongrel/rest.rb | 4 ++++
> lib/puppet/network/http/rack/rest.rb | 5 +++++
> lib/puppet/network/http/webrick/rest.rb | 4 ++++
> spec/unit/indirector/rest.rb | 9 ++++++++-
> spec/unit/network/format_handler.rb | 26 ++++++++++++++++++++++++++
> spec/unit/network/http/handler.rb | 26 ++++++++++++++++++--------
> spec/unit/network/http/mongrel/rest.rb | 5 +++++
> spec/unit/network/http/rack/rest.rb | 5 +++++
> spec/unit/network/http/webrick/rest.rb | 5 +++++
> 12 files changed, 102 insertions(+), 14 deletions(-)
>
> diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb
> index 6903f9a..909be9a 100644
> --- a/lib/puppet/indirector/rest.rb
> +++ b/lib/puppet/indirector/rest.rb
> @@ -81,7 +81,7 @@ class Puppet::Indirector::REST <
> Puppet::Indirector::Terminus
>
> def save(request)
> raise ArgumentError, "PUT does not accept options" unless
> request.options.empty?
> - deserialize network(request).put(indirection2uri(request),
> request.instance.render, headers)
> + deserialize network(request).put(indirection2uri(request),
> request.instance.render, headers.merge({ "Content-Type" =>
> request.instance.mime }))
> end
I like the idea of using proper mime types in the Content-Type
headers, Hopefully we can get the server responses to send proper mime
types too.
>
> private
> diff --git a/lib/puppet/network/format_handler.rb
> b/lib/puppet/network/format_handler.rb
> index 0a7e9dc..839fe66 100644
> --- a/lib/puppet/network/format_handler.rb
> +++ b/lib/puppet/network/format_handler.rb
> @@ -23,7 +23,7 @@ module Puppet::Network::FormatHandler
> �...@format = format
> end
>
> - [:intern, :intern_multiple, :render, :render_multiple].each do
> |method|
> + [:intern, :intern_multiple, :render, :render_multiple, :mime].each
> do |method|
> define_method(method) do |*args|
> protect(method, args)
> end
> @@ -123,6 +123,12 @@ module Puppet::Network::FormatHandler
>
> Puppet::Network::FormatHandler.protected_format(format).render(self)
> end
>
> + def mime(format = nil)
> + format ||= self.class.default_format
> +
> + Puppet::Network::FormatHandler.protected_format(format).mime
> + end
> +
> def support_format?(name)
> self.class.support_format?(name)
> end
> diff --git a/lib/puppet/network/http/handler.rb
> b/lib/puppet/network/http/handler.rb
> index c6b809d..0383713 100644
> --- a/lib/puppet/network/http/handler.rb
> +++ b/lib/puppet/network/http/handler.rb
> @@ -17,9 +17,20 @@ module Puppet::Network::HTTP::Handler
> raise NotImplementedError
> end
>
> - # Which format to use when serializing our response. Just picks
> - # the first value in the accept header, at this point.
> + # Retrieve the Content-Type header from the http request.
> + def content_type_header(request)
> + raise NotImplementedError
> + end
> +
> + # Which format to use when serializing our response or interpreting the
> request.
> + # IF the client provided a Content-Type use this, otherwise use the
> Accept header
> + # and just pick the first value.
> def format_to_use(request)
> + if header = content_type_header(request)
> + format = Puppet::Network::FormatHandler.mime(header)
> + return format.name.to_s if format.suitable?
> + end
> +
I'm not sure you should use format_to_use for this purpose because it
is used to determine what format to use for the response. If a client
(or a 3rd party app) sends an Accepts header different than the
Content-Type header and both are suitable?, the client will receive
content that they didn't say they can accept. I think it should be a
parallel method to determine the format to use to decode request
bodies. format_to_use should look at the accept header and the other
method should look at the Content-Type header.
> unless header = accept_header(request)
> raise ArgumentError, "An Accept header must be provided to pick
> the right format"
> end
> @@ -118,7 +129,7 @@ module Puppet::Network::HTTP::Handler
>
> format = format_to_use(request)
>
> - obj = indirection_request.model.convert_from(format_to_use(request),
> data)
> + obj = indirection_request.model.convert_from(format, data)
> result = save_object(indirection_request, obj)
>
> set_content_type(response, "yaml")
> diff --git a/lib/puppet/network/http/mongrel/rest.rb
> b/lib/puppet/network/http/mongrel/rest.rb
> index 369d4c6..6b1fafb 100644
> --- a/lib/puppet/network/http/mongrel/rest.rb
> +++ b/lib/puppet/network/http/mongrel/rest.rb
> @@ -15,6 +15,10 @@ class Puppet::Network::HTTP::MongrelREST <
> Mongrel::HttpHandler
> request.params[ACCEPT_HEADER]
> end
>
> + def content_type_header(request)
> + request.params[Mongrel::Const::CONTENT_TYPE]
> + end
> +
> # which HTTP verb was used in this request
> def http_method(request)
> request.params[Mongrel::Const::REQUEST_METHOD]
> diff --git a/lib/puppet/network/http/rack/rest.rb
> b/lib/puppet/network/http/rack/rest.rb
> index e98bffc..a4d475d 100644
> --- a/lib/puppet/network/http/rack/rest.rb
> +++ b/lib/puppet/network/http/rack/rest.rb
> @@ -28,6 +28,11 @@ class Puppet::Network::HTTP::RackREST <
> Puppet::Network::HTTP::RackHttpHandler
> request.env[HEADER_ACCEPT]
> end
>
> + # Retrieve the accept header from the http request.
> + def content_type_header(request)
> + request.env['HTTP_CONTENT_TYPE']
> + end
> +
> # Return which HTTP verb was used in this request.
> def http_method(request)
> request.request_method
> diff --git a/lib/puppet/network/http/webrick/rest.rb
> b/lib/puppet/network/http/webrick/rest.rb
> index 5f77da8..b27b304 100644
> --- a/lib/puppet/network/http/webrick/rest.rb
> +++ b/lib/puppet/network/http/webrick/rest.rb
> @@ -27,6 +27,10 @@ class Puppet::Network::HTTP::WEBrickREST <
> WEBrick::HTTPServlet::AbstractServlet
> request["accept"]
> end
>
> + def content_type_header(request)
> + request["content-type"]
> + end
> +
> def http_method(request)
> request.request_method
> end
> diff --git a/spec/unit/indirector/rest.rb b/spec/unit/indirector/rest.rb
> index 9f77deb..696af9a 100755
> --- a/spec/unit/indirector/rest.rb
> +++ b/spec/unit/indirector/rest.rb
> @@ -306,7 +306,7 @@ describe Puppet::Indirector::REST do
> �...@connection = stub('mock http connection', :put => @response)
> �[email protected](:network).returns(@connection) # neuter
> the network connection
>
> - �...@instance = stub 'instance', :render => "mydata"
> + �...@instance = stub 'instance', :render => "mydata", :mime =>
> "mime"
> �...@request = Puppet::Indirector::Request.new(:foo, :save, "foo
> bar")
> �[email protected] = @instance
> end
> @@ -350,6 +350,13 @@ describe Puppet::Indirector::REST do
> �[email protected](@request)
> end
>
> + it "should provide a Content-Type header containing the mime-type of
> the sent object" do
> + �[email protected](:put).with { |path, data, args|
> args['Content-Type'] == "mime" }.returns(@response)
> +
> + �[email protected](:mime).returns "mime"
> + �[email protected](@request)
> + end
> +
> it "should deserialize and return the network response" do
> �[email protected](:deserialize).with(@response).returns
> @instance
> �[email protected](@request).should equal(@instance)
> diff --git a/spec/unit/network/format_handler.rb
> b/spec/unit/network/format_handler.rb
> index 54409b9..74ee4f5 100755
> --- a/spec/unit/network/format_handler.rb
> +++ b/spec/unit/network/format_handler.rb
> @@ -202,6 +202,10 @@ describe Puppet::Network::FormatHandler do
> FormatTester.new.should respond_to(:render)
> end
>
> + it "should be able to get a format mime-type" do
> + FormatTester.new.should respond_to(:mime)
> + end
> +
> it "should raise a FormatError when a rendering error is
> encountered" do
> format = stub 'rendering format', :supported? => true
> Puppet::Network::FormatHandler.stubs(:format).with(:foo).returns
> format
> @@ -233,5 +237,27 @@ describe Puppet::Network::FormatHandler do
> format.expects(:render).with(tester)
> tester.render
> end
> +
> + it "should call the format-specific converter when asked for the
> mime-type of a given format" do
> + format = stub 'rendering format', :supported? => true
> +
> + Puppet::Network::FormatHandler.stubs(:format).with(:foo).returns
> format
> +
> + tester = FormatTester.new
> + format.expects(:mime).returns "foo"
> +
> + tester.mime(:foo).should == "foo"
> + end
> +
> + it "should return the default format mime-type if no format is
> provided" do
> + format = stub 'rendering format', :supported? => true
> +
> Puppet::Network::FormatHandler.stubs(:format).with("foo").returns format
> +
> + FormatTester.expects(:default_format).returns "foo"
> + tester = FormatTester.new
> +
> + format.expects(:mime).returns "foo"
> + tester.mime.should == "foo"
> + end
> end
> end
> diff --git a/spec/unit/network/http/handler.rb
> b/spec/unit/network/http/handler.rb
> index 8ef6e00..97ad2d2 100755
> --- a/spec/unit/network/http/handler.rb
> +++ b/spec/unit/network/http/handler.rb
> @@ -57,13 +57,14 @@ describe Puppet::Network::HTTP::Handler do
> # Stub out the interface we require our including classes to
> # implement.
> def stub_server_interface
> - �[email protected](:accept_header ).returns
> "format_one,format_two"
> - �[email protected](:set_content_type).returns "my_result"
> - �[email protected](:set_response ).returns "my_result"
> - �[email protected](:path ).returns
> "/my_handler/my_result"
> - �[email protected](:http_method ).returns("GET")
> - �[email protected](:params ).returns({})
> - �[email protected](:content_type
> ...
>
> read more »
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---