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 2011/02/03 15:11:05 UTC

Support for OPTIONS and HEAD calls in API

Hi,

This patch will add support for querying collections and operation for
basic capabilities like supported HTTP methods, operations and params.
It's implemented in Rabbit, so collections like buckets which are
defined outside Rabbit are not supported by this, but we can add them
manually.

For collections there is OPTIONS and HEAD call where:

* OPTIONS /api/instances
  This will return HTTP header X-Operations-Allowed with list of
  operations defined for this collection (create,index,destroy...)

* HEAD /api/instances
  This will return HTTP header Allow which list all HTTP methods
  supported in collection (GET, HEAD, OPTIONS, POST...)

For each operation is defined OPTIONS call:

* OPTIONS /api/instances/create
  Will return X-Required-Parameters with list of all required parameters for
  this call and X-Optional-Parameters with all optional params.

This business should be usefull for clients to check what methods/params/ops
are defined for collections/operations without actually executing that
operations to check that they are not working/available.

Let me know if you found this usefull or you have some suggestions/hints
for concept/header names...

  -- Michal


Re: Support for OPTIONS and HEAD calls in API

Posted by "marios@redhat.com" <ma...@redhat.com>.
On 05/02/11 02:54, David Lutterkort wrote:
(btw, is there a command line tool that will generate
> OPTIONS requests ? I had to try this with telnet)

behold the awesomeness of curl; the -X flag allows you to set pretty 
much any 'method' you like:

"curl -X OPTIONS --user 'name:password' http://localhost:3001/api ..."

curl manpage online: http://curl.haxx.se/docs/manpage.html


marios

Re: Support for OPTIONS and HEAD calls in API

Posted by Michal Fojtik <mf...@redhat.com>.
Hi,

On Feb 5, 2011, at 1:54 AM, David Lutterkort wrote:

> On Thu, 2011-02-03 at 15:11 +0100, mfojtik@redhat.com wrote:
>> This patch will add support for querying collections and operation for
>> basic capabilities like supported HTTP methods, operations and params.
> 
> Looks good.
> 
>> For collections there is OPTIONS and HEAD call where:
>> 
>> * OPTIONS /api/instances
>>  This will return HTTP header X-Operations-Allowed with list of
>>  operations defined for this collection (create,index,destroy...)
> 
> Shouldn't we also generate an Allow header similar to the one for the
> HEAD request ? (btw, is there a command line tool that will generate
> OPTIONS requests ? I had to try this with telnet)

Yes, I will add HEAD to collection as well.
For testing, you can use 'RestClient' gem (just type 'restclient' on console)
Then: 

RestClient.options('http://localhost:3001/api/instances').headers

Will print HTTP headers. Use '.head' for HEAD ;-)

>> Let me know if you found this usefull or you have some suggestions/hints
>> for concept/header names...
> 
> ACK. Looks good to me.

Thanks for review! I'll push this on Monday.


  -- Michal

Michal Fojtik
Software Engineer, Deltacloud API project
http://www.deltacloud.org
mfojtik@redhat.com



Re: Support for OPTIONS and HEAD calls in API

Posted by David Lutterkort <lu...@redhat.com>.
On Thu, 2011-02-03 at 15:11 +0100, mfojtik@redhat.com wrote:
> This patch will add support for querying collections and operation for
> basic capabilities like supported HTTP methods, operations and params.

Looks good.

> For collections there is OPTIONS and HEAD call where:
> 
> * OPTIONS /api/instances
>   This will return HTTP header X-Operations-Allowed with list of
>   operations defined for this collection (create,index,destroy...)

Shouldn't we also generate an Allow header similar to the one for the
HEAD request ? (btw, is there a command line tool that will generate
OPTIONS requests ? I had to try this with telnet)

> Let me know if you found this usefull or you have some suggestions/hints
> for concept/header names...

ACK. Looks good to me.

David



[PATCH core] Added support for HEAD and OPTIONS for Rabbit

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

---
 server/lib/sinatra/rabbit.rb |   50 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/server/lib/sinatra/rabbit.rb b/server/lib/sinatra/rabbit.rb
index a2b1c3d..75c0789 100644
--- a/server/lib/sinatra/rabbit.rb
+++ b/server/lib/sinatra/rabbit.rb
@@ -36,6 +36,11 @@ module Sinatra
         @description = ""
         instance_eval(&block) if block_given?
         generate_documentation
+        generate_options
+      end
+
+      def http_method
+        @method
       end
 
       def standard?
@@ -58,6 +63,21 @@ module Sinatra
         end
       end
 
+      def generate_options
+        current_operation = self
+        ::Sinatra::Application.options("/api/#{current_operation.collection.name}/#{current_operation.name}") do
+          required_params = current_operation.effective_params(driver).collect do |name, validation| 
+            name.to_s if validation.type.eql?(:required)
+          end.compact.join(',')
+          optional_params = current_operation.effective_params(driver).collect do |name, validation| 
+            name.to_s if validation.type.eql?(:optional)
+          end.compact.join(',')
+          headers 'X-Required-Parameters' => required_params
+          headers 'X-Optional-Parameters' => optional_params
+          [200, '']
+        end
+      end
+
       def control(&block)
         op = self
         @control = Proc.new do
@@ -142,6 +162,8 @@ module Sinatra
         @operations = {}
         instance_eval(&block) if block_given?
         generate_documentation
+        generate_head
+        generate_options
       end
 
       # Set/Return description for collection
@@ -152,6 +174,24 @@ module Sinatra
         @description = text
       end
 
+      def generate_head
+        current_collection = self
+        ::Sinatra::Application.head("/api/#{name}") do
+          methods_allowed = current_collection.operations.collect { |o| o[1].method.to_s.upcase }.uniq.join(',')
+          headers 'Allow' => "HEAD,OPTIONS,#{methods_allowed}"
+          [200, '']
+        end
+      end
+
+      def generate_options
+        current_collection = self
+        ::Sinatra::Application.options("/api/#{name}") do
+          operations_allowed = current_collection.operations.collect { |o| o[0] }.join(',')
+          headers 'X-Operations-Allowed' => operations_allowed
+          [200, '']
+        end
+      end
+
       def generate_documentation
         coll = self
         ::Sinatra::Application.get("/api/docs/#{@name}") do
@@ -288,3 +328,13 @@ class String
           downcase
   end
 end
+
+configure do
+  class << Sinatra::Base
+    def options(path, opts={}, &block)
+      route 'OPTIONS', path, opts, &block
+    end
+  end
+  Sinatra::Delegator.delegate :options
+end
+
-- 
1.7.4